Use for personal or educational purposes only. Commercial and other profit uses strictly prohibited. Exploitation of content on a website or in a publication prohibited.

**mat4x4 M** - model matrix - model-to-world space transformation, the result of several matrices multiplication (translation, rotation, scaling) may be stored in it

**mat4x4 V** - view matrix - world-to-view space transformation

**mat4x4 P** - perspective projection matrix - view-to-clip and clip-to-ndc space transformation (perspective division must be applied)

**mat4x4 Bias** - bias matrix - ndc-to-texture space transformation (shadow mapping, screen space ambient occlusion, ...)

**mat4x4 Vp** - viewport matrix - viewport transformation

**vec4 v**_{m} = vec4(x, y, z, 1) - vertex in model space

**vec4 v**_{w} = M * v_{m} - vertex in world space

**vec4 v**_{v} = V * v_{w} - vertex in view (camera, eye) space

**V** causes

**v**_{w} to be rotated and translated in the opposite direction considering the rotation and position of the camera

if

**v**_{v}.z < 0 then

**v**_{v} is in front of the camera

**vec4 v**_{c} = P * v_{v} - vertex in clip space

**v**_{c}.x = P[0] * v_{v}.x
**v**_{c}.y = P[5] * v_{v}.y
**v**_{c}.z = P[10] * v_{v}.z + P[14] * v_{v}.w = P[10] * v_{v}.z + P[14]
**v**_{c}.w = P[11] * v_{v}.z = -v_{v}.z
**v**_{c} = P * V * M * v_{m} = (P * (V * (M * v_{m}))) - output of a vertex shader - gl_Position

For performance reasons the result of the model and view matrix multiplication is stored in the modelview matrix (GL_MODELVIEW_MATRIX, gl_ModelViewMatrix)

**MV = V * M;** and the result of the modelview and projection matrix multiplication is stored in the modelviewprojection matrix (gl_ModelViewProjectionMatrix)

**MVP = P * MV = P * V * M;**.

if

**v**_{c}.w > 0 then

**v**_{c} is in front of the camera

if (

**-v**_{c}.w <= v_{c}.x < v_{c}.w) and (

**-v**_{c}.w <= v_{c}.y < v_{c}.w) and (

**-v**_{c}.w <= v_{c}.z < v_{c}.w) then

**v**_{c} is inside the camera frustum and is visible on the screen

**v**_{c}.w != 1 therefore

**v**_{c} must be divided by

**v**_{c}.w
**v**_{ndc} = v_{c} / v_{c}.w - perspective division

if (

**-1 <= v**_{ndc}.x < 1) and (

**-1 <= v**_{ndc}.y < 1) and (

**-1 <= v**_{ndc}.z < 1) then

**v**_{ndc} is inside the camera frustum and is visible on the screen

**vec4 v**_{t} = Bias * v_{ndc} - vertex in texture space

**v**_{t}.x = v_{ndc}.x * 0.5 + 0.5
**v**_{t}.y = v_{ndc}.y * 0.5 + 0.5
**v**_{t}.z = v_{ndc}.z * 0.5 + 0.5
**v**_{t}.x and

**v**_{t}.y are used to fetch the depth texture and

**v**_{t}.z is used for depth comparison (shadow mapping, screen space ambient occlusion, ...)

if (

**0 <= v**_{t}.x < 1) and (

**0 <= v**_{t}.y < 1) and (

**0 <= v**_{t}.z < 1) then

**v**_{t} is inside the camera frustum

and if

**v**_{t} lies in the

- near clip plane then
**v**_{t}.z = 0
- far clip plane then
**v**_{t}.z = 1

**v**_{t}.z is used for depth test and stored in the depth buffer

**vec4 p = Vp * v**_{t} - pixel on the screen

**p.x = v**_{t}.x * width + x
**p.y = v**_{t}.y * height + y
**p.x** and

**p.y** are coordinates to the color and depth buffers

if a vertex

**v**_{t} is inside the camera frustum then

**x <= p.x < x + width**
**y <= p.y < y + height**
See the

Simple software renderer or

Software shadow mapping tutorials for more details.

__View matrix__ - gluLookAt(ex, ey, ez, cx, cy, cz, ux, uy, uz)

vec3 P

_{c} = vec3(ex, ey, ez);

vec3 Z

_{c} = normalize(P

_{c} - vec3(cx, cy, cz));

vec3 Y

_{c} = normalize(vec3(ux, uy, uz));

vec3 X

_{c} = normalize(cross(Y

_{c}, Z

_{c}));

Y

_{c} = cross(Z

_{c}, X

_{c});

__Perspective projection matrix__ - gluPerspective(fovy, aspect, n, f)

__Bias matrix__
__Viewport matrix__ - glViewport(x, y, width, height)