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)的更多相关文章

  1. Modern OpenGL用Shader拾取VBO内单一图元的思路和实现

    Modern OpenGL用Shader拾取VBO内单一图元的思路和实现 什么意思? 拾取 最简单的理解拾取的方式大概是到(http://www.yakergong.net/nehe/course/t ...

  2. Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(3)

    Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(3) 到上一篇为止,拾取一个VBO里的单个图元的问题已经彻底解决了.那么来看下一个问题:一个场景里可能会有多个VBO,此时每个 ...

  3. [Modern OpenGL系列(四)]在OpenGL中使用Shader

    本文已同步发表在CSDN:http://blog.csdn.net/wenxin2011/article/details/51347440 在上一篇文章中已经介绍了OpenGL窗口的创建.本文接着说如 ...

  4. OpenGL图形渲染管线、VBO、VAO、EBO概念及用例

    图形渲染管线(Pipeline) 图形渲染管线指的是对一些原始数据经过一系列的处理变换并最终把这些数据输出到屏幕上的整个过程. 图形渲染管线的整个处理流程可以被划分为几个阶段,上一个阶段的输出数据作为 ...

  5. OpenGL中的拾取模式( Picking)

    1. Opengl中的渲染模式有三种:(1)渲染模式,默认的模式:(2)选择模式, (3)反馈模式.如下 GLint glRenderMode(GLenum mode) mode可以选取以下三种模式之 ...

  6. 【OpenGL ES】关于VBO(Vertex Buffer Object)的一些坑——解析一些关于glBuffer的函数

    最近在写毕设的时候用到OpenGL ES中的VBO,由于对一些接口用到的变量不了解被坑得很惨,在此记录一下防止以后再被坑. 本文为大便一箩筐的原创内容,转载请注明出处,谢谢:http://www.cn ...

  7. [Modern OpenGL系列(三)]用OpenGL绘制一个三角形

    本文已同步发表在CSDN:http://blog.csdn.net/wenxin2011/article/details/51347008 在上一篇文章中已经介绍了OpenGL窗口的创建.本文接着说如 ...

  8. [Modern OpenGL系列(二)]创建OpenGL窗口

    本文已同步发表在CSDN:http://blog.csdn.net/wenxin2011/article/details/51295663 在博主的上一篇文章中已经介绍了OpenGL开发环境的搭建,本 ...

  9. [Modern OpenGL系列(一)]十步搞定OpenGL开发环境

    本文已同步发表在CSDN:http://blog.csdn.net/wenxin2011/article/details/51292143 OpenGL官网:https://www.opengl.or ...

随机推荐

  1. mysql索引总结----mysql 索引类型以及创建

    文章归属:http://feiyan.info/16.html,我想自己去写了,但是发现此君总结的非常详细.直接搬过来了 关于MySQL索引的好处,如果正确合理设计并且使用索引的MySQL是一辆兰博基 ...

  2. SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式

    java日期格式大全 format SimpleDateFormat(转) SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH ...

  3. 手持移动扫描终端 PDA移动开单系统-批发零售管理

    条码数据采集器通过扫描商品条码移动开单,实现便携式办公,伴随式销售,是我公司的一款最新便携式开单配套产品,采集器能通过WIFI无线局域网.GPRS互联网直接与主机连接,让公司业务人员能随时随地了解公司 ...

  4. LeetCode 136. Single Number

    最原始的方法:先排序,然后从头查找.若nums[i] = nums[i] + 1则为一对相同的数,i = i  + 2,继续判断.若nums[i] != nums[i] + 1,则输出nums[i]. ...

  5. 前端工具 & git笔记

    git diff    (working dir to INDEX ) git diff --cached (INDEX to HEAD) git diff  HEAD  (working dir t ...

  6. 【转载】Java集合类Array、List、Map区别和联系

    Java集合类主要分为以下三类: 第一类:Array.Arrays第二类:Collection :List.Set第三类:Map :HashMap.HashTable 一.Array , Arrays ...

  7. Python 基础语法学习笔记

    以下运行结果均通过Python3.5版本实测! 1.列表转换为字典 a = ['a', 'b'] b = [1, 2] c = ['c','d'] print (dict([a,b,c])) 输出结果 ...

  8. Windows使用总结

    虚拟桌面快捷键: 新建虚拟桌面 Control+Win+D 切换虚拟桌面 Control+Win+左/右方向键 关闭虚拟桌面 Control+Win+F4 显示虚拟桌面列表 Win+Tab  

  9. 基于redis的点赞功能设计

    前言 点赞其实是一个很有意思的功能.基本的设计思路有大致两种, 一种自然是用mysql等 数据库直接落地存储, 另外一种就是利用点赞的业务特征来扔到redis(或memcache)中, 然后离线刷回m ...

  10. hdu1532网络流

    (双倍经验题) 第二次写dinic模板,居然一遍写对了,而且短了不少O(∩_∩)O~ #include <cstdio> #define INF 2147483647 int n,m,an ...