【问题标题】:OpenGL ES 3.0 matrix array only using first matrixOpenGL ES 3.0 矩阵数组仅使用第一个矩阵
【发布时间】:2014-05-27 22:52:53
【问题描述】:

我正在我的顶点着色器中进行 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) boneIndices 中存在正确的骨骼索引
3) boneWeights 中存在正确的 boneWeights
4) 使用点表示法(.x、.y、.z 和 .w)访问 boneIndices 的组件并没有什么不同
5) 根本没有 OpenGL 错误,因为我在每次调用后检查错误,并且统一大小不是问题(如果我将 boneMatrices 增加 5 个额外的矩阵,每次将矩阵推送到着色器,但在这个尺寸和更低的情况下就可以了)

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

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

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

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

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

gl_FragColor = _colour

在 PC 和 Android 上具有相同的颜色

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

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

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

编辑:不幸的是,采用 Andon 的建议使用 ivec4 而不是 vec4 的 boneIndices 会导致相同的结果,但至少这清楚地表明这不是浮动的铸造问题。现在我感觉自己像个没有任何线索的警察:/

【问题讨论】:

  • 有什么特别的原因使用浮点向量来存储索引? ivec4 会更有意义。您可以使用glVertexAttribIPointer (...) 为整数顶点属性提供数据。在这个 GLSL 程序中,您可能也快用完统一位置,50 个mat4s 的数组本身就使用了 200 个统一位置,而 GL ES 3.0 只需要总共提供 256 个。如果这是一个片段着色器,你已经超过了 224 的限制。
  • 我一时想不起来了,但我确实记得我前一段时间这样做时有某种原因(我认为是我读过的东西)。我将尝试将其更改为使用整数,看看是否可行。是的,在 cmets 的着色器顶部为 GL ES 完成了统一空间计算:)
  • 不幸的是,我做了这些更改并得到了相同的结果。我还通过再次将 ivec4 boneIndices 输出为颜色_colour = vec4(float(boneIndices.x), float(boneIndices.y), float(boneIndices.z), float(boneIndices.w)); 来验证更改是否正确。 Here 是它在 Windows 上的图像,显​​示了所有正在使用的骨骼矩阵,here 是 Android 的屏幕截图,仅显示第一个被使用(骨骼索引用于颜色)。
  • 如果您可以分享您如何将 50 矩阵数组发送到顶点着色器,那就太好了。我正在努力解决这部分问题。
  • 我将它们作为 vec4 数组而不是矩阵发送,因为 Adreno SDK 就是这样做的:glUniform4fv(boneUniformLocation, bones.size()*16, (GLfloat*) &amp;bones[0].values[0]); 其中bones 是具有 16 个 GLfloat 的矩阵数组。

标签: android opengl-es glsl glsles


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2019-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-11
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 2011-10-02
    相关资源
    最近更新 更多