Sign in to follow this  

OpenGL Transform matrix application order

This topic is 2020 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm building my first OpenGL demo to incorporate into the game I'm writing. I wonder if you gentlefolk might help clarify the transformation process for me. I have a basic vertex and fragment shaders up and running already.

Here's what I see as the method for getting 3D objects perspective-transformed to screen:



On update:

Create the camera matrix: c = camRotation * camTranslation
Create the view matrix by inverting the camera matrix: v = c^-1
Create the projection matrix using the standard perspective projection matrix terms
Create view-projection matrix: vp = p * v

For each entity
Create a model matrix using entity world position, rotation, and scale values
Multiply this specific entity's world transform matrix (the model matrix): mvp = vp * m
Set mvp as a uniform for vertex shader

[*]Please offer your advice on whether or not the above structure is sensible.
[*]What options do I have to reduce the number of draw calls? Merging static geometry into a single vertex list using a common texture atlas seems to be the only option?
[*]Re the MVP matrix above, why do some sources present the final matrix value as -1, and others as 1? What should I use?
Any other tips, suggestions on this structure welcome.

Primary references:

[url=""]OpenGL wiki page on viewing and transformations[/url]
[url=""]Joe Groff's tutorial on transformation and projection[/url] Edited by NickWiggill

Share this post

Link to post
Share on other sites
The order of the projection-view matrix is wrong. It shall be Proj*view. So the MVP matrix would be P*V*M. Some of this is done in the shader, some is not. It depends on the complexity of your design. The shader is much faster to compute this, but if a result stays the same for every pixel, then you might as well do it in the main application before sending it to the shader. You don't need a "window matrix", it is included in the projection matrix.

The vertex shader now need to compute PVM*v, for each vertex 'v'.

Share this post

Link to post
Share on other sites
Hi larspensjo,

Thanks for clarifying, I've updated the question by removing the reference to the "window" matrix.

Also could you confirm the order then, for matrix multiplication:
[source lang="java"]
modelViewMatrix = viewMatrix * modelMatrix; //??
modelViewProjectionMatrix = projectionMatrix * modelViewMatrix; //??[/source]

...Assuming matrix mul() ordering is thisMatrix * otherMatrix? Edited by NickWiggill

Share this post

Link to post
Share on other sites
[quote name='NickWiggill' timestamp='1341601398' post='4956430']
Hi larspensjo,

Thanks for clarifying, I've updated the question by removing the reference to the "window" matrix.

Also could you confirm the order then, for matrix multiplication:
[source lang="java"]
modelViewMatrix = viewMatrix * modelMatrix; //??
modelViewProjectionMatrix = projectionMatrix * modelViewMatrix; //??[/source]

...Assuming matrix mul() ordering is thisMatrix * otherMatrix?
Confirmed. If you are using C++, I recommend the package [url=""]glm[/url]. It is a matrix manipulation package, with a syntax close to the shader language.

Share this post

Link to post
Share on other sites
Ah, many thanks. Updated again with the multiplication order. This should allow me to proceed. I hope you have a good weekend too [img][/img]

Share this post

Link to post
Share on other sites
Personally, I find this reference helpful: [url=""][/url]

You could split up the modelview matrix into two parts, and so you would transform your vertices using your model matrix first, and then by your view matrix.

