带有 Assimp 的 OpenGL (GLSL) 中的骨骼动画

Posted

技术标签:

【中文标题】带有 Assimp 的 OpenGL (GLSL) 中的骨骼动画【英文标题】:Skeletal Animation in OpenGL (GLSL) with Assimp 【发布时间】:2015-04-28 23:34:42 【问题描述】:

我正在尝试在程序中实现由 GLSL 驱动的骨骼动画...而不是漂亮的 3D 动画,我创建了一个怪物:https://i.imgur.com/dmpKg6n.gif

在尝试了几种不同的技术之后,我创造了一个不那么可怕但仍然可怕的东西

模型是一个穿着西装的基本人,动画应该是腿摆动,而其他一切都保持不动(一个非常简单的测试动画)。 所有骨骼在其原始位置的 t=0 处都有静态关键帧,以尽量减少它们每隔几秒跳出的位置。

问题...应该相当明显。另外,我很确定模型比它应该的要高。

无论如何,这是我最初的顶点着色器:

#version 430 core
layout (location = 0) in vec4 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texcoords;
layout (location = 3) in vec4 color;
layout (location = 4) in vec4 Weights;
layout (location = 5) in vec4 BoneID;
layout (location = 0) out vec4 f_position;
layout (location = 1) out vec3 f_normal;
layout (location = 2) out vec2 f_texcoord;
const int MAX_BONES = 50;
layout (location = 1) uniform mat4 proj_matrix;
layout (location = 2) uniform mat4 mv_matrix;
layout (location = 6) uniform mat4 boneTrans[MAX_BONES];
void main(void)

mat4 boneTransform = (boneTrans[int(BoneID[0])] * Weights[0]) +
(boneTrans[int(BoneID[1])] * Weights[1]) +
(boneTrans[int(BoneID[2])] * Weights[2]) +
(boneTrans[int(BoneID[3])] * Weights[3]);
float rem = 1 - (Weights[0] + Weights[1] + Weights[2] + Weights[3]);
boneTransform += mat4(1.0) * rem;
f_texcoord = texcoords;
f_position = mv_matrix * (boneTransform * position);
mat4 mv_mat_simple = mv_matrix;
mv_mat_simple[3][0] = 0.0;
mv_mat_simple[3][1] = 0.0;
mv_mat_simple[3][2] = 0.0;
vec4 norm1 = boneTransform * vec4(normal, 1.0);
vec4 nnormal = mv_mat_simple * vec4(norm1.xyz, 1.0);
f_normal = nnormal.xyz / nnormal.w; // TODO: Normalize?
vec4 pos1 = boneTransform * position;
gl_Position = proj_matrix * mv_matrix * vec4(pos1.xyz, 1.0);

这是我的新的:

#version 430 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec2 texcoords;
layout (location = 3) in vec4 color;
layout (location = 4) in vec4 Weights;
layout (location = 5) in vec4 BoneID;

layout (location = 0) out vec4 f_position;
layout (location = 1) out vec3 f_normal;
layout (location = 2) out vec2 f_texcoord;

const int MAX_BONES = 50;

layout (location = 1) uniform mat4 proj_matrix;
layout (location = 2) uniform mat4 mv_matrix;
layout (location = 6) uniform mat4 boneTrans[MAX_BONES];

void main(void)

    vec4 pos1 = vec4(position, 1.0);
    pos1 += (boneTrans[int(BoneID[0])] * vec4(position, 0.0)) * Weights[0];
    pos1 += (boneTrans[int(BoneID[1])] * vec4(position, 0.0)) * Weights[1];
    pos1 += (boneTrans[int(BoneID[2])] * vec4(position, 0.0)) * Weights[2];
    pos1 += (boneTrans[int(BoneID[3])] * vec4(position, 0.0)) * Weights[3];
    vec4 norm1 = vec4(normal, 1.0);
    norm1 += (boneTrans[int(BoneID[0])] * vec4(normal, 0.0)) * Weights[0];
    norm1 += (boneTrans[int(BoneID[1])] * vec4(normal, 0.0)) * Weights[1];
    norm1 += (boneTrans[int(BoneID[2])] * vec4(normal, 0.0)) * Weights[2];
    norm1 += (boneTrans[int(BoneID[3])] * vec4(normal, 0.0)) * Weights[3];
    f_texcoord = texcoords;
    f_position = mv_matrix * vec4(pos1.xyz, 1.0);
    mat4 mv_mat_simple = mv_matrix;
    mv_mat_simple[3][0] = 0.0;
    mv_mat_simple[3][1] = 0.0;
    mv_mat_simple[3][2] = 0.0;
    //vec4 norm1 = boneTransform * vec4(normal, 1.0);
    vec4 nnormal = mv_mat_simple * vec4(norm1.xyz, 1.0);
    f_normal = nnormal.xyz / nnormal.w; // TODO: Normalize?
    gl_Position = proj_matrix * mv_matrix * vec4(pos1.xyz, 1.0);

骨骼处理代码既不漂亮也不简短:http://pastebin.com/A8x1GdUw

该代码和原始着色器源自http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html

新的着色器是随机谷歌搜索得出的。

编辑:我现在明白了:

使用此代码:http://pastebin.com/PvCWUdJn

现在……我做错了什么?!处理这个问题的“正确”方法是什么?有没有我应该使用的更高质量的教程来代替这个?

更新:测试应用程序的完整源代码:https://github.com/mcmonkey4eva/skeletalanimationtest

【问题讨论】:

确保the N64 cartridge is fully seated at all times。 我添加了一个测试应用程序的完整源代码来证明这个问题:github.com/mcmonkey4eva/skeletalanimationtest 【参考方案1】:

所以答案很简单——不要在着色器中乘矩阵 x 向量,多向量 x 矩阵。

【讨论】:

以上是关于带有 Assimp 的 OpenGL (GLSL) 中的骨骼动画的主要内容,如果未能解决你的问题,请参考以下文章

我的OpenGL学习进阶之旅Assimp库支持哪些3D模型格式?

使用 ASSIMP 和 OpenGL 加载 3D 模型时纹理不正确

OpenGL GLSL 通过任意形状混合两个纹理

OpenGL-Assimp库的下载编译及使用

通过 OpenGL Assimp 加载的对象有时会反转法线

渲染在 OpenGL 中使用 Assimp 加载的动画模型时折叠的网格