GLSL逐顶点固定大小数组

GLSL per vertex fixed size array

本文关键字:小数 数组 顶点 GLSL      更新时间:2023-10-16

在桌面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块肌肉。