I'm working on an ASSIMP skeletal animation loader and renderer and right now all the data is correctly loaded and interpolated at its current timeframe. However, there is still one part that isn't working as it should and that's the vertex shader stage.
Via a VBO I pass in two vec4
s that contain the bone IDs and the weights for each vertex (up to a maximum of 4 bones/weights per vertex) and the vertex shader has a matrix array of 100 bone transformations (pre-calculated per frame) that are indexed via the bone IDs.
However, it seems that the bones uniform doesn't contain the proper transformations. For debugging purposes I colored the model with the weight values and the bone IDs value and they contain a color (and thus valid values). However, when I transform my vertex via the bone transformation and color the model with the result, the entire model is colored black, meaning the transformation matrices are all 0.0
. So they're not initialized properly.
I think the problem is with passing the matrices to the uniform array, or perhaps the maximum size of uniforms allowed (I also tried setting the number of uniform matrices to 32 (number of bones on current model) but without effect)?
Before passing the information to the shader, the transformation matrices are indeed valid matrices (not identity/empty matrices) so the fault should probably be in the GLSL shader or the passing of the uniforms.
The following code is from the vertex shader:
#version 330
layout (location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec3 tangent;
layout(location = 3) in vec3 color;
layout(location = 4) in vec2 texCoord;
layout(location = 5) in ivec4 boneIDs;
layout(location = 6) in vec4 weights;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform mat4 bones[100];
out vec2 TexCoord;
out vec4 colorz;
void main()
{
vec4 newPos = vec4(position, 1.0);
colorz = vec4(0.0, 1.0, 0.0, 1.0);
if (weights != vec4(0.0, 0.0, 0.0, 0.0))
{
mat4 boneTransform = bones[boneIDs[0]] * weights[0];
boneTransform += bones[boneIDs[1]] * weights[1];
boneTransform += bones[boneIDs[2]] * weights[2];
boneTransform += bones[boneIDs[3]] * weights[3];
// newPos = boneTransform * vec4(position, 1.0);
vec4 test = vec4(1.0);
colorz = boneTransform * test;
// newPos = boneTransform * newPos;
}
TexCoord = texCoord;
gl_Position = projection * view * model * newPos;
}
The following snippet of code pass the matrix data to the GLSL shader:
// Sets bone transformation matrices
void Shader::SetBoneMatrix(GLint index, aiMatrix4x4 matrix)
{
glm::mat4 mat = glm::transpose(glm::make_mat4(&matrix.a1));
glUniformMatrix3fv(boneLocations[index], 1, GL_FALSE, glm::value_ptr(mat));
}
Also the code that gets all the uniform locations of the bones array:
for(unsigned int i = 0; i < 100; i++)
{
string name = "bones[";
string number;
stringstream ss;
ss << i;
ss >> number;
name += number;
name += ']';
boneLocations[i] = glGetUniformLocation(this->program, name.c_str());
}
gl_Position = projection * view * model * newPos;
thenewPos
variable is there multiplied by the MVP matrix. – Joey Dewd