Search code examples
openglglslvertex-shader

sending array to shader with glUniformMatrix


I have a model with for which all matdexs (read matrix index) are either 0, 1, and 2 roughly evenly distributed. bonebends[matdex[whichvertex]] tells us which matrix should be used on this vertex.
initializing, c++:

std::vector< GLint >  matdex; //initialized to 0, 1, or 2 for each vertex loaded, not shown for brevity
std::vector<glm::mat4> bonebends;
int frames=0;
bonebends.push_back(glm::mat4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)); //identity matrices initially
bonebends.push_back(glm::mat4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1));
bonebends.push_back(glm::mat4(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)); // thats 3 bones
ver_ind = glGetAttribLocation(shaderID, "VER_IND");
boneID = glGetUniformLocation(shaderID, "BONE_MATRIX[0]");
glGenBuffers(1, &ind_buff);
glBindBuffer(GL_ARRAY_BUFFER, ind_buff);
glBufferData(GL_ARRAY_BUFFER, matdex.size() * sizeof(GLint), &matdex[0], GL_STATIC_DRAW);

periodically in main loop, c++:

glEnableVertexAttribArray(3); //IND
glBindBuffer(GL_ARRAY_BUFFER, ind_buff);
glVertexAttribPointer( ver_ind, 1, GL_INT, GL_FALSE, 0, (void*)0 );
//ALSO LOOK HERE
glUniformMatrix4fv(boneID, 3 , GL_FALSE, &bonebends[0][0][0]);
frames+=1;
float cs=cos(3.14*2.0*(frames/100.0));
float sn=sin(3.14*2.0*(frames/100.0));
//  LOOK HERE
bonebends[0]=glm::mat4(
cs ,  0,-sn,0  ,
0 ,  1,  0,0  ,
sn,  0, cs,0  ,
0 ,  0,  0,1  );

in the shader, glsl:

layout(location = 3) in int VER_IND;
uniform mat4 BONE_MATRIX[3];

in the main function of shader, glsl:

gl_Position =  BONE_MATRIX[VER_IND] * vec4(VER_POS,1); //VER_POS is the vertex's coordinates

I hoped this would make all the vertices with a coinciding matdex of 0 to rotate, and the rest remain stationary. Instead this displays the model (which is otherwise rendered correctly) spinning, as if all matdexs values are equal to 0. Which a little couting tells me they are not. I don't know how to debug VER_IND in the shader.
I tried

  • using uint instead of int for all incarnations of matdex, which didn't make a difference.
  • Changing BONE_MATRIX[VER_IND] to BONE_MATRIX[0] in shader, which made it crash(???)
  • Changing the second and fourth argument of glUniformMatrix4fv(boneID, 3 , GL_FALSE, &bonebends[0][0][0]); in various ways, didn't help.
  • changed matdexs values such that none of them were 0, and it still rotates as if the shader is only using BONE_MATRIX[0].
  • Changing the line below // LOOK HERE to bonebends[1]=glm::mat4( results in the model not spinning at all.

From this I concluded that its only ever using the first of BONE_MATRIX[3], probably because the shader isn't receiving it correctly. I can post the whole thing but its a bit lengthy.
I would like to know what I am doing wrong and how to get information back from the shader.


Solution

  • There are a lot of problems.

    First, matdex is empty. So you're not getting any actual information.

    Second,

    layout(location = 3) in int VER_IND;
    
    glVertexAttribPointer( ver_ind, 1, GL_INT, GL_FALSE, 0, (void*)0 );
    

    These two things cannot work together. glVertexAttribPointer can only feed floating-point inputs. If you use integer formats like GL_INT, they will be converted to floats. If you want to feed integer inputs, you must use glVertexAttribIPointer (note the I).

    Or just make VER_IND a float. And pass GLubytes instead of GLints. Really, there's no point in taking up all of that memory.

    Third:

    glEnableVertexAttribArray(3); //IND
    glVertexAttribPointer( ver_ind, 1, GL_INT, GL_FALSE, 0, (void*)0 );
    

    The first parameter of both of these functions should be the same, if you're trying to enable ver_ind.

    Fourth:

    //ALSO LOOK HERE
    glUniformMatrix4fv(boneID, 3 , GL_FALSE, &bonebends[0][0][0]);
    

    I don't see where you use glUseProgram to set the program you wanted to change the uniform data on.

    Fifth:

    //  LOOK HERE
    bonebends[0]=glm::mat4(
    

    Changing a value after you have uploaded it does not magically cause the uploaded value to change.

    There may be (and likely are) more problems, but the code you posted is incomplete and I don't intend to be your personal debugger. At the very least, start with code that you know works, then make the smallest change leading towards what you want. Get that working, then make another change. And so on. You did a bunch of stuff all at once, and it didn't work out.