渲染流水线
计算机在渲染的时候,把任务分成了一系列的特定子阶段,这些阶段按照一定的顺序来处理顶点数据,最后生成图像,这些子阶段就构成了流水线。整个流水线是由CPU和GPU共同完成。
应用程序阶段
此阶段开发者通过代码来控制CPU进一步访问GPU
此阶段主要有三个任务:
1.准备好场景数据:如场景物件、光源和相机等。
2.设置渲染状态:材质系数、使用的纹理等。
3.调用DrawCall:当渲染相关的一切数据和状态都准备好之后,将这些信息输出到下一阶段开始进行绘制。几何阶段
在GPU中进行,将顶点坐标变换到剪裁空间中。- 光栅化阶段
绘制图像。在GPU中进行,输入几何阶段输出的逐顶点数据,根据这些数据输出并渲染最终的图像
CPU和GPU之间的通讯
此阶段属于应用程序阶段。
加载数据到内存
显卡对显存的访问速度更快,所有要渲染的数据先加载到系统内存,网格和顶点数据需要加载到显存。设置渲染状态
渲染状态用于知识GPU如何渲染一个物体,CPU通过DrawCall命令来通知GPU使用指定的状态来渲染给定的数据调用DrawCall
DrawCall实际上是一个命令,它的发起方是CPU,接收方是GPU,CPU通过这个命令通知GPU进行渲染并输出图像到屏幕。
GPU流水线
此阶段属于最后的两个阶段。
GPU为每个流水线阶段提供了不同的可配置性和可编程性。GPU流水线中几何阶段和光栅化阶段都包含若干固定的子流水线阶段,这些流水线阶段的实现,有些提供了参数供开发者修改,这称之为可配置。有些则是完全由开发者通过shader语言定义的函数来实现的,这称之为可编程。
几何阶段
顶点着色器(Vertex Shader):可编程,必须
把顶点坐标从模型空间转换到的剪裁空间(屏幕)。类似下面代码:
o.pos = mul(UNITY_MVP,v.position)
曲面细分着色器(Tessellation Shader):可编程,可选
几何着色器(Geometry Shader):可编程,可选
裁剪(Clipping):可配置
这一阶段主要是把不在视野范围的图元给剔除掉,对部分可见的图元进行裁剪,同时会根据图片朝向或者背离相机来决定是否需要剔除(一般会剔除背面)。
这一过程是不可编程的,但是我们可以通过定义裁剪面或者设置正反面剔除模式来进行配置。
屏幕映射(Screen Mapping):不可控
这一步的输入还是三维空间下的坐标,它的任务是把图元的x和y转换到屏幕坐标系下,不会对输入的z坐标做任何处理。
光栅化阶段
三角形设置(Triangle Setup):不可控
这是光栅化的第一个阶段,光栅化阶段的主要目标是:计算每个图元覆盖了哪些像素,并计算这些像素的颜色。这一阶段的输入是三角网格的三个顶点,这些顶点的信息是由上一阶段输出的。
三角形遍历(Triangle Traversal):不可控
这一阶段的主要任务是扫描每个像素,根据上一阶段得到的三角形边界信息,决定其是否被当前图元(这里就是三角形)所覆盖。
对覆盖的每个像素生成一个片元,这些片元的顶点信息(屏幕坐标、深度z,法线方向等所有信息)将通过对三角网格的三个顶点进行插值得到。
这一阶段的输出是片元序列。注意,片元对应像素,但片元不是像素,它包含了很多顶点信息和状态用以计算对应像素的颜色。
片元着色器(Fragment Shader):可编程,必须
这一阶段会遍历上一阶段的片元序列并对每个片元执行片元着色器。
在这个阶段最重要的技术就是进行纹理采样。片元着色器仅影响单个片元。
逐片元操作(Per-Fragment Operations):可配置
这一阶段在Direct3D中称为合并/混合阶段。已经很明确了这一阶段的的操作单位是片元,目的是将上一阶段输出的片元颜色与颜色缓冲区中的颜色进行颜色混合。