Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(2)
Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(2)
上一篇里介绍了Color-Coded Picking的思路和最基本的实现。在处理GL_POINTS时已经没有问题,但是处理GL_LINES、GL_TRIANGLES等时会遇到同一图元的各个顶点颜色不同的问题,这就不能正确拾取了,本篇来解决这个问题。
对于GL_LINES,可以用 int objectID = gl_VertexID / 2; 来使得每个线段图元的两个顶点颜色分别相同;对于GL_TRIANGLES,则用 int objectID = gl_VertexID / 3; 。但是这个方法无法应用到存在共享顶点的GL_LINE_STRIP、GL_TRIANGLE_STRIP、GL_LINE_LOOP等情况。所以要另辟蹊径。
ShadeMode
首先介绍一下glShadeMode()这个函数。就是靠它才解决了本文的问题。
glShadeMode()
在(https://www.opengl.org/sdk/docs/man2/xhtml/glShadeModel.xml)有它的专业解释,里面有这样一张表格。
Primitive Type of Polygon i |
Vertex |
Single polygon ( i == 1 ) |
1 |
Triangle strip |
i + 2 |
Triangle fan |
i + 2 |
Independent triangle |
3 × i |
Quad strip |
2 × i + 2 |
Independent quad |
4 × i |
这个表格的意思是:在 glShadeMode(GL_FLAT); 状态下,在绘制某种图元时,其颜色由第i个顶点的颜色决定。(其实就是由定义一个图元的最后一个顶点的颜色决定)
单看表格难以理解,用下面的Demo进行说明。
这个Demo绘制了8个顶点,其位置和颜色如下(同上图左侧所示)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 gl.Color(0, 0, 0); 2 gl.Vertex(0, 0); 3 4 gl.Color(1f, 0, 0); 5 gl.Vertex(0, 1); 6 7 gl.Color(0, 1f, 0); 8 gl.Vertex(1, 0); 9 10 gl.Color(1f, 1f, 0); 11 gl.Vertex(1, 1); 12 13 gl.Color(0, 0, 1f); 14 gl.Vertex(2, 0); 15 16 gl.Color(1f, 0, 1f); 17 gl.Vertex(2, 1); 18 19 gl.Color(0, 1f, 1f); 20 gl.Vertex(3, 0); 21 22 gl.Color(1f, 1f, 1f); 23 gl.Vertex(3, 1);
下面分别看一下在 glShadeMode(GL_SMOOTH); 和 glShadeMode(GL_FLAT); 模式下,用这个8个顶点绘制各种图元的情况。
这是GL_SMOOTH 模式下的GL_LINE_STRIP。
这是GL_FLAT模式下的GL_LINE_STRIP。
这是GL_SMOOTH 模式下的GL_TRIANGLES。
这是GL_FLAT 模式下的GL_TRIANGLES。
这是GL_SMOOTH 模式下的GL_TRIANGLE_STRIP。
这是GL_FLAT模式下的GL_TRIANGLE_STRIP。
这是GL_SMOOTH 模式下的GL_QUAD_STRIP。
这是GL_FLAT 模式下的GL_QUAD_STRIP。
您可以点此下载此Demo慢慢对比。
GL_FLAT的作用
通过上面一节的观察可以看到,GL_FLAT模式下,各种类型的图元的颜色都是由绘制它的最后一个顶点的颜色给出的。
这么绝妙的颜色分配方案简直就是为了解决本文的问题而设计的。
我们只需在做Picking的绘制时,在GL_FLAT状态下绘制图元,就可以用glReadPixel()获取到应拾取的图元的最后一个顶点的编号。根据上一节的表格,很容易推算出此编号代表的图元。
'flat' in GLSL
不过这又带来一个小问题:glShadeMode();在使用Shader+VBO时是无效的。不过Modern OpenGL必然要有能代替它的功能:GLSL里的flat关键字。给in/out变量附加一个flat,就相当于Legacy OpenGL里调用了glShadeMode(GL_FLAT);
flat out vec4 pass_Color; // glShadeMode(GL_FLAT); in legacy opengl.
flat in vec4 pass_Color; // glShadeMode(GL_FLAT); in legacy opengl.
这也是本文与上一篇的程序中唯一的区别。
未完待续
拾取一个VBO里的单个图元的问题已经彻底解决了。那么来看下一个问题:一个场景里可能会有多个VBO,此时每个VBO的gl_VertexID都是从0开始的,那么如何区分不同VBO里的图元呢?我们下回分解。
相关文章
- 大文件上传和断点续传_文件断点续传实现的思路
- 腾讯面试官曰Mysql架构的内部模块索引原理及性能优化思路谁会?
- Pytest测试框架一键动态切换测试环境实现思路及方案
- 从零开发一款相机APP 第十二篇:相机水印实现思路
- 2023美赛Y题二手帆船价格--成品论文、思路、数据、代码
- 手机号码归属地 API 实现个性化推荐的思路分析
- 谈谈SQL慢查询的解决思路详解数据库
- 解锁Linux启动分区的思路(linux启动分区)
- C语言除法算法和取模运算的实现(多种算法,多种思路)
- ASP.NET 大文件下载的实现思路及代码
- 学习Oracle树查询的语法思路(oracle树查询的语法)
- 为radio类型的INPUT添加客户端脚本(附加实现JS来禁用onClick事件思路代码)
- javascript淡入淡出效果的实现思路
- ajaxphp传递和接收变量实现思路及代码
- 读取XML并绑定至RadioButtonList实现思路及演示动画
- JS判断不同分辨率调用不同的CSS样式文件实现思路及测试代码
- Repeater控件动态变更列(Header,Item和Foot)信息实现思路
- 数据库中两张表之间的数据同步增加、删除与更新实现思路
- js将long日期格式转换为标准日期格式实现思路
- 50行代码实现贪吃蛇(具体思路及代码)
- PHP登录记住密码实现思路
- .NET调用控制台下生成的exe文件,传参及获取返回参数的思路及代码
- ASP.NET在下载文件时对其重命名的思路及实现方法
- 复选框全选与全不选操作实现思路
- jquery监听div内容的变化具体实现思路
- 使用python获取CPU和内存信息的思路与实现(linux系统)
- jQuery拖拽div实现思路
- jQuery多项选项卡的实现思路附样式及代码