GLSL 每个顶点固定大小的数组

Posted

技术标签:

【中文标题】GLSL 每个顶点固定大小的数组【英文标题】:GLSL per vertex fixed size array 【发布时间】:2012-01-28 08:07:28 【问题描述】:

在桌面 GLSL 中是否可以将固定大小的浮点数组作为属性传递给顶点着色器?如果是,怎么做?

我想为角色动画设置每个顶点的权重,所以我想在我的顶点着色器中添加如下内容:

attribute float weights[25];

如何从我的 C++ 和 OpenGL 程序中填充属性数组?我在另一个question 中看到,我可以获取数组属性的属性位置,然后将索引添加到该位置。有人可以为我相当大的阵列举一个例子吗?

谢谢。

【问题讨论】:

【参考方案1】:

让我们从您的要求开始。

目前几乎没有任何硬件可以编译attribute float weights[25];。虽然着色器可以有属性数组,但每个数组索引代表一个 new 属性索引。在当前存在的所有硬件上,属性索引的最大数量为... 16。您需要 25,而这只是用于权重。

现在,您可以通过记住可以使用vec4 属性来轻松缓解这种情况。因此,您将每四个数组元素存储在一个属性中。您的数组将是attribute vec4 weights[7];,这是可行的。当然,你的重量获取逻辑必须改变。

即便如此,您似乎并没有考虑到这对您的顶点数据实际上意味着的含义。每个属性代表一个顶点数据的一个组成部分。渲染调用的每个顶点将具有相同的数据量;该数据的内容会有所不同,但不会有多少数据。

为了按照您的建议进行操作,网格中的每个 顶点 都需要 25 个浮点数来描述权重。即使这被存储为规范化的无符号字节,这仍然是至少 25 个额外字节的数据。好多啊。特别是考虑到 vast 大多数顶点,这些值中的大多数将为 0。即使在最坏的情况下,您可能会看到 6-7 个骨骼影响单个顶点。

通常在顶点着色器中进行蒙皮的方式是将影响单个顶点的骨骼数量限制为四个。这样,您就不会使用属性数组;您只需使用vec4 属性作为权重。当然,您现在还需要说出哪块骨头与哪块重量相关联。所以你有第二个vec4 属性来指定该权重的骨骼索引。

这达到了很好的平衡。您只占用 2 个额外属性(在大小方面可以是无符号字节)。而对于绝大多数顶点,您甚至都不会注意到,因为大多数顶点仅受 1-3 根骨骼的影响。少数人使用 4,更少的人仍然使用 5+。在这些情况下,您只需切除最低权重并按比例重新计算其他权重。

【讨论】:

非常感谢。你回答了我所有的问题,甚至更多!我希望这将大大提高性能!再次感谢。【参考方案2】:

尼可波拉斯已经给出了如何重组任务的答案。你应该这样做,因为为一个顶点处理 25 个浮点数,可能通过一些四元数乘法会浪费大量良好的 GPU 处理能力;无论如何,顶点的大多数属性都将转换为接近于恒等变换。

但是出于学术原因,我将告诉您,如何通过每个顶点 25 个浮点数。关键不是为此使用属性,而是从某个缓冲区(纹理)中获取数据。 GLSL 顶点着色器阶段有内置变量gl_VertexID,它传递当前处理的顶点的索引。使用最近的 OpenGL,您也可以从顶点着色器访问纹理。所以你有一个大小为vertex_count × 25 的纹理来保存这些值。在您的顶点着色器中,您可以使用texelFetch 函数访问它们,即texelFetch(param_buffer, vec2(gl_VertexID, 3));

如果用于骨骼动画,这个系统通常被称为纹理蒙皮。然而,它应该谨慎使用,因为它是一个真正的性能猪。但有时您无法避免,例如在实现面部动画系统时,如果您想准确模拟人脸,则必须将所有顶点加权到 26 块肌肉。

【讨论】:

以上是关于GLSL 每个顶点固定大小的数组的主要内容,如果未能解决你的问题,请参考以下文章

顶点着色器 glsl qt 中的纹理映射

OpenGL3:高级篇 GLSL

顶点纹理获取(在顶点着色器中读取纹理)

glsl attributes变量怎么用

在 GLSL 顶点着色器中,您可以访问索引缓冲区中顶点的索引,而不仅仅是顶点缓冲区吗?

GLSL:如何使用投影矩阵计算光线方向?