首页 > 解决方案 > 如何为着色器的每个顶点提供 14 个浮点值?

问题描述

我已经下载了一个模型,并将其导出为.fbx. 该模型包含几个动画(准确地说是 6 个),我想显示其中一个。根据 Anton Gerdelan 关于 openGL 的书,我编写了一个导入器,它使用 assimp 解析模型、缓冲相关顶点数据并检索动画所需的偏移矩阵。

在骨骼动画方面没有太多经验,我我已经能够对 anton 的导入器进行必要的更改,以便它可以在我需要的更复杂的模型上工作。但是,导入器假设每个顶点仅受 1 个骨骼影响,但不幸的是,情况并非如此。

经过一番修改,我发现模型的每个顶点一次最多可以受到 14 个骨骼的影响。由于我不确定如何将 14 个值传递给包含boneId相关内容的着色器,因此weight我尝试更改代码以一次最多容纳 4 个骨骼。这是解析骨骼 id 和权重并缓冲它们的代码:

    *bone_count = (int)mesh->mNumBones;
    char bone_names[256][64];

    struct vertexdata {
        int IDs[4];
        float Weights[4];
        int ptr;
    };

    vector<vertexdata> vdata;
    vdata.resize(*point_count);

    for (int i = 0; i < *point_count; i++) {
        vdata[i].ptr = 0;
    }

    for (int b_i = 0; b_i < *bone_count; b_i++) {
        const aiBone* bone = mesh->mBones[b_i];
        strcpy(bone_names[b_i], bone->mName.data);
        printf("bone_names[%i]=%s\n", b_i, bone_names[b_i]);
        bone_offset_mats[b_i] = convert_assimp_matrix(bone->mOffsetMatrix);

        //getting weights for each bone
        int num_weights = (int)bone->mNumWeights;
        for (int w_i = 0; w_i < num_weights; w_i++) {
            aiVertexWeight weight = bone->mWeights[w_i];

            int vid = weight.mVertexId;
            float vweight = weight.mWeight;

            if (vdata[vid].ptr < 4) {
                vdata[vid].IDs[vdata[vid].ptr] = b_i;
                vdata[vid].Weights[vdata[vid].ptr] = vweight;
                vdata[vid].ptr++;
            }


            int vertex_id = (int)weight.mVertexId;
        }

    }


    //buffering bone id data
    GLuint vbo1;
    glGenBuffers(1, &vbo1);
    glBindBuffer(GL_ARRAY_BUFFER, vbo1);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vdata[0]) * vdata.size(), &vdata[0], GL_STATIC_DRAW);

    glEnableVertexAttribArray(3);
    glVertexAttribIPointer(3, 4, GL_INT, sizeof(vertexdata), (const GLvoid*)0);

    glEnableVertexAttribArray(4);
    glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(vertexdata), (const GLvoid*)16); 

在着色器中:

顶点着色器

#version 330 core

layout (location = 0) in vec3 pos;
layout (location = 1) in vec3 norm;
layout (location = 2) in vec2 UV;
layout (location = 3) in ivec4 boneIDs;
layout (location = 4) in vec4 Weights;

uniform mat4 view, projection, model;
uniform mat4 bone_matrices[40];

out vec2 tCoords;

void main()
{
    mat4 boneTransform = bone_matrices[boneIDs[0]] * Weights[0];
    boneTransform += bone_matrices[boneIDs[1]] * Weights[1];
    boneTransform += bone_matrices[boneIDs[2]] * Weights[2];
    boneTransform += bone_matrices[boneIDs[3]] * Weights[3];

    tCoords = UV;
    gl_Position = projection * view * boneTransform * model  * vec4(pos, 1.0);
}  

片段着色器

#version 330 core

in vec2 tCoords;
out vec4 fragColour;

uniform sampler2D tex;

void main()
{   
    fragColour = texture(tex, tCoords); 
}

模型渲染正确,但我没有观察到任何运动。同样,对骨骼动画了解不多,我只能假设这是因为我没有包括影响每个顶点的每个骨骼以及相应的权重。但是,在缓冲数据时,着色器最多只能接受vec4每个顶点 4 个值。如何传递 14 个 ID 和 14 个权重?这可能是动画无法正常工作的原因吗?

标签: c++openglglsl

解决方案


推荐阅读