如何在 GLSL 中使用 4x4 矩阵作为顶点属性?
Posted
技术标签:
【中文标题】如何在 GLSL 中使用 4x4 矩阵作为顶点属性?【英文标题】:How to use a 4x4 matrix as a vertex attribute in GLSL? 【发布时间】:2012-10-09 03:31:54 【问题描述】:我正在尝试使用 4x4 矩阵作为顶点属性,使用以下代码:
Mat4 matrices[numVerts];
int mtxBoneID = glGetAttribLocation(hProgram, "aMtxBone");
glEnableVertexAttribArray(mtxBoneID + 0);
glEnableVertexAttribArray(mtxBoneID + 1);
glEnableVertexAttribArray(mtxBoneID + 2);
glEnableVertexAttribArray(mtxBoneID + 3);
glVertexAttribPointer(mtxBoneID + 0, 4, GL_FLOAT, GL_FALSE, sizeof(Mat4), ((Vec4*)matrices) + 0);
glVertexAttribPointer(mtxBoneID + 1, 4, GL_FLOAT, GL_FALSE, sizeof(Mat4), ((Vec4*)matrices) + 1);
glVertexAttribPointer(mtxBoneID + 2, 4, GL_FLOAT, GL_FALSE, sizeof(Mat4), ((Vec4*)matrices) + 2);
glVertexAttribPointer(mtxBoneID + 3, 4, GL_FLOAT, GL_FALSE, sizeof(Mat4), ((Vec4*)matrices) + 3);
// shader:
// ...
attribute mat4 aMtxBone;
// ...
但我在屏幕上看到的都是垃圾。
【问题讨论】:
如果你想进行网格蒙皮,最好将矩阵作为制服传递,并使用一个或多个整数向量属性来尊重它们。 您找到解决方案了吗?我遇到了完全相同的问题。 查看这个***.com/questions/17355051/… @sak 就像 Luca 所说,您可以将整数索引作为顶点属性传递到数组中,但不要将矩阵作为制服发送(着色器有最大数量的制服,这可能还不够)您可以将所有矩阵存储在浮点纹理中,然后使用最近邻采样对其进行采样。 Mat4 类型是什么样子的? 【参考方案1】:你可以试试这样的 在你的着色器中使用布局
layout(location=x) in mat4 <name>;
x 不会等于glGetAttribLocation
,你必须自己维护它。它等于你调用glVertexAttribPointer
的次数。
例子
layout(location=0) in vec4 in_Position;
layout(location=1) in vec4 in_Color;
layout(location=2) in vec4 in_Normal;
glVertexAttribPointer(0, xxxxxxxx);
glVertexAttribPointer(1, xxxxxx);
glVertexAttribPointer(2, xxxxxx);
【讨论】:
应该注意,位置索引并不总是如上所述的“相等”,因为为每对 4 个顶点分配了一个索引。因此,一个矩阵将包含 4 个索引位置(或 16 个浮点数)。如果您尝试在位置 0 存储矩阵,在位置 1 存储 vec4,则链接着色器后会出现错误,因为这两个属性会导致重叠。您需要将 vec4 放置在位置 4,或将 mat4 放置在 vec4 之后以避免此类错误。【参考方案2】:所以,我的答案因为未知原因被删除了。
我又来了,这次换个格式吧。
我遇到了与问题完全相同的问题,东西会被画得一团糟。至少描述是这样的。
为我解决的问题是调用
glDrawElementsInstancedBaseVertex(GL_TRIANGLES,
d->drawCount,
GL_UNSIGNED_INT,
0,
p_objects.size(),
0);
要画我的东西,仅此而已。
但是!
如果您的东西绘制不正确,这可能不是您遇到的唯一问题。你需要纠正它的整个清单是巨大的。所以我要在这里放一个链接,它有一个关于如何画很多东西的很棒的教程。另外,您可以获取源代码并自己尝试。
http://ogldev.atspace.co.uk/www/tutorial33/tutorial33.html
来源:http://ogldev.atspace.co.uk/ogldev-source.zip
再次拒绝我并删除我的答案,它的内容与原来的完全没有改变。
禁止我访问该网站,你的损失。
【讨论】:
【参考方案3】:首先您需要为您的矩阵创建 VBO (glGenBuffers
),然后将其 (glBindBuffer
) 绑定为当前,然后使用
glVertexAttribPointer(mtxBoneID + 0, 4, GL_FLOAT, GL_FALSE, 0, 0);
glVertexAttribPointer(mtxBoneID + 1, 4, GL_FLOAT, GL_FALSE, 0, 4);
glVertexAttribPointer(mtxBoneID + 2, 4, GL_FLOAT, GL_FALSE, 0, 8);
glVertexAttribPointer(mtxBoneID + 3, 4, GL_FLOAT, GL_FALSE, 0, 12);
而不是您的glVertexAttribPointer
电话。
【讨论】:
顶点缓冲区对象不是强制性的。所以,不,这不是解决方案。 更新了我的答案。但是您似乎正在使用 OpenGL 2。我建议切换到 OpenGL 3,因为它似乎没有那么错误(我在使用 OpenGL 2 时经常遇到一些奇怪的行为,而 OpenGL 3 没有这个问题)。 现在答案已经完全过时了,只是展示他已经使用的代码。只有一个区别,这种区别甚至会让你的答案错误,因为12 * sizeof(float)
的步幅是行不通的。您需要从一个顶点的开始 到下一个顶点的字节,所以很可能是16 * sizeof(float)
,或者更好的是sizeof(Mat4)
。但是等一下,那将完全是他的代码,你已经准备好删除答案了。
@AntonGuryanov OpenGL 2 的漏洞丝毫不比 OpenGL 3 少。唯一可能有漏洞的是您的实现(硬件+驱动程序)(您没有使用 ATI 或 Intel GPU,是吗?)。可能只是核心 OpenGL 3 更简洁的界面让驱动程序失败的机会更少。
@ChristianRau 哎呀,我的错。然后我只能建议使用 OpenGL 3 尝试 VBO,问题就会消失。关于我的 GPU,当我使用 OpenGL 2 时,我有 NVidia GPU,我遇到了一些奇怪的问题。然后我切换到 OpenGL 3 并获得了一台装有 AMD Radeon 的新计算机。从那以后,我没有发现任何错误或奇怪的行为。【参考方案4】:
您的偏移量似乎已关闭。应该是
((Vec4*)matrices) + sizeOf(Vec4)*i
而不是
((Vec4*)matrices) + i
【讨论】:
这是错误的。当您将整数添加到指针时,添加的偏移量等于该整数与对象大小(以字节为单位)的乘积。您提供的代码相当于-> ((char*)matrices) + (sizeof(Vec4) * i) * sizeof(Vec4)以上是关于如何在 GLSL 中使用 4x4 矩阵作为顶点属性?的主要内容,如果未能解决你的问题,请参考以下文章