shader-based engines and transformations

Hi!

I’m quite a beginner in the use of shaders. I wonder how the transformations are handled in a shader-based engine that does not rely on the fixed pipeline. For example, currently I do this to draw a model composed of several parts :
gl.glPushMatrix(GL.GL_MODELVIEW_MATRIX);
gl.glMultMatrix(transform0);
//draw the first part
gl.glPushMatrix(GL.GL_MODELVIEW_MATRIX);
gl.glMultMatrix(transform1);
//draw the second part
gl.glPopMatrix();
gl.glMultMatrix(transform2);
//draw the third part
gl.glMultMatrix(transform3);
//draw the fourth part
gl.glPopMatrix();
gl.glPopMatrix();
gl.glPopMatrix();

In a GLSL vertex shader, I assume I can use a mat4 as an uniform variable to contain a transformation matrix but I cannot use one uniform variable per transform and use it with a single vertex shader. Should I use several shaders? Is my approach completely wrong? How do you use vertex shaders to draw the content of a scene graph?

Actually I wouldn’t user vertex shaders at all for scene graph transformations. They are more targeted to vertex displacement problems like terrain rendering or skinning. Just leave your scene graph code they way it is. But take this as a personal opinion, since I did not research the available papers out there. There might pobably be some stuff out there that transfer the scenegraph and model prototypes to the card and let vertex shaders do the scene graph transformation and model instancing, but I think that would be a quite uncommon approach atm.

You are right that the transform would be stored as a mat4 uniform. In my shaders I usually have two to three mat4’s (one for the projection, and then a combined modelview or a separate view and model matrix). However, you have the different problem of trying to combine all of your scene graph transforms together for a renderable object, which you can’t do because you don’t know the max depth of your tree.

When I was profiling old versions of my graphics engine, I found out that because of JNI overhead, it is actually slower to use glPush and glPop and make multiple glMatrix commands to set up the transform for each object. It’s faster to combine a scene graphs transforms in memory and track a final model transform for each object. Then in the fixed pipeline it’s only one graphics call, and in a shader engine, you only need to have one mat4 for the model. HTH and I can explain better if you have questions.

A shader-oriented engine, does not use the predefined OpenGL uniforms such as gl_ModelViewProjectionMatrix, or the glPushMatrix/PopMatrix calls.

Instead the matrices are composed by the engine before the object is rendered and then those matrices are available through custom-defined uniforms to the shader.
E.g, a basic vertex shader:


uniform mat4 g_WorldViewProjectionMatrix;
attribute vec3 inPosition;

void main(){
    gl_Position = g_WorldViewProjectionMatrix * vec4(inPosition, 1.0);
}

That is why I ask this question, my example uses the fixed pipeline of course.

I believe I see what you mean. g_WorldViewProjectionMatrix contains gl_ModelViewProjectionMatrix multiplied by all transform matrices that concern the object that is going to be drawn. When you want to draw this object, g_WorldViewProjectionMatrix is computed in the CPU side, then you use glUniform*** to update this uniform variable, after that you draw the mesh. inPosition is the absolute position, isn’t it? Thank you for your answer, it is exactly what I was looking for. I will understand better the source code of JMonkeyEngine 3 now.

what i want to know is: how would i compute g_WorldViewProjectionMatrix if my camera is at position (x,y,z), with an orientation of (pitch,yaw,roll). think airplane style.

Look at this utility class I have written, hopefully it should be pretty clear. There are two parts to the gl_ModelViewProjection matrix that the camera defines: the view transform and the projection matrix. The view transform is effectively the inverse of the camera’s world transform, and the projection matrix does the orthographic or perspective projection. To get the combined transform, you’d use:


T = P x V x M

where P is the projection matrix, V is the view transform, and M is the world transform of the object to render.

HTH

[attachment deleted by admin]