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个顶点,其位置和颜色如下(同上图左侧所示)

 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);
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里的图元呢?我们下回分解。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt OpenGL提供了一种实现高效渲染的机制,它使用了VAO(Vertex Array Object)和VBO(Vertex Buffer Object)技术。 VAO是一种对象,用于存储顶点数据、顶点属性以及它们之间的关联关系。它可以理解为一个顶点属性的容器。通过使用VAO,我们可以将顶点数据存储在显存中,而不是每次渲染时都从CPU传输顶点数据到显存,从而提高渲染的效率。 VBO是一个存储顶点数据的缓冲区对象。通过将顶点数据存储在VBO中,我们可以将数据一次性地传输到显存中,并且可以高效地管理和使用这些数据。同时,VBO还可以提供顶点缓存和索引缓存功能,用于顶点的重用和图元的索引。 Qt OpenGL提供了许多方便的API来操作VAO和VBO。我们可以使用QOpenGLVertexArrayObject类来创建和管理VAO,通过调用QOpenGLBuffer类的相关方法来创建和管理VBO。例如,我们可以使用QOpenGLVertexArrayObject::bind()和QOpenGLVertexArrayObject::release()方法来绑定和释放VAO,使用QOpenGLBuffer::bind()和QOpenGLBuffer::release()方法来绑定和释放VBO。 使用VAO和VBO可以大大简化OpenGL代码的编写,并且能够有效提高渲染效率。我们可以将需要渲染的数据一次性地传输到显存中,并且设置好相应的渲染状态,然后每次渲染时只需要绑定VAO进行渲染即可,不需要重复的数据传输和状态设置操作。 综上所述,Qt OpenGL的VAO和VBO技术可以帮助我们实现高效渲染,提高应用程序的性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值