【C++游戏引擎开发】第18篇:视锥体裁剪与光源剔除
一、视锥体裁剪的数学原理
1.1 视锥体的几何表示
1.1.1 三维空间平面方程
视锥体的六个平面由标准形式定义:
a x + b y + c z + d = 0 ax + by + cz + d = 0 ax+by+cz+d=0
其中法向量 n ⃗ = ( a , b , c ) \vec{n} = (a,b,c) n=(a,b,c),平面到原点的距离为 d / ∣ ∣ n ⃗ ∣ ∣ d/||\vec{n}|| d/∣∣n∣∣
1.1.2 投影矩阵参数分解
透视投影矩阵由以下参数构成:
FOV = 4 5 ∘ Aspect = 16 : 9 Near = 0.1 Far = 100.0 \begin{aligned} \text{FOV} &= 45^\circ \\ \text{Aspect} &= 16:9 \\ \text{Near} &= 0.1 \\ \text{Far} &= 100.0 \end{aligned} FOVAspectNearFar=45∘=16:9=0.1=100.0
通过逆矩阵计算可得到视锥体8个角点的三维坐标,其齐次坐标转换公式为:
P w o r l d = ( M p r o j e c t i o n ⋅ M v i e w ) − 1 ⋅ P c l i p P_{world} = (M_{projection} \cdot M_{view})^{-1} \cdot P_{clip} Pworld=(Mprojection⋅Mview)−1⋅Pclip
1.2 平面方程生成算法
1.2.1 三点确定平面法向量
给定视锥体角点 P 0 , P 1 , P 2 P_0,P_1,P_2 P0,P1,P2,平面参数计算过程:
v 1 ⃗ = P 1 − P 0 v 2 ⃗ = P 2 − P 0 n ⃗ = v 1 ⃗ × v 2 ⃗ d = − n ⃗ ⋅ P 0 \begin{aligned} \vec{v_1} &= P_1 - P_0 \\ \vec{v_2} &= P_2 - P_0 \\ \vec{n} &= \vec{v_1} \times \vec{v_2} \\ d &= -\vec{n} \cdot P_0 \end{aligned} v1v2nd=P1−P0=P2−P0=v1×v2=−n⋅P0
1.2.2 六个平面构造方法
- 近平面:直接使用投影矩阵的Near值
- 远平面:通过矩阵第四列参数计算
- 侧平面(左右上下):
n