我使用的是openglEs 2.0。我正在研究硬件外观。我尝试将骨骼索引作为ivec4传递,但是编译器告诉我不可能将ivec4用作顶点属性。我如何克服这种情况?

这是我的顶点着色器代码。

0(1) : error C7507: OpenGL does not allow attributes of type ivec4
"struct Bone"
    "{"
    "   mat4 transform;"
    "   mat4 bindPose;"
    "};"
    "attribute vec3 vPosition;"
    "attribute vec3 vNormal;"
    "attribute vec2 vTexture;"
    "attribute ivec4 vBones;"
    "attribute vec4 vWeights;"
    "uniform mat4 projectViewModel;"
    "uniform Bone bones[64];"
    "varying vec3 v_normal;"
    "varying vec2 v_texCoord;"
    "void main()"
    "{"
    "   gl_Position = bones[vBones.x].transform * bones[vBones.x].bindPose * vec4(vPosition, 1.0) * vWeights.x;"
    "   gl_Position += bones[vBones.y].transform * bones[vBones.y].bindPose * vec4(vPosition, 1.0) * vWeights.y;"
    "   gl_Position += bones[vBones.z].transform * bones[vBones.z].bindPose * vec4(vPosition, 1.0) * vWeights.z;"
    "   gl_Position += bones[vBones.w].transform * bones[vBones.w].bindPose * vec4(vPosition, 1.0) * vWeights.w;"
    "   gl_Position = projectViewModel * gl_Position;"
    "   v_texCoord = vTexture;"
    "   v_normal = vNormal;"
    "}";

更新:

如前所述,我更改了着色器代码和客户端代码。这是客户端代码:
glEnableVertexAttribArray(3); // Bones
glVertexAttribPointer(3, 4, GL_INT, GL_FALSE, object->m_mesh->GetVertexSize(), (const void*)offset);

这就是我在着色器代码中访问骨骼索引的方式:
gl_Position = bones[int(vBones.x)].transform * bones[int(vBones.x)].bindPose * vec4(vPosition, 1.0) * vWeights.x;

如果我在Windows pc上运行此代码。它工作正常,但是当我使用emscripten将其编译到Web浏览器时。它给出gl错误1282(无效操作)。

如果我更改为GL_FLOAT,这将修复gl错误,但是,所有骨骼索引都变为0,并且我得到了无蒙皮的网格物体,因为骨骼0的单位矩阵为bindpose和worldpose矩阵。

最佳答案

ES 2.0不支持整数属性。从GLSL ES 1.00规范(与ES 2.0一起使用的GLSL版本)开始:



您可以执行的最接近的操作是在着色器代码中使用vec4,并在需要时将float值转换为整数。

如果您在客户端的数据是整数格式,则必须小心glVertexAttribPointer()调用。作为第4个参数传递的 bool(boolean) 值指定是否要对值进行规范化,或者是否应将它们转换为没有规范化的float值。对于您的情况,您将希望传递GL_FALSE。例如,如果您的客户端代码中包含字节数据:

glVertexAttribPointer(loc, 4, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);

ES 3.0及更高版本支持整数属性。因此,您可以在其中将ivec4用于属性,并在客户端代码中使用glVertexAttribIPointer()(请注意函数名称中的其他I)指定值。

07-24 14:08