在OpenGL中,如何处理每个三角形的多个变量?

4
我正在使用OpenGL,并不满意标准方法传递每个三角形(或在我的情况下,四边形)的值,这些值需要在片段着色器中使用,即将它们分配给每个原始图元的顶点,并通过顶点着色器传递它们以被不必要地插值(除非使用“flat”指令)在片段着色器中(因此换句话说,每个片段非变化的)。
有没有一种方式可以存储每个三角形(或四边形)的值,以便在片段着色器中访问,而不需要每个顶点都有冗余副本?如果是这样,那么这种方式是否比CPU端的3x(或4x)数据移动代码的开销更好?
我知道使用几何着色器可以将这些值扩展到新顶点,但我听说几何着色器在不更新硬件上非常慢。这是真的吗?
2个回答

6

OpenGL片段语言支持gl_PrimitiveID输入变量,它将是当前处理的片段所属原始图元的索引(每个绘制调用从0开始)。这可以用作对某些保存每个原始数据的数据存储的索引。

根据每个原始需要的数据量和总原始数量,有不同的选择。对于少量的原始,您可以设置一个统一的数组并索引到其中。

对于相当多的原始,我建议使用纹理缓冲对象(TBO)。这基本上是一个普通的缓冲对象,可以通过texelFetch GLSL操作在随机位置只读访问。请注意,TBO实际上不是纹理,它们仅重用现有的纹理对象接口。在内部,它仍然是从缓冲对象获取数据,并且没有纹理管线的任何开销,非常高效。

这种方法的唯一问题是您无法轻松地混合不同的数据类型。您必须为TBO定义一个基本数据类型,并且每次提取都会以该格式获取数据。如果您只需要每个基元的一些浮点数/向量,则这完全不是问题。如果您需要每个基元的一些整数和一些浮点数,您可以使用不同的TBO,每种类型一个,或者使用现代GLSL(>=3.30),您可以使用整数类型的TBO并重新解释整数位为浮点数,通过intBitsToFloat()绕过该限制。

那么您是在暗示我应该使用gl_PrimitiveID来索引TBO吗? - Christopher Brown
@ChristopherBrown:是的。当然,你可能需要一些因素,因为你可能需要一个原语中不止一个“元素”(或者也许不需要),所以不要直接使用gl_PrimitiveID作为纹理坐标。 - derhass

2
您可以使用顶点数组中的一个元素来渲染多个顶点。这被称为实例化顶点属性

@snb 你是否认为之前的编辑建议了不同的解决方案?在我看来,我之前也是在建议同样的事情。 :) - HolyBlackCat
是的,看起来你在谈论另一件事情。 - Krupip
不,你之前更接近了,看看这个。你需要使用分频器,否则你将无法使用每个实例的属性。还有一个事情让我困惑,就是你说“这种方法不能加速渲染”,但实例化确实可以加速渲染……你发送一个命令而不是10000个。 - Krupip
@snb 但是 glVertexAttribDivisor 允许每个实例一个属性值,而不是每个三角形。每个实例一个三角形会很愚蠢。你对性能的看法是正确的,我已经修改了。 - HolyBlackCat
Op说:“PER三角形(或四边形)”,他们可以单独绘制每个三角形或四边形实例,但无论如何,没有足够的信息让任何人知道该怎么做。我甚至不确定你现在在说什么。 - Krupip
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接