Android OpenGL ES 3.0 骨骼动画出现 UBO 故障

Android OpenGL ES 3.0 Skeletal Animations glitch with UBO

过去 2 天的大部分时间我都在寻找我只在某些设备上遇到的 OpenGL ES 错误。详细:

我正在尝试使用以下 GLSL 代码实现骨骼动画:

#ifndef NR_BONES_INC
#define NR_BONES_INC

#ifndef NR_MAX_BONES
#define NR_MAX_BONES 256
#endif

in ivec4 aBoneIds;
in vec4 aBoneWeights;

layout (std140) uniform boneOffsets { mat4 offsets[NR_MAX_BONES]; } bones;

mat4 bones_get_matrix() {
    mat4 mat = bones.offsets[aBoneIds.x] * aBoneWeights.x;
    mat += bones.offsets[aBoneIds.y] * aBoneWeights.y;
    mat += bones.offsets[aBoneIds.z] * aBoneWeights.z;
    mat += bones.offsets[aBoneIds.w] * aBoneWeights.w;

    return mat;
}

#endif

然后将其包含在顶点着色器中并按如下方式使用:

vec4 viewPos = mv * bones_get_matrix() * vec4(aPos, 1.0);
gl_Position = projection * viewPos;

我的 M1 MacBook Pro 上的 Android 仿真器 (armv8) 运行ning 上实现的所需输出是这样的:

遗憾的是,我实际上无法捕获故障设备(Espon Moverio BT-350,Android 在 x86 Intel Atom 上)的输出,但它基本上是相同的图片,没有头、手臂或腿。

为了测试,绑定到 boneOffsets 的统一缓冲区被创建为 std::vector<glm::mat4>,大小为 256,并且 created/bound 是这样的:

GLint buffer = 0;
std::vector<glm::mat4> testData(256, glm::mat4(1.0));
glGenBuffers(1, &buffer);
glBindBuffer(GL_UNIFORM_BUFFER, buffer);
glBufferData(GL_UNIFORM_BUFFER, sizeof(glm::mat4) * testData.size(), &testData[0], GL_DYNAMIC_DRAW);

glBindBufferBase(GL_UNIFORM_BUFFER, 0, buffer);
glUniformBlockBinding(programId, glGetUniformBlockIndex(programId, "boneOffsets"), 0); 

我是不是在我的设置中遗漏了某个步骤?这是我遇到的 GPU 错误吗?我是否误解了 std140 布局?

P.S.: 每次 OpenGL 调用后,我 运行 glGetError(),但没有任何显示。着色器和程序的各种信息日志中也没有任何内容。

编辑

第二天,我尝试跳过 UBO 并使用普通的统一数组(100 个元素而不是 256 个元素,无论如何我的模型有 70 根左右的骨头)。结果相同。

我也刚刚尝试过“纹理”。这是一个 4*256 GL_RGBAF teture,它是这样“采样”的:

uniform sampler2D bonesTxt;

mat4 read_bones_txt(int id) {
    return mat4(
        texelFetch(bonesTxt, ivec2(0, id), 0),
        texelFetch(bonesTxt, ivec2(1, id), 0),
        texelFetch(bonesTxt, ivec2(2, id), 0),
        texelFetch(bonesTxt, ivec2(3, id), 0));
}

仍然没有骰子。正如评论所建议的那样,我检查了我的骨骼 ID 和权重。我发送给 glBufferData() 的内容没问题,但我实际上无法检查 GPU 上有什么,因为我无法让 RenderDoc(或其他任何东西)在我的设备上工作。

终于想通了

绑定我的骨骼 ID 时,我使用 glVertexAttribPointer() 而不是 glVertexAttribIPointer()

我正在向 glVertexAttribPointer() 发送正确的类型 (GL_INT),但我没有阅读文档中的这一行:

For glVertexAttribPointer() [...] values will be converted to floats [...]

像往常一样,RTFM 人。