Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 6 of 6

Thread: Problems with using mat4 vertex attribute

  1. #1
    Junior Member Newbie
    Join Date
    Apr 2014
    Posts
    3

    Problems with using mat4 vertex attribute

    Hello!

    I've got this problem where i'm sending all my vertices in one buffer object and
    all it's model matrices in another. The problem is that is seems that vertex shader is only getting the first model matrix (or none)
    because all the models are drawn in the same place.

    Here is the init code:
    Code :
     
    GLint matrix_loc = glGetAttribLocation(mShaderProgram,"model_matrix");
     
    glGenBuffers(1, &mMatrixBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, mMatrixBuffer);
    // Loop over each column of the matrix...
    for (unsigned int i = 0; i < 4; i++)
    {
    	GLuint index = matrix_loc + i;
    	GLsizei stride = sizeof(glm::mat4);
    	GLsizei offset = (sizeof(GLfloat) * i * 4);
     
    	// Enable it
    	glEnableVertexAttribArray(index);
    	// Set up the vertex attribute
    	glVertexAttribPointer(index,             // Location
    					 4, GL_FLOAT, GL_FALSE,       // vec4
    					stride,                // Stride
    					 (const GLvoid*)offset); // Start offset
    	// Make it instanced
    	glVertexAttribDivisor(index, 1);
    }
    glBindVertexArray(0);

    Here is the data upload code:
    Code :
     
    Drawable* d = mDrawings[i];
     
    glm::mat4 mat = d->getMatrix();
    ModelData model = d->getData();
     
    std::vector<glm::mat4>& mats = mMatrices;
    for (int d = 0; d < model.size * 3; d += 3) {
            //upload vertices
    	glm::vec4 v = glm::vec4(model.vertices[d], model.vertices[d + 1],
    			model.vertices[d + 2], 1);
     
    	verts.push_back(v.x);
    	verts.push_back(v.y);
    	verts.push_back(v.z);
     
            //upload model matrices
    	mats.push_back(mat);
    }
     
    glBindBuffer(GL_ARRAY_BUFFER, mMatrixBuffer);
    glBufferData(GL_ARRAY_BUFFER,
    	sizeof(glm::mat4) * mMatrices.size(),
    	&mMatrices[0][0], drawType);

    And here is the vertex shader:

    Code :
    #version 330
     
    layout (location = 0) in vec3 position_vec;
    layout (location = 1) in vec3 normal_vec;
    layout (location = 2) in vec2 texture_vec;
    layout (location = 3) in mat4 model_matrix;
     
    out vec2 texture_vec0;                                                                 
    out vec3 normal_vec0;   
     
    uniform mat4 projection_view_mat;
     
    void main()
    {	
       gl_Position = projection_view_mat * model_matrix * vec4(position_vec,1); 
     
       texture_vec0 = texture_vec;
       normal_vec0 = normal_vec;
    }

    Edit:

    Draw method:
    Code :
     
    glUseProgramObjectARB(mShaderProgram);
     
    GLint PVMLoc = glGetUniformLocationARB(mShaderProgram, "projection_view_mat");
     
    glm::mat4 projView = mProjection * mView;
     
    glUniformMatrix4fv(PVMLoc, 1,
    	   GL_FALSE, &projView[0][0]);
     
    GLint loc1 = glGetUniformLocationARB(mShaderProgram, "tex");
     
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, 1);
    glUniform1iARB(loc1, 1);
    glBindVertexArray(mArrayBuffer); // Bind our Vertex Array Object
    glDrawArrays(GL_TRIANGLES, 0, mVertices.size()); // Draw our square
     
    glBindVertexArray(0); // Unbind our Vertex Array Object
    check_gl_error();
    }
    }
    Thanks.
    Last edited by tommila; 04-24-2014 at 11:24 PM. Reason: Added draw method

  2. #2
    Member Regular Contributor malexander's Avatar
    Join Date
    Aug 2009
    Location
    Ontario
    Posts
    345
    I don't see the code that's actually doing the draw call. Are you using an instanced draw method (glDrawArraysInstanced, glDrawElementsInstanced)? Otherwise the instance will always be 0 unless you use one of the ...BaseInstance draw variants.

  3. #3
    Junior Member Newbie
    Join Date
    Apr 2014
    Posts
    3
    I'm not in fact using any object instancing, just plain old glDrawArray. Is it even possible to use mat4 attribute without using instancing?
    I've tested the code by using only position vectors that I've pulled from the model matrices and then send them as vec3 attributes, and it works just fine.
    Last edited by tommila; 04-25-2014 at 12:40 AM.

  4. #4
    Intern Contributor
    Join Date
    Mar 2014
    Location
    San Jose, CA
    Posts
    58
    malexander probably thought you were using instancing because you have a glVertexAttribDivisor call in your code. I don't think it should do any harm, but you may want to keep that at 0 if you're not using instancing.

    I haven't been able to spot a problem with the setup of the matrix vertex attribute so far.

    You do have a problem with your texture setup, but that's probably unrelated. Assuming that "tex" is a sampler in your fragment shader, the value of the uniform variable must be the index of the texture unit you bind it to. In your case, you need to set the value of that uniform to 0. Also, how do you know that your texture id is 1? Are you using that as a fixed value? That might still work depending on the OpenGL profile you're using, but using your own texture ids is deprecated. You need to use glGenTextures() to generate the ids (or "names", as the spec likes to call them) in the core profile.

  5. #5
    Junior Member Newbie
    Join Date
    Apr 2014
    Posts
    3

    Post

    Quote Originally Posted by reto.koradi View Post
    malexander probably thought you were using instancing because you have a glVertexAttribDivisor call in your code. I don't think it should do any harm, but you may want to keep that at 0 if you're not using instancing...
    That did the trick
    Phew, been hammering this problem for days, thanks a bunch!

    Texturing hasn't been a issue, but i'll check setup nevertheless.

  6. #6
    Intern Contributor
    Join Date
    Mar 2014
    Location
    San Jose, CA
    Posts
    58
    Awesome, thanks for reporting back. I was initially surprised that it helped, because I expected that the value only mattered when instancing was used. But after going back to the spec, this is the value that actually enables instancing for the attribute:

    If divisor is zero, the attribute at slot index advances once per vertex. If divisor is non-zero, the attribute advances once per divisor instances of the set(s) of vertices being rendered.
    So you got the first vector out of your array for all the vertices.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •