3月6日 21:58

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 |
javascript
function 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

javascript
const 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

javascript
mat4.ortho( projectionMatrix, -2, 2, // Left, Right -2, 2, // Bottom, Top 0.1, 100 // Near, Far );

Coordinate Space Transformation Flow

shell
Model 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 transpose of gl.uniformMatrix4fv must be false

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
标签:WebGL