Perspective Projection Matrix of OpenGL and Direct3D

1. Setting the Stage: What Does Perspective Projection Do?

The perspective projection matrix transforms 3D points from camera space (or view space) into clip space (before clipping and normalization). The key goals of a perspective projection matrix are:

  • Mapping 3D points to 2D while preserving the depth information.
  • Foreshortening: Objects further away from the camera appear smaller.
  • Clipping: Points outside the view frustum (outside the near and far planes, or outside the left, right, top, and bottom planes) are clipped.

Both OpenGL and Direct3D use a 4x4 matrix to achieve this, but they handle things like depth range and homogeneous coordinates differently. These differences give us two distinct forms of the projection matrix.

2. General Perspective Projection Matrix Setup

A perspective projection matrix typically involves the following parameters:

  • Field of view (FOV) --- defines the viewing angle.
  • Aspect ratio (AR) --- the ratio of the width to the height of the image.
  • Near plane (n) and far plane (f) --- these define the depth range of the scene being rendered.
  • Frustum bounds --- the left, right, top, and bottom boundaries of the view frustum (a truncated pyramid that represents the visible part of the scene).

The view frustum is defined by:

  • l l l: Left boundary of the near plane.
  • r r r: Right boundary of the near plane.
  • b b b: Bottom boundary of the near plane.
  • t t t: Top boundary of the near plane.
  • n n n: Distance to the near clipping plane.
  • f f f: Distance to the far clipping plane.

3. Deriving the Perspective Projection Matrix

(a) Frustum Definition

The frustum is a truncated pyramid that defines the visible region of the 3D scene:

  • Near clipping plane : The rectangle at z = n z = n z=n, defined by [ l , r ] [l, r] [l,r] in the horizontal direction and [ b , t ] [b, t] [b,t] in the vertical direction.
  • Far clipping plane : The rectangle at z = f z = f z=f, also bounded horizontally and vertically.

The idea is to map 3D points inside this frustum to a cube (known as clip space) where:

  • x x x is in the range [ − 1 , 1 ] [-1, 1] [−1,1],
  • y y y is in the range [ − 1 , 1 ] [-1, 1] [−1,1],
  • For OpenGL , z z z is in the range [ − 1 , 1 ] [-1, 1] [−1,1],
  • For Direct3D , z z z is in the range [ 0 , 1 ] [0, 1] [0,1].
(b) Perspective Projection Matrix Form

To map the 3D frustum to this normalized clip space, we use a perspective projection matrix. For both OpenGL and Direct3D, the general form of the matrix is the same:

P 4 x 4 = [ 2 n r − l 0 r + l r − l 0 0 2 n t − b t + b t − b 0 0 0 f + n n − f 2 f n n − f 0 0 − 1 0 ] P_{4x4} = \begin{bmatrix} \frac{2n}{r-l} & 0 & \frac{r+l}{r-l} & 0 \\ 0 & \frac{2n}{t-b} & \frac{t+b}{t-b} & 0 \\ 0 & 0 & \frac{f+n}{n-f} & \frac{2fn}{n-f} \\ 0 & 0 & -1 & 0 \end{bmatrix} P4x4= r−l2n0000t−b2n00r−lr+lt−bt+bn−ff+n−100n−f2fn0

Where:

  • r r r, l l l: Right and left boundaries of the frustum at the near plane.
  • t t t, b b b: Top and bottom boundaries of the frustum at the near plane.
  • n , f n, f n,f: Near and far clipping distances.
© Breaking Down the Matrix:

