OpenGL ES 3.0 matrix array only using first matrix

喜欢而已 提交于 2019-12-12 00:43:51

问题


I am doing GPU skinning in my vertex shader which works fine on PC, and which I'm porting to Android. My vertex shader is below, and the problem is that the creation of the matTransform matrix seems to only use the first matrix in boneMatrices:

#version 300 es

precision highp float;
precision highp int;

//Uniform count: projectionMatrix(16) + modelViewMatrix(16) + MVPMatrix(16) + textureMatrix(16) + normalMatrix(9) + lightMVPMatrices(16*5) + nShadowLights(1) + boneMatrices(16*boneMax)  = 73 + 1 + 16*shadowLightMax + 16*boneMax = (out of ~1024 components)
//GLSL ES (vectors): projectionMatrix(4) + modelViewMatrix(4) + MVPMatrix(4) + textureMatrix(4) + normalMatrix(3) + lightMVPMatrices(4*5) + nShadowLights(1) + boneMatrices(4*boneMax) = 19 + 4*shadowLightMax + 4*boneMax = 239 out of 256 vectors on Nexus 5 (shadowLightMax = 5, boneMax = 50, 17 vec4s remain, or 4 matrices and 1 vec4)
//Matrices
//uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat4 MVPMatrix;
uniform mat4 textureMatrix;
uniform mat3 normalMatrix;
uniform mat4 lightMVPMatrices[5];
uniform int nShadowLights;

//Bones
uniform mat4 boneMatrices[50];

//Vertex information
in vec3 position;
in vec4 colour;
in vec2 texCoord;
in vec3 normal;
in vec3 boneWeights;
in vec4 boneIndices;

out vec4 _colour;
out vec2 _texCoord;
out vec3 _normal;
out vec3 _eyePos;
out vec4 _lightPos[5];

void main(void)
{
    vec4 positionSkinned;
    vec4 normalSkinned;

    mat4 matTransform = boneMatrices[int(boneIndices[0])] * boneWeights[0];
    matTransform += boneMatrices[int(boneIndices[1])] * boneWeights[1];
    matTransform += boneMatrices[int(boneIndices[2])] * boneWeights[2];
    float finalWeight = 1.0 - (boneWeights[0] + boneWeights[1] + boneWeights[2]);
    matTransform += boneMatrices[int(boneIndices[3])] * finalWeight;

    positionSkinned = matTransform * vec4(position, 1.0);
    //positionSkinned.w = 1.0;
    normalSkinned = matTransform * vec4(normal, 0.0);

    gl_Position = MVPMatrix * positionSkinned;
    _colour = colour;
    _texCoord = (textureMatrix * vec4(texCoord, 0.0, 1.0)).xy;
    _normal = normalize(normalMatrix * normalize(normalSkinned.xyz));
    _eyePos = (modelViewMatrix * positionSkinned).xyz;
    for(int i = 0; i < nShadowLights; i++)
        _lightPos[i] = lightMVPMatrices[i] * positionSkinned;
}

I have verified that:

1) the correct matrices get pushed into boneMatrices
2) the correct bone indexes exist within boneIndices
3) the correct boneWeights exist within boneWeights
4) accessing components of boneIndices with dot notation (.x, .y, .z and .w) doesn't make a different
5) There are no OpenGL errors at all, as I check for errors after every call, and uniform size isn't an issue (if I increase boneMatrices by 5 extra matrices, I get invalid operation errors after each time I push matrices to the shader, but at this size and lower it's fine)

I have checked points 1, 2 and 3 (boneMatrices, boneIndices and boneWeights are correct) by doing the following:

1) using a specific animation which modified a few bones only (e.g. boneMatrix[6]), then hard-coding boneMatrix[6] and verifying that all vertices get properly modified by this single matrix, with the same result on PC and Android

2) drawing out boneIndices by doing the following in the vertex shader:

_colour = vec4(boneIndices[0], boneIndices[1], boneIndices[2], boneIndices[3]);

and the following in the fragment shader:

gl_FragColor = _colour

with the same colours on PC and Android

3) doing the same as above but with setting _colour to:

_colour = vec4(boneWeights[0], boneWeights[1], boneWeights[2], finalWeight);

I have no idea what else to try, and it definitely seems to be that only the first matrix is used and that for some reason, int(boneIndices[x]) results in 0 for any x. This is on a Nexus 5 with an OpenGL ES 3.0. Help!

EDIT: Taking Andon's advice of using ivec4's instead of vec4's for boneIndices unfortunately results in the same result, however at least this clears up that it isn't a casting issue from float. Now I feel like a cop without any leads :/


回答1:


In the end this looks to be a limitation of the Adreno driver, which doesn't support indexing a uniform array of matrices without a constant integer contrary to what is mandatory within the OpenGL ES spec. A workaround however is to just use a uniform array of vec4s, as it does seem to support indexing these with variables (as is done within their SDK).



来源:https://stackoverflow.com/questions/20388086/opengl-es-3-0-matrix-array-only-using-first-matrix

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!