What are matrix transformations in WebGL? What is the MVP matrix?
Matrix Transformations in WebGL
In 3D graphics rendering, matrix transformations are used to convert vertices from one coordinate space to another. WebGL uses 4×4 matrices for various transformation operations.
Basic Transformation Matrices
1. Translation Matrix
Moves an object along the X, Y, and Z axes
shell| 1 0 0 tx | | 0 1 0 ty | | 0 0 1 tz | | 0 0 0 1 |
javascriptfunction createTranslationMatrix(tx, ty, tz) { return new Float32Array([ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, tx, ty, tz, 1 ]); }
2. Scale Matrix
Scales an object along each axis
shell| sx 0 0 0 | | 0 sy 0 0 | | 0 0 sz 0 | | 0 0 0 1 |
3. Rotation Matrix
Rotation around X axis
shell| 1 0 0 0 | | 0 cosθ -sinθ 0 | | 0 sinθ cosθ 0 | | 0 0 0 1 |
Rotation around Y axis
shell| cosθ 0 sinθ 0 | | 0 1 0 0 | | -sinθ 0 cosθ 0 | | 0 0 0 1 |
Rotation around Z axis
shell| cosθ -sinθ 0 0 | | sinθ cosθ 0 0 | | 0 0 1 0 | | 0 0 0 1 |
MVP Matrix Explained
The MVP matrix is the product of three matrices used to transform vertices from model space to clip space:
MVP = P × V × M
M - Model Matrix
Purpose: Transforms vertices from model space (local space) to world space
javascript// Model matrix = Translation × Rotation × Scale const modelMatrix = mat4.create(); mat4.translate(modelMatrix, modelMatrix, [x, y, z]); mat4.rotateX(modelMatrix, modelMatrix, angleX); mat4.rotateY(modelMatrix, modelMatrix, angleY); mat4.scale(modelMatrix, modelMatrix, [sx, sy, sz]);
Use cases:
- Object position in the world
- Object rotation angles
- Object size scaling
V - View Matrix
Purpose: Transforms vertices from world space to camera space (view space)
javascript// Create view matrix using lookAt function const viewMatrix = mat4.create(); mat4.lookAt( viewMatrix, [0, 0, 5], // Camera position (eye) [0, 0, 0], // Target point to look at [0, 1, 0] // Up direction vector );
Essence of view matrix:
- Moves world coordinate origin to camera position
- Rotates coordinate system so camera faces -Z direction
- Camera is at origin, looking towards -Z axis
P - Projection Matrix
Purpose: Transforms vertices from camera space to clip space
Perspective Projection
Simulates human eye visual effect, objects appear smaller with distance
javascriptconst projectionMatrix = mat4.create(); mat4.perspective( projectionMatrix, Math.PI / 4, // Field of view (FOV) canvas.width / canvas.height, // Aspect ratio 0.1, // Near plane 100.0 // Far plane );
Orthographic Projection
Maintains object size, commonly used in 2D games or CAD software
javascriptmat4.ortho( projectionMatrix, -2, 2, // Left, Right -2, 2, // Bottom, Top 0.1, 100 // Near, Far );
Coordinate Space Transformation Flow
shellModel Space (Local Space) ↓ [Model Matrix M] World Space ↓ [View Matrix V] Camera Space (View Space) ↓ [Projection Matrix P] Clip Space ↓ [Perspective Division] Normalized Device Coordinates (NDC) ↓ [Viewport Transform] Screen Space
MVP Application in Vertex Shader
glsl// Vertex shader attribute vec3 a_position; attribute vec3 a_color; uniform mat4 u_modelMatrix; uniform mat4 u_viewMatrix; uniform mat4 u_projectionMatrix; varying vec3 v_color; void main() { // Method 1: Apply three matrices separately // vec4 worldPos = u_modelMatrix * vec4(a_position, 1.0); // vec4 viewPos = u_viewMatrix * worldPos; // gl_Position = u_projectionMatrix * viewPos; // Method 2: Use pre-computed MVP matrix (recommended) mat4 mvp = u_projectionMatrix * u_viewMatrix * u_modelMatrix; gl_Position = mvp * vec4(a_position, 1.0); v_color = a_color; }
Matrix Calculation in JavaScript
javascript// Using gl-matrix library import { mat4, vec3 } from 'gl-matrix'; class Camera { constructor() { this.projectionMatrix = mat4.create(); this.viewMatrix = mat4.create(); this.mvpMatrix = mat4.create(); } setPerspective(fov, aspect, near, far) { mat4.perspective(this.projectionMatrix, fov, aspect, near, far); } lookAt(eye, center, up) { mat4.lookAt(this.viewMatrix, eye, center, up); } getMVPMatrix(modelMatrix) { // MVP = P × V × M mat4.multiply(this.mvpMatrix, this.viewMatrix, modelMatrix); mat4.multiply(this.mvpMatrix, this.projectionMatrix, this.mvpMatrix); return this.mvpMatrix; } } // Usage example const camera = new Camera(); camera.setPerspective(Math.PI / 4, 16/9, 0.1, 100); camera.lookAt([0, 0, 5], [0, 0, 0], [0, 1, 0]); const modelMatrix = mat4.create(); mat4.translate(modelMatrix, modelMatrix, [1, 0, 0]); const mvp = camera.getMVPMatrix(modelMatrix); gl.uniformMatrix4fv(mvpLocation, false, mvp);
Common Issues and Considerations
1. Matrix Multiplication Order
Matrix multiplication is not commutative, order is crucial:
- Correct:
MVP = P × V × M, applied to vertex:MVP × vertex - Transformations applied first are on the right side of the multiplication chain
2. Row-major vs Column-major
- WebGL uses column-major matrix storage
- Third parameter
transposeofgl.uniformMatrix4fvmust befalse
3. Homogeneous Coordinates
Using 4D vectors (x, y, z, w):
- Vertex position:
w = 1 - Direction vector:
w = 0(not affected by translation)
4. Performance Optimization
- Pre-compute MVP matrix on CPU instead of multiplying separately in shader
- Use uniforms to pass pre-computed matrices