在桌面 GLSL 中是否可以将固定大小的浮点数组作为属性传递给顶点着色器?如果是,如何?
我想为角色动画设置每个顶点的权重,所以我想在我的顶点着色器中有如下内容:
attribute float weights[25];
如何从我的 C++ 和 OpenGL 程序中填充属性数组?我在另一个问题中看到,我可以获取数组属性的属性位置,然后将索引添加到该位置。有人可以为我相当大的阵列举一个例子吗?
谢谢。
在桌面 GLSL 中是否可以将固定大小的浮点数组作为属性传递给顶点着色器?如果是,如何?
我想为角色动画设置每个顶点的权重,所以我想在我的顶点着色器中有如下内容:
attribute float weights[25];
如何从我的 C++ 和 OpenGL 程序中填充属性数组?我在另一个问题中看到,我可以获取数组属性的属性位置,然后将索引添加到该位置。有人可以为我相当大的阵列举一个例子吗?
谢谢。
让我们从你所要求的开始。
目前几乎没有任何硬件可以attribute float weights[25];
编译。虽然着色器可以有属性数组,但每个数组索引代表一个新的属性索引。在当前存在的所有硬件上,属性索引的最大数量是... 16。你需要 25,这只是权重。
现在,您可以通过记住您可以使用vec4
属性来轻松缓解这种情况。因此,您将每四个数组元素存储在一个属性中。您的阵列将attribute vec4 weights[7];
是可行的。当然,你的取重逻辑必须改变。
即便如此,您似乎并没有考虑到这对您的顶点数据实际上意味着什么。每个属性代表一个顶点数据的一个组成部分。渲染调用的每个顶点将具有相同的数据量;该数据的内容会有所不同,但不会有多少数据。
为了执行您的建议,网格中的每个顶点都需要 25 个浮点数来描述权重。即使这被存储为规范化的无符号字节,这仍然是至少 25 个额外字节的数据。好多啊。特别是考虑到对于绝大多数顶点,这些值中的大多数将为 0。即使在最坏的情况下,您可能会看到 6-7 个骨骼影响单个顶点。
通常在顶点着色器中进行蒙皮的方式是将影响单个顶点的骨骼数量限制为四个。这样,您就不会使用属性数组;您只需使用vec4
权重属性。当然,您现在还需要说出哪块骨头与哪块重量相关联。因此,您有第二个vec4
属性指定该权重的骨骼索引。
这达到了很好的平衡。您只占用 2 个额外属性(在大小方面可以是无符号字节)。而对于绝大多数顶点,您甚至都不会注意到,因为大多数顶点仅受 1-3 根骨骼的影响。少数人使用 4,更少的人仍然使用 5+。在这些情况下,您只需切断最低权重并按比例重新计算其他权重。
Nicol Bolas 已经给出了如何重组任务的答案。你应该这样做,因为为一个顶点处理 25 个浮点数,可能通过一些四元数乘法会浪费大量良好的 GPU 处理能力;无论如何,顶点的大多数属性都将转换为接近恒等变换。
但是出于学术原因,我将告诉你,如何通过每个顶点 25 个浮点数。关键不是为此使用属性,而是从某个缓冲区(纹理)中获取数据。GLSL 顶点着色器阶段具有内置变量gl_VertexID
,它传递当前处理的顶点的索引。使用最近的 OpenGL,您也可以从顶点着色器访问纹理。所以你有一个大小的纹理来vertex_count × 25
保存这些值。在您的顶点着色器中,您可以使用该texelFetch
函数访问它们,即texelFetch(param_buffer, vec2(gl_VertexID, 3));
如果用于骨骼动画,这个系统通常被称为纹理蒙皮。然而,它应该谨慎使用,因为它是一个真正的性能猪。但有时你无法避免它,例如在实现面部动画系统时,如果你想准确地模拟人脸,你必须将所有顶点加权到 26 块肌肉。