Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modern OpenGL: VBO, GLM and Matrix Stacks

After searching and reading about Modern OpenGL in order to upgrade my existing project, I'm a bit confused, since my 3D framework based on OpenGL 2.1.

so, as far as I learn...

  • We need to generate our Vertex-Buffer-Objects from vertices, indices, normals, colors, uvs, etc.

  • then we can use GLM for matrix transformation, and we only use VBO to create or manipulate meshes, finally we pass everything into GLSL vertex shader like this...

    glm::mat4 MVP = projection * view * model;
    glUniformMatrix4fv(glGetUniformLocation(shaderProgramID, "MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); //or &MVP[0][0]
    
    // uniform mat4 MVP;
    // in vec3 Vertex;
    // void main(void)
    // {
    //    gl_Position = MVP * vec4(Vertex, 1.0); //instead of ftransform();
    // }
    

QUESTION: How we do hierarchical transformations without pushMatrix/popMatrix? (or maybe we do hierarchical transformation by using our VBOs, is it possible?)

If not possible, then how to achieve same result as pushMatrix/popMatrix by using GLM and C++ < stack > library?

Lets say I need something like this:

> Set identity
> Translate to X, Y, Z
> Draw Mesh 1
> Rotate 0.5 by X axis
> Draw Mesh 2
> Scale down to 0.1
> Draw Mesh 3
like image 295
xxx Avatar asked Jan 21 '12 07:01

xxx


3 Answers

If your rendering already happens hierarchically using, for example, function recursion then you already have matrix stack!

void renderMesh(Matrix transform, Mesh mesh)
{
    // here call glDrawElements/glDrawArrays and send transform matrix to MVP uniform
    mesh->draw(transform);

    // now render all the sub-meshes, then will be transformed relative to current mesh
    for (int i=0; i<mesh->subMeshCount(); i++)
    {
        Matrix subMeshTransform = mesh->getSubMeshTransform(i);
        Mesh subMesh = mesh->getSubMesh();

        renderMesh(subMeshTransform * transform, subMesh);
    }
}

// somwhere in main function
...
Matrix projection = Matrix::perspective(...);
Matrix view = camera->getViewMatrix();

Matrix transform = view * projectIon;
renderMesh(transform, rootMesh);
like image 66
Mārtiņš Možeiko Avatar answered Sep 29 '22 19:09

Mārtiņš Možeiko


  • We need to generate our Vertex-Buffer-Objects from vertices, indices, normals, colors, uvs, etc.

It's not really necessary to use VBOs, client side Vertex Arrays do work as well. However it's strongly recommended to use VBO, because it makes the life of the driver easier and in the long run also your's as the one who has to juggle the data. The code overhead is neglectible (it's about the same as generating and uploading texture data) and performance will only increase.

  • then we can use GLM for matrix transformation, and we only use VBO to create or manipulate meshes, finally we pass everything into GLSL vertex shader like this...

You're not limited to GLM. Any matrix math library will do. If you're looking for something you can use in C99, have a look at my (still incomplete) linmath.h https://github.com/datenwolf/linmath.h which is just a header file with static inline functions. I've yet to benchmark if the code duplication has a negative impact on performance (code size creates L1 cache pressure).

QUESTION: How we do hierarchical transformations without pushMatrix/popMatrix? (or maybe we do hierarchical transformation by using our VBOs, is it possible?)

The VBOs have nothing to do with this. What gives most users of old fashioned OpenGL trouble are those matrix stack functions, which make OpenGL look a bit like a scene graph. But it is not.

If you forget about the matrix stack of old OpenGL, it becomes obvious how to do hierarchical tranformations: At each branch in the hierarchy make a copy of the transformation matrix and operate on that. You get a hierarchical tree of transformations, at each node the corresponding matrix stored. Then you pass those matrices as uniforms to the vertex shader; or just one matrix if you're drawing a rigid object that has only one transformation. Multiple matrices you normally only need for deformables like skeletal animation of a character like this

worldtransform -> 
    pelvis ->
        left upper leg -> left lower leg -> left foot
        right upper leg -> right lower leg -> right foot
    torso ->
        neck -> head ->
             left eye
             right eye
             facial deformation // this is a whole chapter of it's own
        left upper arm -> left lower arm -> left hand
        right upper arm -> right lower arm -> right hand

Everytime you enounter a -> in such a hierachy you make a copy of the matrix and proceed working on that one. When falling back to a higher level of the tree you start working from that matrix again.

like image 34
datenwolf Avatar answered Sep 29 '22 20:09

datenwolf


Yes, if you need hierarchical transformations, then you have to do it on your own. However, that is pretty much trivial if all you need is a stack. Just take the last entry on the stack and multiply it with the next matrix you want to apply, and push the result onto the stack.

[On your edited question]: You don't need a stack at all for this, and there's no hierarchical transformation either. Just have a single matrix and apply your translation, draw, multiply it with your rotation matrix, draw, multiply your scaling, draw.

like image 30
Anteru Avatar answered Sep 29 '22 20:09

Anteru