Reading — step 1 of 5
Read
~1 min read3D Math
Model-View-Projection (MVP) Transform
Every vertex in a 3D pipeline gets multiplied by MVP to land on the screen:
clipPos = P * V * M * vertex
- M (Model): object's local coords → world coords (where it is in the scene).
- V (View): world coords → camera coords (camera at origin, looking down -Z).
- P (Projection): camera coords → clip coords (the canonical -1..1 frustum after perspective divide).
Read right-to-left: vertex is first lifted to world by M, then dragged into camera space by V, then warped by P.
LookAt: build V from camera position eye, target at, and up vector up:
f = normalize(at - eye)
r = normalize(cross(f, up))
u = cross(r, f)
View = [[ r.x, r.y, r.z, -dot(r, eye) ],
[ u.x, u.y, u.z, -dot(u, eye) ],
[-f.x, -f.y, -f.z, dot(f, eye) ],
[ 0, 0, 0, 1 ]]
Perspective projection (OpenGL convention):
f = 1 / tan(fov / 2)
P = [[ f/aspect, 0, 0, 0 ],
[ 0, f, 0, 0 ],
[ 0, 0, (near+far)/(near-far), (2*near*far)/(near-far) ],
[ 0, 0, -1, 0 ]]
After P * V * M * v, divide by w to get NDC (normalized device coords), then map (-1..1) → pixels with the viewport transform.
This is the entire vertex-shader job for 99% of triangle work. Cache MVP per draw call; recompute only when the camera or object moves.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…