这里是SunshineBooming,GPU公司一枚小小的Driver工程师,主要工作是写DirectX12 Driver,我会持续更新这个DX12 Spec系列,可能比较冷门,但是都是干货和工作中的心得体会,有任何GPU相关的问题都可以在评论区互动,知无不言:
DirectX12 Spec 总目录
1. 什么是Triangle Culling(三角形剔除)?
- 我们都知道,在现有的3D图形框架中,3D模型都是由Triangle有序排列起来的。例如一个长方体有6个面,每个面可以拆分成2个Triangle。那么我们就可以用[Tri0…Tri11]这样12个Triangle有序排列,最后还原成一个长方体的3D模型:
- 同时我们也可以发现,在正对着长方体某个面的观察视角上,例如这样:
在此视角下,只能观察到Tri0、Tri1两个三角形组成的平面,Tri2/3/4/5是无法看见的,因此这部分Triangle在DirectX12的Rendering Pipeline中可以预先剔除(Culling),这样做可以减少不必要的计算量,提高渲染效率。
2. 什么是Winding Order(绕序)?
- Winding Order是几何图形学中的知识。假设一个Triangle由3个Vertex构成,且3个Vertex输入到DX12驱动的Input Layout顺序,为Ver0->Ver1->Ver2,这个Vertex的排布顺序,就是Triangle的绕序(Winding Order):
根据左手定则,在该绕序条件下,Triangle的法向量,为传出纸向外,且垂直于该平面的单位向量。 - 注意:DirectX12判定平面法向量用的是左手定则,OGL正好相反,用的是右手定则。
- 所以我们可以看出,每个Triangle的Vertex绕序,决定了该Triangle图形的法向量方向。
3. 如何用Winding Order(绕序)做Culling(剔除)?
- 有了绕序的概念,做剔除的原理其实很简单。
- 我们知道DirectX12做渲染过程中,所有3D模型最后都要统一到观察空间(View Space)。每个3D模型先在局部空间建模,然后通过世界矩阵->世界空间,然后根据Camera在世界空间中摆放的参数,得到观察矩阵,再通过观察矩阵,将世界空间->观察空间(扯远了。。。)。
- 那么观察空间也是一个三维空间:
Camera观察方向指向+Z方向,所以我们规定,任何一个Triangle的法向量,和-Z方向的单位向量(比如(0,0,-1))做比较,2个向量夹角在[0,Pi/2)范围留下,在[Pi/2,Pi]范围剔除,因为大于Pi/2角度的平面,是背向观察方向的平面,所以是不可见的:
法向量如何确定呢?就是根据之前说的的绕序确定。 - 所以剔除的整个原理就是这样简单,其中算法向量和算向量夹角都有数学公式支撑,这里不做赘述。
- 另外剔除的整个计算和判定过程都是由GPU Hardware端做的,因为一个简单的3D模型,都可能有成千上万个Triangle组成,计算量是非常大的。