Let's break down each part of this matrix:

  • First row (horizontal scaling) :
    2 n r − l \frac{2n}{r-l} r−l2n

    This scales the x-coordinate into the range [ − 1 , 1 ] [-1, 1] [−1,1] in clip space. The r − l r-l r−l term ensures the width of the frustum is correctly mapped, and the factor of 2 n 2n 2n accounts for the depth and field of view.

    The third element of the first row,
    r + l r − l \frac{r+l}{r-l} r−lr+l

    adjusts for the horizontal offset of the frustum (if it's centered or not).

  • Second row (vertical scaling) :
    2 n t − b \frac{2n}{t-b} t−b2n

    This scales the y-coordinate into the range [ − 1 , 1 ] [-1, 1] [−1,1] in clip space. Similar to the horizontal scaling, this term ensures the height of the frustum is correctly mapped.

    The third element of the second row,
    t + b t − b \frac{t+b}{t-b} t−bt+b

    adjusts for the vertical offset of the frustum.

  • Third row (depth scaling) :
    f + n n − f \frac{f+n}{n-f} n−ff+n

    This term maps the z-coordinate (depth) from the range [ n , f ] [n, f] [n,f] in camera space into the clip space range. Here's where the difference between OpenGL and Direct3D comes in:

    • In OpenGL , we want z z z to be mapped into the range [ − 1 , 1 ] [-1, 1] [−1,1].
    • In Direct3D , we want z z z to be mapped into the range [ 0 , 1 ] [0, 1] [0,1].

    The fourth element of the third row,
    2 f n n − f \frac{2fn}{n-f} n−f2fn

    ensures that the depth values are correctly scaled.

  • Fourth row :
    − 1 -1 −1

    This term ensures the correct perspective divide happens, where after applying the transformation, the coordinates are divided by w w w to obtain normalized device coordinates (NDC).

4. Differences Between OpenGL and Direct3D Matrices

Now, let's focus on the key differences between the OpenGL and Direct3D perspective projection matrices.

(a) Depth Range Differences (Third Row)
  • OpenGL : The depth range is mapped to [ − 1 , 1 ] [-1, 1] [−1,1]. This is why the term f + n n − f \frac{f+n}{n-f} n−ff+n is used in the M 33 M_{33} M33 element of the OpenGL matrix. It ensures that z z z values at the near plane ( z = n z = n z=n) are mapped to − 1 -1 −1 and at the far plane ( z = f z = f z=f) are mapped to 1 1 1.

    This explains why M 33 = 1 M_{33} = 1 M33=1 in OpenGL, as OpenGL uses a symmetric depth range around 0.

  • Direct3D : The depth range is mapped to [ 0 , 1 ] [0, 1] [0,1]. In Direct3D, P 33 = − 1 P_{33} = -1 P33=−1 because Direct3D maps the near plane to z = 0 z = 0 z=0 and the far plane to z = 1 z = 1 z=1. This convention is more compatible with common buffer formats (where a depth of 0 corresponds to the near plane and 1 corresponds to the far plane).

(b) c x c_x cx and c y c_y cy (Principal Point Offsets)

The terms c x c_x cx and c y c_y cy (the third elements in the first and second rows) represent the offsets for the principal point (the center of projection) on the image plane. These terms are different because they depend on how the frustum is defined:

  • In OpenGL , the frustum is typically symmetric, so c x c_x cx and c y c_y cy are often 0 when the frustum is centered. This means that the projection is symmetric around the origin in clip space.

  • In Direct3D , the frustum may be defined differently, or the principal point may be offset from the center (especially if the projection is not symmetric). This can lead to non-zero values for c x c_x cx and c y c_y cy.

5. Alternative Form: Field of View (FOV) Perspective Matrix

In some cases, instead of defining the frustum with explicit bounds ( r , l , t , b ) (r, l, t, b) (r,l,t,b), it's more intuitive to use the field of view (FOV) and aspect ratio. The projection matrix in this form is often used for cameras:

P 4 x 4 = [ 1 A R ⋅ tan ⁡ ( F O V 2 ) 0 0 0 0 1 tan ⁡ ( F O V 2 ) 0 0 0 0 f + n n − f 2 f n n − f 0 0 − 1 0 ] P_{4x4} = \begin{bmatrix} \frac{1}{AR \cdot \tan(\frac{FOV}{2})} & 0 & 0 & 0 \\ 0 & \frac{1}{\tan(\frac{FOV}{2})} & 0 & 0 \\ 0 & 0 & \frac{f+n}{n-f} & \frac{2fn}{n-f} \\ 0 & 0 & -1 & 0 \end{bmatrix} P4x4= AR⋅tan(2FOV)10000tan(2FOV)10000n−ff+n−100n−f2fn0

Where:

  • F O V FOV FOV is the field of view angle.
  • A R AR AR is the aspect ratio (width/height).
  • n n n and f f f are the near and far clipping planes.
相关推荐
曹勖之18 小时前
UE5中的sim3dSceneCap中视角亮度怎么调节?
3d·ue5
CAD芯智库2 天前
国产三维CAD工程图特征、公母唇缘有何提升?| 中望3D 2026亮点速递(8)
科技·3d·业界资讯·中望3d·国产三维cad软件·中望3d2026·3d工程图设计
苏州知芯传感2 天前
MEMS与CMOS的3D集成技术研究进展
3d·cmos·mems
曹勖之2 天前
simulink中的Simulation 3D Camera模块和Simulation 3D Camera Get模块的区别?
3d·ue5
da_vinci_x2 天前
Substance Designer的通道合并(Channel Packing)自动化工作流
3d·自动化·贴图·技术美术·游戏策划·游戏美术·substance designer
康谋自动驾驶2 天前
拆解3D Gaussian Splatting:原理框架、实战 demo 与自驾仿真落地探索!
算法·数学建模·3d·自动驾驶·汽车
黑金IT3 天前
3D虚拟人模型转换的完整指南
服务器·数据库·3d
xhload3d3 天前
WebGL/Canvas 内存泄露分析
低代码·3d·html5·webgl·数字孪生·可视化·软件开发·工业互联网·内存泄漏·轻量化·技术应用·hightopo
小张成长计划..4 天前
前端6:CSS3 2D转换,CSS3动画,CSS3 3D转换
前端·3d·css3
GIS数据转换器4 天前
带高度多边形,生成3D建筑模型,支持多种颜色或纹理的OBJ、GLTF、3DTiles格式
数据库·人工智能·机器学习·3d·重构·无人机