OpenGL ES 3.0矩阵阵列仅使用第一个矩阵

时间:2013-12-04 23:12:49

标签: android opengl-es glsl glsles

我在顶点着色器中进行GPU换肤,这在PC上工作正常,而且我正在移植到Android。我的顶点着色器在下面,问题是matTransform矩阵的创建似乎只使用了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;
}

我已经确认:

1)正确的矩阵被推入boneMatrices
2)骨骼内存在正确的骨骼指数
3)骨重量中存在正确的骨重量 4)使用点符号(.x,.y,.z和.w)访问boneIndices的组件不会产生不同的结论 5)根本没有OpenGL错误,因为我在每次调用后检查错误,并且统一大小不是问题(如果我将boneMatrices增加5个额外矩阵,每次将矩阵推入到矩阵后,我都会得到无效的操作错误着色器,但是这个尺寸越低越好(

我通过执行以下操作检查了第1,2和3点(boneMatrices,boneIndices和boneWeights是否正确):

1)使用仅修改了几个骨骼的特定动画(例如boneMatrix [6]),然后硬编码boneMatrix [6]并验证所有顶点是否被此单个矩阵正确修改,在PC上具有相同的结果和Android

2)通过在顶点着色器中执行以下操作来绘制boneIndices:

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

以及片段着色器中的以下内容:

gl_FragColor = _colour

在PC和Android上使用相同的颜色

3)执行与上述相同的操作,但将_colour设置为:

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

我不知道还有什么可以尝试,而且肯定似乎只使用了第一个矩阵,并且由于某种原因,int(boneIndices [x])导致任何x的0。这是在带有OpenGL ES 3.0的Nexus 5上。救命啊!

编辑:考虑到Andon的建议,使用ivec4而不是vec4用于boneIndices不幸导致相同的结果,但至少这清楚地表明它不是浮动的投射问题。现在我觉得自己像一个没有任何线索的警察:/

1 个答案:

答案 0 :(得分:0)

最后,这看起来是Adreno驱动程序的一个限制,它不支持索引统一的矩阵数组而没有一个与OpenGL ES规范中强制要求相反的常数整数。然而,解决方法是使用统一的vec4数组,因为它似乎支持使用变量对这些进行索引(就像在SDK中一样)。