简体   繁体   English

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

[英]GLSL per vertex fixed size array

Is it possible in desktop GLSL to pass a fixed size array of floats to the vertex shader as an attribute? 在桌面GLSL中是否可以将固定大小的浮点数组作为属性传递给顶点着色器? If yes, how? 如果有,怎么样?

I want to have per vertex weights for character animation so I would like to have something like the following in my vertex shader: 我想为角色动画设置每个顶点权重,所以我想在顶点着色器中使用以下内容:

attribute float weights[25];

How would I fill the attribute array from my C++ & OpenGL program? 我如何从C ++和OpenGL程序中填充属性数组? I have seen in another question that I could get the attribute location of the array attribute and then just add the index to that location. 我在另一个问题中看到我可以获取数组属性的属性位置,然后只需将索引添加到该位置。 Could someone give an example on that for my pretty large array? 有人可以为我的大型数组提供一个例子吗?

Thanks. 谢谢。

Let's start with what you asked for. 让我们从你要求的开始。

On pretty much no hardware that exists currently will attribute float weights[25]; 几乎没有当前存在的硬件将attribute float weights[25]; compile. 编译。 While shaders can have arrays of attributes, each array index represents a new attribute index. 着色器可以具有属性数组,而每个数组索引代表一个新的属性索引。 And on all hardware the currently exists, the maximum number of attribute indices is... 16. You'd need 25, and that's just for the weights. 在目前存在的所有硬件上,属性索引的最大数量是...... 16.你需要25,这只是权重。

Now, you can mitigate this easily enough by remembering that you can use vec4 attributes. 现在,您可以通过记住可以使用vec4属性来轻松地缓解这一问题。 Thus, you store every four array elements in a single attribute. 因此,您将每四个数组元素存储在一个属性中。 Your array would be attribute vec4 weights[7]; 你的数组将是attribute vec4 weights[7]; which is doable. 这是可行的。 Your weight-fetching logic will have to change of course. 你的举重逻辑当然必须改变。

Even so, you don't seem to be taking in the ramifications of what this would actually mean for your vertex data. 即便如此,您似乎并没有考虑到这对您的顶点数据实际意味着什么。 Each attribute represents a component of a vertex's data. 每个属性代表顶点数据的一个组成部分。 Each vertex for a rendering call will have the same amount of data; 渲染调用的每个顶点将具有相同数量的数据; the contents of that data will differ, but not how much data. 该数据的内容会有所不同,但不会有多少数据。

In order to do what you're suggesting, every vertex in your mesh would need 25 floats describing the weight. 为了做你所建议的,网格中的每个顶点都需要25个浮点数来描述权重。 Even if this was stored as normalized unsigned bytes, that's still 25 extra bytes worth of data at a minimum. 即使将其存储为规范化的无符号字节,这仍然是至少25个额外字节的数据。 That's a lot. 好多啊。 Especially considering that for the vast majority of vertices, most of these values will be 0. Even in the worst case, you'd be looking at maybe 6-7 bones affecting an single vertex. 特别是考虑到绝大多数顶点,大多数这些值都是0.即使在最坏的情况下,你也可能会看到影响单个顶点的6-7个骨骼。

The way skinning is generally done in vertex shaders is to limit the number of bones that affects a single vertex to four . 通常在顶点着色器中完成蒙皮的方法是将影响单个顶点的骨骼数量限制为四个 This way, you don't use an array of attributes; 这样,您就不会使用属性数组; you just use a vec4 attribute for the weights. 你只需要使用vec4属性作为权重。 Of course, you also now need to say which bone is associated with which weight. 当然,您现在还需要说明哪个骨骼与哪个骨骼相关联。 So you have a second vec4 attribute that specifies the bone index for that weight. 因此,您有第二个vec4属性,指定该权重的骨骼索引。

This strikes a good balance. 这达到了很好的平衡。 You only take up 2 extra attributes (which can be unsigned bytes in terms of size). 您只需要占用2个额外属性(就大小而言可以是无符号字节)。 And for the vast majority of vertices, you'll never even notice, because most vertices are only influenced by 1-3 bones. 对于绝大多数顶点,您甚至都不会注意到,因为大多数顶点仅受1-3个骨骼的影响。 A few uses 4, and fewer still use 5+. 少数使用4,少数使用5+。 In those cases, you just cut off the lowest weights and recompute the weights of the others proportionately. 在这些情况下,您只需按比例切断最低权重并重新计算其他权重。

Nicol Bolas already gave you an answer how to restructure your task. Nicol Bolas已经给你一个如何重组你的任务的答案。 You should do it, because processing 25 floats for a vertex, probably through some quaternion multiplication will waste a lot of good GPU processing power; 你应该这样做,因为为一个顶点处理25个浮点数,可能通过一些四元数乘法会浪费很多好的GPU处理能力; most of the attributes for a vertex will translate close to an identity transform anyway. 无论如何,顶点的大多数属性都将转换为接近身份转换。

However for academic reasons I'm going to tell you, how to pass 25 floats per vertex. 但是出于学术原因,我将告诉你,如何在每个顶点传递25个浮点数。 The key is not using attributes for this, but fetching the data from some buffer, a texture. 关键是不使用属性,而是从某个缓冲区(纹理)中获取数据。 The GLSL vertex shader stage has the builtin variable gl_VertexID , which passes the index of the currently processed vertex. GLSL顶点着色器阶段具有内置变量gl_VertexID ,它传递当前处理的顶点的索引。 With recent OpenGL you can access textures from the vertex shader as well. 使用最近的OpenGL,您也可以从顶点着色器访问纹理。 So you have a texture of size vertex_count × 25 holding the values. 所以你有一个大小为vertex_count × 25的纹理来保存这些值。 In your vertex shader you can access them using the texelFetch function, ie texelFetch(param_buffer, vec2(gl_VertexID, 3)); 在您的顶点着色器中,您可以使用texelFetch函数访问它们,即texelFetch(param_buffer, vec2(gl_VertexID, 3));

If used in skeletal animation this system is often referred to as texture skinning . 如果在骨架动画中使用,则此系统通常称为纹理蒙皮 However it should be used sparingly, as it's a real performance hog. 然而,它应该谨慎使用,因为它是一个真正的性能猪。 But sometimes you can't avoid it, for example when implementing a facial animation system where you have to weight all the vertices to 26 muscles, if you want to accurately simulate a human face. 但有时候你无法避免它,例如当你实现一个面部动画系统,你需要将所有顶点加权到26个肌肉,如果你想要准确地模拟人脸。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM