Search code examples
c++opengl-esemscriptenglsles

ivec4 as vertex attribute Opengl ES 2.0


I use openglEs 2.0. I am working on hardware skinning. I try to pass bone indices as ivec4 however compiler tells me that it is impossible to use ivec4 as vertex attribute. How can I overcome this stuation ?

Here is my Vertex shader code.

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;"
    "}";

UPDATE:

As I have been told, I changed shader code and client side code. Here is the client side code :

glEnableVertexAttribArray(3); // Bones
glVertexAttribPointer(3, 4, GL_INT, GL_FALSE, object->m_mesh->GetVertexSize(), (const void*)offset);

And this is how I access to bone indices in the shader code :

gl_Position = bones[int(vBones.x)].transform * bones[int(vBones.x)].bindPose * vec4(vPosition, 1.0) * vWeights.x;

If I run this code on windows pc. It works just fine, However when I compiled it with emscripten to web browsers. It gives gl error 1282 (Invalid Operation).

If I change to GL_FLOAT this fixes gl error however, all bone indices becomes 0 and I get a none skinned mesh because bone 0 has unit matrixes as bindpose and worldpose matrix.


Solution

  • Integer attributes are not supported in ES 2.0. From the GLSL ES 1.00 spec (which is the GLSL version used with ES 2.0):

    The attribute qualifier can be used only with the data types float, vec2, vec3, vec4, mat2, mat3, and mat4.

    The closest you can do is use vec4 in the shader code, and cast the float values to integers where needed.

    If your data on the client side is in an integer format, you have to be careful about your glVertexAttribPointer() call. The boolean passed as the 4th argument specifies if you want the values to be normalized, or if they should be converted to float without normalization. In your case, you will want to pass GL_FALSE. For example, if you have byte data in your client code:

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

    ES 3.0 and higher support integer attributes. So there you can use ivec4 for an attribute, and specify the values with glVertexAttribIPointer() (note the additional I in the function name) in your client code.