3D视觉的表示:根据人们在真实生活中观察物体的经验,我们可以总结出一些规律。运用这些规律,我们便可以通过2D图像模拟出3D效果的场景。我们可以观察到的规律有:平行线会聚于消失点,物体的尺寸受其深度的影响(近大远小),离观察者近的物体会遮挡其后距观察者远的物体,光照与阴影的明暗对比可以刻画出3D物体的实体形状和体积感,阴影还暗示了光源的位置,并反映出场景中不同物体之间的相对位置。
模型的表示:我们用三角形网格来近似的表示物体。并通过指定三角形的3个顶点来定义三角形。在许多网格中都存在着顶点被不同三角形所共有的现象,而索引列表则可以用于避免因重复使用顶点而复制顶点数据所带来的冗余信息。
色彩的表示:如下所示:
1.我们可以通过指定红,绿,蓝三色光的强度来描述颜色。利用此三色光不同强度的相加混色,可以使我们表示出数以千万计的颜色。
2.我们通常用归一化范围 0 ~ 1 来描述三色的强度,0表示没有强度,1表示最高强度,两者之间的值表示相应的中间强度。
3.一般来说还会加入另一种名为alpha分量的颜色分量来表示颜色的不透明度,这在混合技术中是很有用的。
4.为了能用128位数据来表示颜色,每一个分量都被分配四个字节;DirectXMath库提供了XMVECTOR类型来存储128位颜色值,其中 0 ≤ r,g,b,a ≤ 1。在使用DirectXMath向量函数进行颜色值运算时,我们还可以从SIMD技术中受益。
5.为了能用32位数据来表示颜色,每一个分量都将被分配一个字节;DirectXMath库提供了XMCOLOR结构体来存储32位颜色值,其中 0 ≤ r,g,b,a ≤ 255。
6.通过XMLoadColor函数将32位颜色对象转换成128位颜色对象;通过XMStoreColor函数将128位颜色对象转换成32位颜色对象。
7.在计算颜色向量的加法,减法和标量乘法时,除了需要将分量钳制在区间[0, 1]之中,其余都与普通向量的运算相同。而其他诸如点积,叉积这样的向量运算,对颜色向量而言都是没有意义的。此外,符号⊗表示分量式乘法,它的定义为(c1, c2, c3, c4) ⊗ (k1, k2, k3, k4) = (c1k1, c2k2, c3k3, c4k4)。
渲染流水线:如下所示:
1.渲染流水线也叫做渲染管道,渲染管线,绘制流水线,图形流水线等。
2.可以把渲染流水线想象为一个工厂里的流水线,里面有不同的加工环节(也就是渲染阶段),可以根据用户需求对每个环节灵活改造或拆卸(也就是在不同的着色器中编写自定义函数以及开启或者禁用某些渲染阶段)。以此把原始材料(CPU端向GPU端提交的纹理资源以及指令等)加工为成品(像素颜色)出售给消费者(用户屏幕)。
3.渲染流水线的各个阶段如图所示:
4.Input Assembler Stage(输入装配阶段)会从显存中读取几何数据(顶点和索引),并将它们装配为几何图元(三角形和线条)。具有以下特性:
1>.顶点缓冲区利用连续的内存来存储一系列顶点,并将顶点与渲染流水线相绑定。
2>.图元拓扑用来告诉Direct3D如何用顶点数据来表示几何图元。
3>.通过ID3D12GraphicsCommandList::IASetPrimitiveTopology函数来修改图元拓扑之前,所有的绘制调用都会沿用当前设置的图元拓扑方式。
4>.经过观察可以发现,当图元拓扑为三角形带类型时,次数为偶数的三角形与次数为奇数三角形的绕序是不同的,这就是剔除问题的由来。为了解决这个问题,GPU内部会对偶数三角形中后两个顶点(在OpenGL中为前两个顶点)的顺序进行调换,以此使它们与奇数三角形的绕序保持一致。
5>.每个图形适配器都具有特定大小的缓存,刚处理过的顶点可以被临时存储在缓存当中,由于缓存的读取速度比顶点缓冲区快,因此可以利用这一点来提升软件的性能。不同硬件的缓存大小有别,因此应该安排好顶点顺序,首先引用需要复用的顶点,在这些顶点扔位于缓存之中时尽快引用。
6>.采用索引技术来复用顶点数据的工作流程为:先创建一个顶点列表和一个索引列表。在顶点列表中收录一份所有独立的顶点,并在索引列表中存储顶点列表的索引值,这些索引定义了顶点列表中的顶点是如何组合在一起,从而构成三角形的。
5.Vertex Shader Stage(顶点着色器阶段)是一种输入和输出数据皆为单个顶点的函数。具有以下特性:
1>.每个要被绘制的顶点都须经过顶点着色器的处理再送往后续阶段。
2>.使用局部空间(也叫做模型空间)来构筑3D模型具有易于使用和重复使用等优点。
3>.世界矩阵用来将物体从局部空间变换到世界空间。它的数学公式如下所示:
其中W为世界矩阵;行向量(ux, uy, uz)代表局部空间的x轴相对于世界空间的齐次坐标;行向量(vx, vy, vz)代表局部空间的y轴相对于世界空间的齐次坐标;行向量(wx, wy, wz)代表局部空间的z轴相对于世界空间的齐次坐标;行向量(qx, qy, qz)代表局部空间的原点相对于世界空间的齐次坐标;缩放矩阵S将物体缩放到世界空间;旋转矩阵R用来定义局部空间相对于世界空间的朝向;平移矩阵T定义的是局部空间的原点相对于世界空间的位置。
4>.观察空间(也叫做视图空间,视觉空间,摄像机空间)用于在渲染流水线的后续阶段中描述这些顶点相对于摄像机坐标系的坐标。
5>.观察矩阵用来将物体从世界空间变换到观察空间。只要我们提供虚拟摄像机位置,观察目标点以及世界空间中向上方向的向量,我们就可以通过XMMatrixLookAtLH函数来获取观察矩阵。它的数学公式如下所示:
其中V为观察矩阵;行向量(ux, uy, uz)代表观察空间的x轴相对于世界空间的齐次坐标;行向量(vx, vy, vz)代表观察空间的y轴相对于世界空间的齐次坐标;行向量(wx, wy, wz)代表观察空间的z轴相对于世界空间的齐次坐标;Q代表虚拟摄像机的位置;u代表虚拟摄像机局部空间的x轴;v代表虚拟摄像机局部空间的y轴;w代表虚拟摄像机局部空间的z轴。
6>.顶点的投影线指的是从观察点到顶点之间的连线。
7>.投影指的是顶点的投影线与投影平面的交点。
8>.可以通过近平面n,远平面f,垂直视场角α以及纵横比r这四个参数来定义一个平截头体。具有以下特性:
1>>.纵横比r的取值应该跟后台缓冲区的纵横比保持一致,这样当投影窗口中的2D图像映射到后台缓冲区时,才不会发生拉伸现象。
2>>.一般建议近平面n与远平面f尽可能的接近,以改善深度值的精度问题。
3>>.可以通过垂直视场角α和纵横比r来确定水平视场角β。数学公式如下所示:
4>>.点 (x, y, z) 在投影平面 z = d 中的投影点为 (x’, y’, d)。其中 x’ = x / z * tan(α / 2),y’ = y / z * tan(α / 2)。当 -r <= x’ <= r, -1 <= y’ <= 1,n <= z <= f 时,表明点 (x, y, z) 位于平截头体内。
5>>.投影矩阵用来将物体从观察空间变换到投影空间(也叫做齐次裁剪空间)。只要我们提供用弧度制表示的垂直视场角,纵横比,近平面的距离以及远平面的距离,我们就可以通过XMMatrixPerspectiveFovLH函数来获取投影矩阵。它的数学公式如下所示:
6>>.NDC表示规范化设备坐标,其中1个NDC单位等于观察空间中的r个单位。可以通过透视除法将齐次裁剪空间中点除以w分量值,从而得到NDC空间的点。
6.Tessellation Stage(曲面细分阶段)是利用镶嵌化处理技术对网格中的三角形进行细分,以此来增加物体表面上的三角形数量。再将这些新增的三角形偏移到适当的位置,使网格表现出更加细腻的细节。具有以下优点:
1>.借此实现LOD机制,使离虚拟摄像机较近的三角形经镶嵌化处理得到更加丰富的细节,而对距离摄像机较远的三角形不进行任何更改。
2>.在内存中仅维护简单的低模网格,再根据需求为它动态的增添额外的三角形,以此节省内存资源。
3>.在处理动画和物理模拟之时采用简单的低模网格,而仅在渲染的过程中使用经镶嵌化处理的高模网格。
7.Geometry Shader Stage(几何着色器阶段)是将输入的几何图元拓展为一个或者多个其他几何图元,抑或根据某些条件而选择不输出任何几何图元。
8.Rasterization Stage(光栅化阶段)的主要任务是为投影主屏幕上的3D三角形计算出对应的像素颜色。具有以下特性:
1>.NDC空间中顶点的x,y坐标会变换到后台缓冲区中的视口矩形里,并以像素为单位。
2>.根据观察者的视角看去,顶点绕序为顺时针方向的三角形为正面朝向,而顶点绕序为逆时针方向的三角形为背面朝向。
3>.背面剔除就是用于将背面朝向的三角形从渲染流水线中除去的处理过程。
9.Pixel Shader Stage(像素着色器阶段)会针对每一个像素片段进行处理,并根据顶点的差值属性作为输入来计算出对应的像素颜色。
10.Output Merger Stage(输出合并阶段)会舍弃没有经过深度测试和模板测试的像素片段,并将剩余的像素片段通过是否与后台缓冲区中的像素片段进行混合处理,然后将最终像素片段写入到后台缓冲区中。