I like thinking in terms which order the transformations are applied, then afterwards rearrange things to match the multiplication order I am working with (i.e. "pre" or "post" multiplication.) Edited by scniton

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Similar Content

    • By xhcao
      Does sync be needed to read texture content after access texture image in compute shader?
      My simple code is as below,
      glBindImageTexture(0, texture[0], 0, GL_FALSE, 3, GL_READ_ONLY, GL_R32UI);
      glBindImageTexture(1, texture[1], 0, GL_FALSE, 4, GL_WRITE_ONLY, GL_R32UI);
      glDispatchCompute(1, 1, 1);
      // Does sync be needed here?
      glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
                                     GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, texture[1], 0);
      glReadPixels(0, 0, kWidth, kHeight, GL_RED_INTEGER, GL_UNSIGNED_INT, outputValues);
      Compute shader is very simple, imageLoad content from texture[0], and imageStore content to texture[1]. Does need to sync after dispatchCompute?
    • By Jonathan2006
      My question: is it possible to transform multiple angular velocities so that they can be reinserted as one? My research is below:
      // This works quat quaternion1 = GEQuaternionFromAngleRadians(angleRadiansVector1); quat quaternion2 = GEMultiplyQuaternions(quaternion1, GEQuaternionFromAngleRadians(angleRadiansVector2)); quat quaternion3 = GEMultiplyQuaternions(quaternion2, GEQuaternionFromAngleRadians(angleRadiansVector3)); glMultMatrixf(GEMat4FromQuaternion(quaternion3).array); // The first two work fine but not the third. Why? quat quaternion1 = GEQuaternionFromAngleRadians(angleRadiansVector1); vec3 vector1 = GETransformQuaternionAndVector(quaternion1, angularVelocity1); quat quaternion2 = GEQuaternionFromAngleRadians(angleRadiansVector2); vec3 vector2 = GETransformQuaternionAndVector(quaternion2, angularVelocity2); // This doesn't work //quat quaternion3 = GEQuaternionFromAngleRadians(angleRadiansVector3); //vec3 vector3 = GETransformQuaternionAndVector(quaternion3, angularVelocity3); vec3 angleVelocity = GEAddVectors(vector1, vector2); // Does not work: vec3 angleVelocity = GEAddVectors(vector1, GEAddVectors(vector2, vector3)); static vec3 angleRadiansVector; vec3 angularAcceleration = GESetVector(0.0, 0.0, 0.0); // Sending it through one angular velocity later in my motion engine angleVelocity = GEAddVectors(angleVelocity, GEMultiplyVectorAndScalar(angularAcceleration, timeStep)); angleRadiansVector = GEAddVectors(angleRadiansVector, GEMultiplyVectorAndScalar(angleVelocity, timeStep)); glMultMatrixf(GEMat4FromEulerAngle(angleRadiansVector).array); Also how do I combine multiple angularAcceleration variables? Is there an easier way to transform the angular values?
    • By dpadam450
      I have this code below in both my vertex and fragment shader, however when I request glGetUniformLocation("Lights[0].diffuse") or "Lights[0].attenuation", it returns -1. It will only give me a valid uniform location if I actually use the diffuse/attenuation variables in the VERTEX shader. Because I use position in the vertex shader, it always returns a valid uniform location. I've read that I can share uniforms across both vertex and fragment, but I'm confused what this is even compiling to if this is the case.
      #define NUM_LIGHTS 2
      struct Light
          vec3 position;
          vec3 diffuse;
          float attenuation;
      uniform Light Lights[NUM_LIGHTS];
    • By pr033r
      I have a Bachelor project on topic "Implenet 3D Boid's algorithm in OpenGL". All OpenGL issues works fine for me, all rendering etc. But when I started implement the boid's algorithm it was getting worse and worse. I read article ( inspirate from another code (here: but it still doesn't work like in tutorials and videos. For example the main problem: when I apply Cohesion (one of three main laws of boids) it makes some "cycling knot". Second, when some flock touch to another it scary change the coordination or respawn in origin (x: 0, y:0. z:0). Just some streng things. 
      I followed many tutorials, change a try everything but it isn't so smooth, without lags like in another videos. I really need your help. 
      My code (optimalizing branch):
      Exe file (if you want to look) and models folder (for those who will download the sources):
      Thanks for any help...

    • By Andrija
      I am currently trying to implement shadow mapping into my project , but although i can render my depth map to the screen and it looks okay , when i sample it with shadowCoords there is no shadow.
      Here is my light space matrix calculation
      mat4x4 lightViewMatrix; vec3 sun_pos = {SUN_OFFSET * the_sun->direction[0], SUN_OFFSET * the_sun->direction[1], SUN_OFFSET * the_sun->direction[2]}; mat4x4_look_at(lightViewMatrix,sun_pos,player->pos,up); mat4x4_mul(lightSpaceMatrix,lightProjMatrix,lightViewMatrix); I will tweak the values for the size and frustum of the shadow map, but for now i just want to draw shadows around the player position
      the_sun->direction is a normalized vector so i multiply it by a constant to get the position.
      player->pos is the camera position in world space
      the light projection matrix is calculated like this:
      mat4x4_ortho(lightProjMatrix,-SHADOW_FAR,SHADOW_FAR,-SHADOW_FAR,SHADOW_FAR,NEAR,SHADOW_FAR); Shadow vertex shader:
      uniform mat4 light_space_matrix; void main() { gl_Position = light_space_matrix * transfMatrix * vec4(position, 1.0f); } Shadow fragment shader:
      out float fragDepth; void main() { fragDepth = gl_FragCoord.z; } I am using deferred rendering so i have all my world positions in the g_positions buffer
      My shadow calculation in the deferred fragment shader:
      float get_shadow_fac(vec4 light_space_pos) { vec3 shadow_coords = / light_space_pos.w; shadow_coords = shadow_coords * 0.5 + 0.5; float closest_depth = texture(shadow_map, shadow_coords.xy).r; float current_depth = shadow_coords.z; float shadow_fac = 1.0; if(closest_depth < current_depth) shadow_fac = 0.5; return shadow_fac; } I call the function like this:
      get_shadow_fac(light_space_matrix * vec4(position,1.0)); Where position is the value i got from sampling the g_position buffer
      Here is my depth texture (i know it will produce low quality shadows but i just want to get it working for now):
      sorry because of the compression , the black smudges are trees ...
      EDIT: Depth texture attachment:
  • Popular Now