Скелетная анимация в OpenGL (GLSL) с Assimp
Я пытаюсь реализовать скелетную анимацию на основе GLSL в программе... и вместо красивой 3D-анимации я создал монстра: https://i.imgur.com/dmpKg6n.gif
Попробовав несколько разных техник, я создал менее ужасающую, но все же чудовищную вещь:
Модель - обычный человек в костюме, предполагается, что анимация - это качающаяся нога, а все остальное остается неподвижным (очень простая тестовая анимация). Все кости имеют статические ключевые кадры в момент времени t=0 в своих первоначальных местоположениях, чтобы минимизировать их выпрыгивание из места каждые несколько секунд.
Проблема... должна быть достаточно заметна. Кроме того, я уверен, что модель выше, чем должна быть.
Во всяком случае, это был мой оригинальный Vertex Shader:
#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
Новый шейдер был получен из поиска в Google наугад.
РЕДАКТИРОВАТЬ: Теперь я получаю это:
С этим кодом: http://pastebin.com/PvCWUdJn
Теперь... что я делаю не так?! Какой "правильный" способ справиться с этим? Есть ли более качественные учебники, которые я должен использовать вместо этого?
ОБНОВЛЕНИЕ: ПОЛНЫЙ КОД ИСТОЧНИКА ДЛЯ ТЕСТА APP: https://github.com/mcmonkey4eva/skeletalanimationtest
1 ответ
Таким образом, ответ прост - не умножайте матрицу х вектор, кратный вектор х матрицу в шейдере.