Difference between revisions of "Vertex Transformation"

This page contains a small example that shows how a vertex is transformed.
object space ---> world space
world space ---> eye space
eye space ---> clip space
clip space ---> normalized device space
normalized device space ---> window space

Let's built a projection matrix.

glFrustum(-0.1, 0.1, -0.1, 1.0, 1.0, 1000.0);

The resulting matrix looks like this

[1.81, 0.00, 0.81, 0.00]
[0.00, 1.81, 0.81, 0.00]
[0.00, 0.00, -1.00, -2.00]
[0.00, 0.00, -1.00, 0.00]

Let's built a very simple modelview matrix

glTranslatef(1.0, 2.0, 3.0);

The resulting matrix looks like this

[1.0, 0.00, 0.00, 1.00]
[0.00, 1.0, 0.00, 2.00]
[0.00, 0.00, 1.00, 3.00]
[0.00, 0.00, 0.00, 1.00]

and of course, the viewport also matters

glViewport(0, 0, 800, 600);

The vertex you give to GL is considered to be in object space.
Let's assume the values are [21.5, 58.6, -99.6, 1.0]
Notice that w=1.0
When you transform a vertex by the modelview, the vertex is considered to be in eye space.
Note: The modelview matrix is actually 2 matrices in 1. The world matrix which transforms from object space to world space and the view matrix which transforms from world to eye space.
The vertex becomes [22.5, 60.6, -96.6, 1.0]
When you transform a vertex by the projection matrix, you get [-38.12, 31.14, 94.79, 96.59]. This is called clip coordinate.
Then w inverse is computed : 1/96.59 = 0.0103520
Each component is multiplied by the 1/w, you get [-0.394692, 0.322417, 0.981277, 1.0] This is called normalized device coordinates.
Here, if z is from -1.0 to 1.0, then it is inside the znear and zfar clipping planes.
Now the final stage of the transformation pipeline:
The z is transformed to the 0.0 to 1.0 range. Anything outside this range gets clipped away. Notice that glDepthRange() has an effect here. By default, glDepthRange(0.0, 1.0)
The final operation looks like this

windowCoordinate=(viewport * x +(viewport + viewport)) * 0.5;
windowCoordinate=(viewport * y +(viewport + viewport)) * 0.5;
windowCoordinate=(1.0 + z)*0.5;   //Convert to 0.0 to 1.0 range. Anything outside that ranges gets clipped.

and the vertex will now be [242.123, 396.725, 0.990639]
W doesn't matter.