GLSL:如何访问附近的顶点颜色? (没有制服的双线性插值)

时间:2011-03-22 19:01:24

标签: c++ opengl glsl interpolation

我正试图在四边形上进行双线性颜色插值,我在这里的前一个问题的帮助下成功了,但它的性能很差,因为它要求我重复glBegin()和glEnd()以及4次glUniform ()之前的glBegin()。

问题是:无论如何可以在这样的四边形上应用双线性颜色插值:

glBegin(GL_QUADS);
    glColor4f(...); glVertexAttrib2f(uv, 0, 0); glTexCoord2f(...); glVertex3f(...);
    glColor4f(...); glVertexAttrib2f(uv, 1, 0); glTexCoord2f(...); glVertex3f(...);
    glColor4f(...); glVertexAttrib2f(uv, 1, 1); glTexCoord2f(...); glVertex3f(...);
    glColor4f(...); glVertexAttrib2f(uv, 0, 1); glTexCoord2f(...); glVertex3f(...);
... // here can be any amount of quads without repeating glBegin()/glEnd()
glEnd();

要做到这一点,我想我应该以某种方式访问​​附近的顶点颜色,但如何?或者还有其他解决方案吗?

我需要这样才能以这种方式工作,这样我就可以轻松地在不同的插值着色器之间切换。

任何其他适用于一个glBegin()命令的解决方案都是好的,但是每个顶点发送所有角色是不可接受的,除非这是唯一的解决方案吗?

编辑:示例代码仅使用立即模式以获得清晰度。即使使用顶点数组/缓冲区,问题也是一样的:我必须将渲染调用分成4个顶点块,这会导致整个速度下降!

4 个答案:

答案 0 :(得分:3)

长话短说:你不能用顶点着色器做到这一点。

插值器(或光栅化器)是不可编程的图形管道的组件之一。鉴于图形管道的工作原理,由于速度,简单性和并行性的原因,顶点着色器和片段着色器都不允许访问除顶点(或分段)之外的任何内容。

解决方法是使用纹理查找,这在以前的答案中已经注明过。

在较新版本的OpenGL(3.0及以上版本,我相信?)中,现在有了几何着色器的概念。与相对简单的顶点和片段着色器相比,几何着色器实现起来更复杂,但几何着色器会获得拓扑信息。也就是说,它们在基元(三角形,直线,四边形等)而不是单个点上执行。有了这些信息,他们就可以创建额外的几何图形,以便解决您的备用颜色插值方法。

然而,这远比必要复杂得多。我会坚持使用4纹素纹理贴图,并在片段查找中实现您的逻辑。

答案 1 :(得分:2)

引擎盖下,OpenGL(以及它驱动的所有硬件)将以三角形的形式完成所有操作。因此,如果您选择通过顶点插值来混合颜色,那么它将是三角插值,因为硬件不会以任何其他方式工作。

如果你想要“四元”插值,你应该把颜色放到纹理中,因为在硬件中纹理总是“四边形”。

答案 2 :(得分:0)

使用glColorPointer可以有效地设置每个顶点指定颜色的线性插值。类似地,您应该使用glTexCoordPointer / glVertexAttribPointer / glVertexPointer来通过引用数组中的数据的单个调用来替换所有这些单独的每顶点调用。然后使用单个(或最多一些)glDrawArrays或glDrawElements调用渲染所有四边形。即使没有VBO(只是改变存储数组的位置),你也会看到一个巨大的改进。

你提到要在四分之一基础上更改着色器(在ShaderA和ShaderB之间说)。你应该:

  • 安排事情,这样你就可以将所有ShaderA四边形和所有ShaderB四边形一起批处理,并通过一次调用一起渲染所有这些四边形。更改着色器通常非常昂贵,因此您希望最小化更改次数。

  • 在单个“统一”着色器中实现所需的所有不同着色器逻辑,但由另一个顶点属性选择,该属性在不同的代码路径之间进行选择。这是否与批处理方法(这是优选的)一样有效,取决于SIMD着色器的每个“图块”是否必须运行路径的混合或仅一个。

答案 3 :(得分:0)

如果你真的认为这是导致你的性能下降的绘制数量,你可以尝试使用GL 3.1核心中提供的Instancing(使用glDrawArrayInstanced + glVertexAttribDivisor)。

替代方案可能是点精灵,具体取决于您的使用模型(主要是您的四边形的最大尺寸,并且它们始终垂直于视图)。这是自GL 2.0核心以来的。