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 / ; 来使得每个线段图元的两个顶点颜色分别相同;对于GL_TRIANGLES,则用 int objectID = gl_VertexID / ; 。但是这个方法无法应用到存在共享顶点的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个顶点,其位置和颜色如下(同上图左侧所示)
gl.Color(, , );
gl.Vertex(, ); gl.Color(1f, , );
gl.Vertex(, ); gl.Color(, 1f, );
gl.Vertex(, ); gl.Color(1f, 1f, );
gl.Vertex(, ); gl.Color(, , 1f);
gl.Vertex(, ); gl.Color(1f, , 1f);
gl.Vertex(, ); gl.Color(, 1f, 1f);
gl.Vertex(, ); gl.Color(1f, 1f, 1f);
gl.Vertex(, );
Demo 模型
下面分别看一下在 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里的图元呢?我们下回分解。
Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(2)的更多相关文章
- Modern OpenGL用Shader拾取VBO内单一图元的思路和实现
Modern OpenGL用Shader拾取VBO内单一图元的思路和实现 什么意思? 拾取 最简单的理解拾取的方式大概是到(http://www.yakergong.net/nehe/course/t ...
- Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(3)
Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(3) 到上一篇为止,拾取一个VBO里的单个图元的问题已经彻底解决了.那么来看下一个问题:一个场景里可能会有多个VBO,此时每个 ...
- [Modern OpenGL系列(四)]在OpenGL中使用Shader
本文已同步发表在CSDN:http://blog.csdn.net/wenxin2011/article/details/51347440 在上一篇文章中已经介绍了OpenGL窗口的创建.本文接着说如 ...
- OpenGL图形渲染管线、VBO、VAO、EBO概念及用例
图形渲染管线(Pipeline) 图形渲染管线指的是对一些原始数据经过一系列的处理变换并最终把这些数据输出到屏幕上的整个过程. 图形渲染管线的整个处理流程可以被划分为几个阶段,上一个阶段的输出数据作为 ...
- OpenGL中的拾取模式( Picking)
1. Opengl中的渲染模式有三种:(1)渲染模式,默认的模式:(2)选择模式, (3)反馈模式.如下 GLint glRenderMode(GLenum mode) mode可以选取以下三种模式之 ...
- 【OpenGL ES】关于VBO(Vertex Buffer Object)的一些坑——解析一些关于glBuffer的函数
最近在写毕设的时候用到OpenGL ES中的VBO,由于对一些接口用到的变量不了解被坑得很惨,在此记录一下防止以后再被坑. 本文为大便一箩筐的原创内容,转载请注明出处,谢谢:http://www.cn ...
- [Modern OpenGL系列(三)]用OpenGL绘制一个三角形
本文已同步发表在CSDN:http://blog.csdn.net/wenxin2011/article/details/51347008 在上一篇文章中已经介绍了OpenGL窗口的创建.本文接着说如 ...
- [Modern OpenGL系列(二)]创建OpenGL窗口
本文已同步发表在CSDN:http://blog.csdn.net/wenxin2011/article/details/51295663 在博主的上一篇文章中已经介绍了OpenGL开发环境的搭建,本 ...
- [Modern OpenGL系列(一)]十步搞定OpenGL开发环境
本文已同步发表在CSDN:http://blog.csdn.net/wenxin2011/article/details/51292143 OpenGL官网:https://www.opengl.or ...
随机推荐
- HDU 5945 / BestCoder Round #89 1002 Fxx and game 单调队列优化DP
Fxx and game 问题描述 青年理论计算机科学家Fxx给的学生设计了一款数字游戏. 一开始你将会得到一个数\:XX,每次游戏将给定两个参数\:k,tk,t, 任意时刻你可以对你的数执行下面 ...
- [原创]Centos7 从零配置Nginx+PHP+MySql
序言 这次玩次狠得.除了编译器使用yum安装,其他全部手动编译.哼~ 看似就Nginx.PHP.MySql三个东东,但是它们太尼玛依赖别人了. 没办法,想用它们就得老老实实给它们提供想要的东西. 首先 ...
- ubuntu14.04禁用自动待机保持屏幕亮度
http://jingyan.baidu.com/article/9989c7461fd041f648ecfe05.html
- Flask下如何处理Requests 上传中文文件名的问题
一.问题的由来 最近有个项目,叫做文档服务资源中心,类似于七牛,为各个业务系统提供统一的文件资源服务,包括文件的存储.操作管理.下载.预览等.在做文件存储的时候,遇到了这个当指定上传的文件名为 ...
- [RxJava^Android]项目经验分享 --- 失败重试
简单介绍一下业务逻辑:获取字符串,如果获取失败进行10次重试,超出10次未成功视为失败. 模拟获取字符串场景 代码块 class MsgTool { int count; String getMsg( ...
- BZOJ2109: [Noi2010]Plane 航空管制
Description 世博期间,上海的航空客运量大大超过了平时,随之而来的航空管制也频频 发生.最近,小X就因为航空管制,连续两次在机场被延误超过了两小时.对此, 小X表示很不满意. 在这次来烟台的 ...
- weex image
weex 的image用来渲染图片, 可以使用img作为它的别名. 需要注意的是,他的长度可宽度必须指定, 不然它是不会工作的. 它没有任何的子组件. 有两个属性: src 用来指定图片的地址图片. ...
- php中echo(),print(),print_r(),var_dump()间的区别
echo()函数:输出一个或多个字符串.实际上它并不是一个函数,所以不必对它使用括号,直接用echo就行.然而,如果您希望向echo()传递一个以上的参数,使用括号将会生成解析错误.echo()函数比 ...
- clear属性
clear:规定元素的哪一侧不允许其他浮动元素. clear 属性定义了元素的哪边上不允许出现浮动元素.在 CSS1 和 CSS2 中,这是通过自动为清除元素(即设置了 clear 属性的元素)增加上 ...
- Ubuntu14.10搭建C++开发环境
方法一:1、安装Eclipsesudo apt-get install eclipse2、安装Eclipse CDTsudo apt-get install eclipse-cdt3、安装Autoto ...