概述
渲染流水线的最终目的在于生成或者说是渲染一张二维图像,即我们在电脑屏幕上看到的所有效果。
渲染流程大体可以分为三个概念阶段:
CPU流水线
- 应用阶段
开发者具有这个阶段的绝对控制权。
大致分为三个阶段:
- 把数据加载到显存中
渲染所需的数据从硬盘最终加载到显存中。在渲染时,GPU可以快速访问这些数据
-
设置渲染状态
渲染状态定义了场景中的网格是怎样被渲染的。例如,使用哪个顶点着色器/片元着色器、光源属性、材质等。 -
调用Draw Call
Draw Call只是一个命令,从CPU发送向GPU。这个命令仅仅会指向一个需要被渲染的图元列表,并且不会包含任何材质信息。
GPU流水线
GPU的渲染流水线接收顶点数据作为输入。这些顶点数据是由应用阶段加载到显存中,再由Draw Call指定的。
- 几何阶段
顶点着色器是完全可编程的,它的处理单位是顶点。顶点着色器需要完成的工作主要有:坐标变换、逐顶点光照和输出后续阶段所需的数据。必须完成的一个工作是,把顶点坐标从模型空间转换到齐次裁剪空间。
裁剪是为了不处理那些不在摄像机视野范围内的物体。这一步不可编程。裁剪过程:
屏幕映射的任务是把每个图元的*x*和*y*坐标转换到屏幕坐标系下。 将*x、y *坐标从(-1,1)范围转换到屏幕坐标系中:
注意:屏幕坐标系在OpenGL和DiretX之间存在差异:
- 光栅化阶段
三角形设置阶段会计算光栅化一个三角形网格所需的数据。
三角形遍历阶段将会检查每个像素是否被一个三角网格所覆盖。如果被覆盖,会生成一个片元。片元是包含了很多状态的集合,这些状态包括屏幕坐标、深度信息、法线、纹理坐标等。三角形遍历过程:
片元着色器是另一个非常重要的可编程着色器阶段。这一阶段可以完成很多重要的渲染技术,技术之一是纹理采样。在执行片元着色器时,它不能将自己的任何结果直接发送给它的邻居。这一阶段的输出是一个或多个颜色值。
逐片元操作这一阶段有几个主要任务:
- 决定每个片元的可见性。涉及许多测试工作:深度测试、模板测试等。
- 如果片元通过测试,需要把源颜色(通过测试的片元颜色)与目标颜色(颜色缓冲区中的颜色)进行混合。
此阶段所做的操作:
模板测试和深度测试简化流程图:
混合操作简化流程图:
Unity的渲染流水线中,深度测试是在片元着色器之前。
屏幕显示的就是颜色缓冲区的值,为了避免看到正在进行光栅化的图元,GPU会使用双重缓冲:即对场景的渲染发生在后置缓冲中。
Draw Call
Draw Call本身的含义很简单,就是CPU调用图像编程接口,如OpelGL中的glDrawElements命令。
Draw Call中造成性能问题的元凶是CPU
CPU和GPU实现并行工作
让CPU和GPU可以并行工作,解决方法是使用一个命令缓冲区:
Draw Call多了影响帧率
如果Draw Call的数量太多,CPU就会把大量时间花费在提交Draw Call上,造成CPU过载。
减少Draw Call
- 避免使用大量很小的网格。
- 避免使用过多的材质。
以便于Unity中利用批处理进行优化。