Glsl剥皮的障碍,谁能跳?

时间:2012-02-17 16:16:22

标签: c++ opengl glsl skinning

我目前正在尝试设置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;
    }
};

My SkinningWeights结构几乎相同,浮点数而不是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;

我的所有网格实际上都在旋转,这意味着我的统一animation_matrices很好。

任何人都能看到我在这里做错了什么?

2 个答案:

答案 0 :(得分:4)

我终于开始工作了。对于那些可能感兴趣的人来说,这就是我做错了:

当我将关节索引数组发送到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));

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

希望有一天这会有所帮助。

答案 1 :(得分:2)

您是否尝试调试了皮肤属性?将顶点权重输出为颜色,以便确认您有有意义的值?如果一切都是黑色的,你就会知道在哪里看。

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

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