我需要计算顶点着色器输出的每个顶点属性的数量大于 GL_MAX_VERTEX_ATTRIBS。是否有一种有效的方法来例如使用统一的索引数组指向多个缓冲区并以这种方式访问每个顶点数据?
3 回答
这是一个硬件限制,所以简短的回答是否定的。如果您考虑其他方式的解决方法,例如使用也有限制的制服,那么这也是没有办法的。
我能想到的一种可能的方法是从纹理中获取额外的数据。由于您可以从顶点着色器访问纹理,但不支持纹理过滤(您不需要它,所以对您来说没关系)。使用较新的 OpenGL 可以在纹理中存储相当大量的数据,并且即使在顶点着色器中也可以不受限制地访问它们,这似乎是一种方法。
尽管使用这种方法,但您需要面对一个问题,您如何知道当前索引,即它是哪个顶点?你可以查看 gl_VertexID 内置的。
您可以绕过输入汇编器并将额外属性绑定到 SSBO 或纹理中。然后您可以在顶点着色器中使用 gl_VertexID 来获取您当前正在渲染的索引缓冲区条目的值(例如:您需要从中读取的顶点数据中的索引)
因此,例如在 VS 中,以下代码本质上是相同的(但是,根据您的硬件,它可能具有不同的性能特征)
in vec3 myAttr;
void main() {
vec3 vertexValue = myAttr;
//etc
}
对比
buffer myAttrBuffer {
vec3 myAttr[];
};
void main() {
vec3 vertexValue = myAttr[gl_VertexID];
//etc
}
CPU 端的绑定代码是不同的,但通常是这个概念。myAttr 计入 GL_MAX_VERTEX_ATTRIBS,但 myAttrBuffer 不计入,因为它是由着色器显式加载的。
您甚至可以通过绑定不同的目标在这两种情况下使用相同的缓冲区对象。
如果你不能绝对限制自己使用 GL_MAX_VERTEX_ATTRIBS 属性,我会建议使用多通道着色器。重新设计您的代码以处理在第一遍中具有一半属性集的数据,其余在第二遍中。