问题
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
回答1:
- 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.
回答2:
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.
回答3:
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);
回答4:
In regard to VAO and VBO performance I disagree that VBO is faster, I suggest to see this link
http://www.openglsuperbible.com/2013/12/09/vertex-array-performance/
You can see from the results above that, at least for our small sample set, VAO is faster on all implementations. It stands to reason — there are less parameters to validate when calling glBindVertexArray than either glBindBuffer or glVertexAttribPointer. Even when there is only a single vertex attribute, there are half as many calls into OpenGL with a VAO switch than with explicit update of a global VAO. Besides the obvious “fewer API calls means faster execution” relationship, the VAO is a place that an OpenGL driver can stash information required to program the underlying GPU. The total amount of state changes sent to the GPU is the same either way.
来源:https://stackoverflow.com/questions/8951509/modern-opengl-vbo-glm-and-matrix-stacks