|
|
@@ -1048,3 +1048,132 @@ int D3DApp::Run()
|
|
|
}
|
|
|
```
|
|
|
|
|
|
+### 渲染流水线
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+#### 输入装配器阶段
|
|
|
+
|
|
|
+输入装配器(`Input Assembler`, IA) 阶段会从现存中读取几何数据(顶点和索引, `Vertex And Index`),再将他们装配为几何图元(`geometric primitive`,如三角形和线条这种构成图形的基本元素)
|
|
|
+
|
|
|
+在 `Direct3D` 中通过 `Vertex Buffer` 的特殊数据结构将顶点与渲染流水线绑定
|
|
|
+
|
|
|
+`Vertext Buffer` 利用连续的内存来存储一系列顶点
|
|
|
+
|
|
|
+除了顶点之外,还需要指定**图元拓扑**(`primitive topology`)来告知如何用顶点数据来表示几何图元
|
|
|
+
|
|
|
+```cpp
|
|
|
+mCommandList->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
|
|
+```
|
|
|
+
|
|
|
+上述代码就是在设置**图元拓扑**类型,枚举类型为: `D3D_PRIMITIVE_TOPOLOGY`,枚举值有点多,在[官方文档](https://learn.microsoft.com/zh-cn/windows/win32/api/d3dcommon/ne-d3dcommon-d3d_primitive_topology)中有详细说明
|
|
|
+
|
|
|
+```cpp
|
|
|
+D3D_PRIMITIVE_TOPOLOGY_POINTLIST, // 将顶点数据解释为点列表
|
|
|
+D3D_PRIMITIVE_TOPOLOGY_LINELIST, // 将顶点数据解释为线条列表
|
|
|
+D3D_PRIMITIVE_TOPOLOGY_LINESTRIP, // 将顶点数据解释为线条带
|
|
|
+D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP, // 将顶点数据解释为三角形带
|
|
|
+// ....
|
|
|
+```
|
|
|
+
|
|
|
+| 点列表 | 线条列表 | 线条带 | 三角形条带 |
|
|
|
+| --- | --- | --- | --- |
|
|
|
+|  |  |  |  |
|
|
|
+
|
|
|
+可以通过顶点坐标构成各种图形,但是有一个问题,那就是数据冗余的问题,以下图纹理
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+```cpp
|
|
|
+Vertex quad[6] = {
|
|
|
+ v0, v1, v2, // 三角形1
|
|
|
+ v0, v2, v3, // 三角形2
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+通过 `quad` 数组可以获得俩个三角形拼成的四边形,但是两个三角形中有两个数据(v0, v2)冗余了
|
|
|
+
|
|
|
+顶点中除了坐标信息,还可以存储颜色、法线等信息,这就意味着内存的浪费,为了处理这个冗余的问题,于是采用**索引**的方式来记录图元的顶点信息
|
|
|
+
|
|
|
+```cpp
|
|
|
+Vertex v[4] = {v0, v1, v2, v3};
|
|
|
+UINT indexList[6] = {
|
|
|
+ 0, 1, 2, // 三角形1
|
|
|
+ 0, 2, 3, // 三角形2
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+让图元的顶点信息通过索引获得, 这样顶点信息就没有冗余
|
|
|
+
|
|
|
+#### 顶点着色器阶段
|
|
|
+
|
|
|
+图元装配完毕之后,其顶点就会被送入**顶点着色器**阶段
|
|
|
+
|
|
|
+可以把顶点主送二七看作一种输入与输出皆为单个顶点的函数。每个要被绘制的顶点都须经过顶点着色器的处理,再送往后续阶段
|
|
|
+
|
|
|
+```cpp
|
|
|
+for(UINT i = 0; i < numVertices; ++i) {
|
|
|
+ outputVertex[i] = VertexShader(inputVertex[i]);
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+> 顶点着色器函数就是 `VertexShader` 要实现的部分
|
|
|
+
|
|
|
+通过顶点着色器可以实现变换、光照、位移贴图等特效。顶点着色器也可以访问顶点数据、纹理和其他存于显存中的数据(如变换矩阵、光照信息等)
|
|
|
+
|
|
|
+#### 曲面细分阶段
|
|
|
+
|
|
|
+曲面细分阶段利用镶嵌化处理技术对网格中的三角形进行细分,以此来增加物体表面上的三角形数量。再将新增的三角形偏移到适当的位置,是网格表现出更加细腻的细节
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+1. 可以实现细节层次机制(`Level-of-Detail`, `LOG`),即离虚拟相机近的三角形镶嵌化处理得到更丰富的细节,离相机远的三角形不进行任何更改
|
|
|
+2. 内存中只需要维护简单的**低模**网格,再根据需要动态增添额外三角形面
|
|
|
+3. 处理动画和物理模拟时采用简单的低模网格,仅在渲染的过程中使用经镶嵌化处理的高模网格
|
|
|
+
|
|
|
+#### 几何着色器
|
|
|
+
|
|
|
+几何着色器接受的输入应该是完整的图元,例如正在绘制三角形列表,那么几何着色器传入的将是定义三角形的三个顶点
|
|
|
+
|
|
|
+几何着色器可以创建或者销毁几何体,可以利用几何着色器将输入的图元拓展为一个或者多个其他图元
|
|
|
+
|
|
|
+#### 裁剪
|
|
|
+
|
|
|
+位于视锥体之外的几何体需要被丢弃,而处于平截头体交界意外的几何部分也一定要接受被裁剪的操作。因此只有在平截头体之内的物体对象才能最终保留下来
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+> 顶视图
|
|
|
+
|
|
|
+#### 光栅化
|
|
|
+
|
|
|
+光栅化阶段(rasterization stage, RS),也称栅格化、像素化,主要是为投影主屏幕上的3D三角形计算出对应的颜色
|
|
|
+
|
|
|
+当裁剪操作完成之后,硬件会通过透视除法将物体从齐次裁剪空间变换为规格化设备坐标(NDC)。一旦物体的顶点位于 NDC 空间内,构成 2D 图像的 2D 顶点 x、y 坐标就会被变换到后台缓冲区称为视口的矩形里。这些 x、y 坐标都将以像素为单位,z坐标通常用作深度值
|
|
|
+
|
|
|
+每个三角形都有两个面,假设三角形的顶点顺序为 v0,v1,v2
|
|
|
+
|
|
|
+一般规定如果顶点绕序为顺时针的三角形为正面朝向,而顶点绕序为逆时针的三角形为背面朝向,摄像机将看不到实体对象中背面朝向的三角形,**背面剔除**就是用于将背面朝向的三角形从渲染流水线中除去的处理流程
|
|
|
+
|
|
|
+`Direct3D` 可以通过设置将顺时针为正面的规则倒过来
|
|
|
+
|
|
|
+#### 顶点属性插值
|
|
|
+
|
|
|
+顶点除了位置信息外还有颜色、法向量、纹理坐标等属性
|
|
|
+
|
|
|
+经过视口变换之后,需要为求取三角形内所有像素所附的属性而进行插值运算
|
|
|
+
|
|
|
+除了顶点属性,还需要对顶点的深度进行插值,继而得到每个像素参与实现深度缓冲的深度值
|
|
|
+
|
|
|
+为了得到屏幕空间中各个顶点的插值属性,往往要通过一种名为**透视矫正插值**的方法,对3D空间中三角形的属性进行线性插值
|
|
|
+
|
|
|
+#### 像素着色器阶段
|
|
|
+
|
|
|
+也称片段着色器
|
|
|
+
|
|
|
+pixel shader PS 是一个中由 GPU 来执行的程序。它会针对每一个像素片段进行处理,并根据顶点的插值属性作为输入来计算出对应的像素颜色
|
|
|
+
|
|
|
+像素着色器既可以直接返回一种单一的恒定颜色,也可以实现如逐像素光照、反射、以及阴影扽给更为复杂的效果
|
|
|
+
|
|
|
+### 绘制几何体
|
|
|
+
|