Glsl剥皮障碍,谁能跳过

Glsl skinning obstacle, who can jump that?

本文关键字:Glsl      更新时间:2023-10-16

我目前正在尝试设置GPU蒙皮(使用glsl),但它没有按我的方式工作:)实际上它根本不工作。当我尝试这个glsl代码时,我的网格消失了:

layout(location = 0) in vec3    vertexPos;
layout(location = 1) in vec2    vertexUv;
layout(location = 2) in vec3    vertexNor;
layout(location = 5) in ivec4   joints_influences;
layout(location = 6) in vec4    weights_influences;
uniform mat4    ViewProj, View, Proj, Model;
out vec3        vertexPosEye;
out vec3        vertexNorEye;
const int       MAX_INFLUENCES = 4;
const int       MAX_BONES = 50;
uniform mat4    animation_matrices[MAX_BONES];
uniform mat4    inv_bind_matrices[MAX_BONES];
void main()
{
    vertexPosEye = (View * Model * vec4(vertexPos, 1)).xyz;     // Position
    vertexNorEye = (View * Model * vec4(vertexNor, 0)).xyz;     // Normal matrix
    vec4 final_v = vec4(0, 0, 0, 0);
    for (int i = 0; i < MAX_INFLUENCES; i++)
    {
        vec4 v =        vec4(vertexPos, 1)
                    *   inv_bind_matrices[joints_influences[i]]
                    *   animation_matrices[joints_influences[i]]
                    *   weights_influences[i];
        final_v += v;
    }
    gl_Position =  ViewProj * Model * final_v;
}

当我尝试这个:

gl_Position =  ViewProj * Model * vertexPos;

我的网格回来了:)但当然不再有动画了。。。

以下是我设置VBO属性时的应用程序(c++)代码:

// Vertex position
glGenBuffers(1, &buffer[0]);
glBindBuffer(GL_ARRAY_BUFFER, buffer[0]);
glBufferData(GL_ARRAY_BUFFER, vertices.pos.size() * sizeof(bVector3), &vertices.pos[0], GL_STATIC_DRAW);
// Ibid for uv, normals, tangents and bitangents.
// Skinning : joints index
glGenBuffers(1, &buffer[5]);
glBindBuffer(GL_ARRAY_BUFFER, buffer[5]);
glBufferData(GL_ARRAY_BUFFER, vertices.joints.size() * sizeof(SkinningJoints), &vertices.joints[0], GL_STATIC_DRAW);
// Skinning : weights
glGenBuffers(1, &buffer[6]);
glBindBuffer(GL_ARRAY_BUFFER, buffer[6]);
glBufferData(GL_ARRAY_BUFFER, vertices.weights.size() * sizeof(SkinningWeights), &vertices.weights[0], GL_STATIC_DRAW);
// Indices
glGenBuffers(1, &buffer[7]);
glBindBuffer(GL_ARRAY_BUFFER, buffer[7]);
glBufferData(GL_ARRAY_BUFFER, vertices.indices.size() * sizeof(bUshort), &vertices.indices[0], GL_STATIC_DRAW);

在主循环中:

glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, m->GetBuffer(0));
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(for uv, normals, tangents and bitangents)...
glEnableVertexAttribArray(5);
glBindBuffer(GL_ARRAY_BUFFER, m->GetBuffer(5));
glVertexAttribPointer(5, 4, GL_INT, GL_FALSE, 0, BUFFER_OFFSET(0));
glEnableVertexAttribArray(6);
glBindBuffer(GL_ARRAY_BUFFER, m->GetBuffer(6));
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->GetBuffer(7));
glDrawElements(GL_TRIANGLES, m->vertices.indices.size(), GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));

这是我的RenderingVertices结构(根据Barr的建议):

struct RenderingVertices
{
    // std::vector<Vec3>
    vVec3                       pos, nor, tang, btan;
    vVec2                       uv;
    vUshort                     indices;
    vector<SkinningJoints>      joints;
    vector<SkinningWeights>     weights;
};

这是我的SkinningJoints结构:

struct SkinningJoints
{
    int         j[MAX_BONES_PER_VERT];
    SkinningJoints(Vertex::Weights weights[MAX_BONES_PER_VERT])
    {
        for (bUint i = 0; i < MAX_BONES_PER_VERT; i++)
            j[i] = weights[i].jid;
    }
};

我的SkinningWeights结构几乎相同,使用float数组而不是int。

现在,当我尝试调试关节索引、权重值和最终顶点作为颜色时,我得到的是:

// Shader
color_debug = joints_influences;

http://www.images-host.fr/view.php?img=00021800pop.jpg

color_debug = weights_influences;

http://www.images-host.fr/view.php?img=00021800pop2.jpg

另一件有趣的事情,当我尝试这个:

vec4 pop = vec4(vertexPos, 1) * animation_matrices[1] * inv_bind_matrices[1] * 1.0;
gl_Position =  ViewProj * Model * pop;

我的所有网格实际上都在旋转,这意味着我的统一动画贴图效果很好。

有人能看到我在这里做错了什么吗?

我终于让它工作起来了。对于那些可能感兴趣的人来说,我做错了什么:

当我向Glsl发送关节索引数组时,而不是这样做:

glEnableVertexAttribArray(5);
glBindBuffer(GL_ARRAY_BUFFER, m->GetBuffer(5));
glVertexAttribPointer(5, 4, GL_INT, GL_FALSE, 0, BUFFER_OFFSET(0));

我需要这样做:

glEnableVertexAttribArray(5);
glBindBuffer(GL_ARRAY_BUFFER, m->GetBuffer(5));
glVertexAttribIPointer(5, 4, GL_INT, 0, BUFFER_OFFSET(0));

你必须仔细观察才能发现差异。我需要调用glVertexAttribIPointer(),而不是调用glVertex AttribPoint(),因为关节索引是int

希望这有一天能帮助到别人。

是否尝试调试蒙皮属性?将顶点权重输出为颜色,以便确认是否具有有意义的值?如果所有东西都是黑色的,你就会知道去哪里找。

通过快速浏览RenderingVertices,我可以发现第一个问题。你正在向GL传递一个指针向量,我认为这不是你想要做的

大多数情况下,将蒙皮影响限制为每个顶点4个关节/权重对。因此,您可以使用一个简单的数组(即SkinningJoints关节[4];)。