Hello.
I am trying to implement skeletal animation using glsl. The skeleton is an array of matrices, I load them into the shader like this:
public void setMatrixArray(String name,boolean transposed, Matrix4f[] matrices){
int location = uniformMap.get(name);
FloatBuffer matrixBuffer = BufferUtils.createFloatBuffer(16*matrices.length);
for(int i = 0; i<matrices.length; i++) {
matrices[i].store(matrixBuffer);
}
matrixBuffer.flip();
GL20.glUniformMatrix4(location,transposed,matrixBuffer);
}
This does not generate any errors.
My vertex shader looks like this:
#version 330
#define MAX_JOINT_COUNT 33 //The number of joints inside the model
uniform mat4 g_view;
uniform mat4 g_projection;
uniform mat4 g_world;
uniform mat4 g_skeleton[MAX_JOINT_COUNT];
layout(location = 0)in vec3 in_position;
layout(location = 1)in vec3 in_normal;
layout(location = 2)in vec2 in_uv;
layout(location = 3)in vec4 in_indices;
layout(location = 4)in vec4 in_weights;
layout(location = 5)out vec3 out_normal;
layout(location = 6)out vec2 out_uv;
void jointInfluence(in mat4 joint_matrix, in float weight, inout vec3 position)
{
position += weight * (joint_matrix * vec4(position, 1.0)).xyz;
}
void main()
{
out_normal = in_normal;
out_uv = in_uv;
jointInfluence(g_skeleton[int(in_indices.x)], in_weights.x, in_position);
jointInfluence(g_skeleton[int(in_indices.y)], in_weights.y, in_position);
jointInfluence(g_skeleton[int(in_indices.z)], in_weights.z, in_position);
jointInfluence(g_skeleton[int(in_indices.w)], in_weights.w, in_position);
gl_Position = g_projection * g_view * g_world * vec4(in_position,1.0);
}
As soon as I use the g_skeleton array I get the error: "Invalid operation". Note that the shader is compiling just fine and that the program is running.
I get the error string from GL11.glGetError().
I am obviously doing somthing illeagal with the g_skeleton variable, but I have no idea what that could be?
If i use a fixed index I still get the same error, eg:
jointInfluence(g_skeleton[0], in_weights.x, in_position);
jointInfluence(g_skeleton[0], in_weights.y, in_position);
jointInfluence(g_skeleton[0], in_weights.z, in_position);
jointInfluence(g_skeleton[0], in_weights.w, in_position);
How ever, if I use another matrix it works just fine, eg:
jointInfluence(g_world, in_weights.x, in_position);
jointInfluence(g_world, in_weights.y, in_position);
jointInfluence(g_world, in_weights.z, in_position);
jointInfluence(g_world, in_weights.w, in_position);
If some one could point me in the right direction it would be much appreciated.
You can get the error log with glGetShaderInfoLog. The log is vendor specific but one hopes that it will tell you what the problem is.
this code:
jointInfluence(g_skeleton[int(in_indices.x)], in_weights.x, in_position);
jointInfluence(g_skeleton[int(in_indices.y)], in_weights.y, in_position);
jointInfluence(g_skeleton[int(in_indices.z)], in_weights.z, in_position);
jointInfluence(g_skeleton[int(in_indices.w)], in_weights.w, in_position);
gl_Position = g_projection * g_view * g_world * vec4(in_position,1.0);
Yields:
Quote
Invalid operation (not this is not from the glGetShaderInfoLog)
WARNING: 0:34: warning(#398) l-value required: assign "in_position" (can't modify an input)
WARNING: 0:35: warning(#398) l-value required: assign "in_position" (can't modify an input)
WARNING: 0:36: warning(#398) l-value required: assign "in_position" (can't modify an input)
So I changed it to:
vec3 position = in_position;
jointInfluence(g_skeleton[int(in_indices.x)], in_weights.x, position);
jointInfluence(g_skeleton[int(in_indices.y)], in_weights.y, position);
jointInfluence(g_skeleton[int(in_indices.z)], in_weights.z, position);
jointInfluence(g_skeleton[int(in_indices.w)], in_weights.w, position);
gl_Position = g_projection * g_view * g_world * vec4(position,1.0);
Now I don't get warnings from the shader log. How ever, the glGetError still gives me the "Invalid operation".
It feels like the error has to do with my g_skeleton variable, maybe the way I am uploading the matrices?
Anyways, thanks for the tip about glGetShaderInfoLog, very usefull.
I checked out the documentation for glUniformMatrix4.
There is one function that seems to do exactly what I am trying to do:
void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value);
How ever, LWJGL has not ported that function.
Is there some usage example how to upload a list of matrices to a unform variable?
Well this is akward ;)
I set the skeleton variable before i draw each mesh in the model. I bind the shader when i draw a mesh, not before. So my shader is not set when I try to set the skeleton variable, hence the error.
So the sytax for uploading a matrix array is correct.