【问题标题】:How to use a 4x4 matrix as a vertex attribute in GLSL?如何在 GLSL 中使用 4x4 矩阵作为顶点属性?
【发布时间】: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;
// ...

但我在屏幕上看到的都是垃圾。

【问题讨论】:

  • 如果你想进行网格蒙皮,最好将矩阵作为制服传递,并使用一个或多个整数向量属性来尊重它们。
  • 您找到解决方案了吗?我遇到了完全相同的问题。
  • @sak 就像 Luca 所说,您可以将整数索引作为顶点属性传递到数组中,但不要将矩阵作为制服发送(着色器有最大数量的制服,这可能还不够)您可以将所有矩阵存储在浮点纹理中,然后使用最近邻采样对其进行采样。
  • Mat4 类型是什么样子的?

标签: c++ opengl glsl vertex-shader


【解决方案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)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-18
    相关资源
    最近更新 更多