LWJGL Forum

Programming => OpenGL => Topic started by: rherma on May 04, 2013, 15:53:50

Title: [Solved]Sending matrix array to GLSL vertex shader
Post by: rherma on May 04, 2013, 15:53:50
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.
Title: Re: Sending matrix array to GLSL vertex shader
Post by: quew8 on May 04, 2013, 20:27:24
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.
Title: Re: Sending matrix array to GLSL vertex shader
Post by: rherma on May 04, 2013, 21:31:28
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.
Title: Re: Sending matrix array to GLSL vertex shader
Post by: rherma on May 05, 2013, 13:12:51
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?
Title: Re: Sending matrix array to GLSL vertex shader
Post by: rherma on May 05, 2013, 13:49:16
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.