渲染流水线的最终目的在于生成或者说是渲染一张二维纹理,即我们在电脑屏幕上看到的所有效果。
流水线主要分成三个阶段:应用阶段,几何阶段,光栅化阶段。(概念)
一.概述
1. 应用阶段
这个阶段由应用主导,通常由CPU负责,开发者对这个阶段拥有绝对控制权。
在这一阶段,主要有三个任务
- 首先,需要准备好场景数据,例如相机,视椎体,场景中的模型,光源
- 其次,为了提高渲染性能,需要做一个粗粒度剔除的工作,把那些不可见的物体剔除,这样就不再需要移交几何阶段
- 最后,设置好每个模型的渲染状态,包括但不限于使用的材质,使用的纹理,使用的shader ,最终输出渲染图元,即渲染所需几何信息,一般是点,线,三角面等,这些图元最终会被传递到下一阶段。
2. 几何阶段
几何阶段用于处理所有和我们要绘制的几何相关的事情,这一阶段通常在GPU进行
3. 光栅化阶段
这一阶段将会使用上个阶段传递的数据来产生屏幕上的像素,并输出最终的图像,这一阶段也是在GPU进行
二.CPU和GPU通信
1. CPU流水线
渲染流水线的起点是CPU,即应用阶段,大致三个阶段
- 把数据加载到显存,例如顶点位置信息,法线方向,顶点颜色,纹理坐标等
- 设置渲染状态,这些状态定义了场景中的网格是怎样被渲染的
- 调用drawcall
2. GPU流水线
主要是几何阶段和光栅化阶段。
GPU的流水线接收顶点数据作为输入,这些顶点数据由应用阶段加载到显存,再由drawcall指定。
顶点着色器,通常用于实现顶点的空间变换,顶点着色等功能,完全可编程。
曲面细分着色器,一个可选的着色器,它用于细分图元。
几何着色器,一个可选的着色器,它可被用于执行逐图元的着色操作,或者用于产生更多的图元。
裁剪,将不在摄像机视野范围内的顶点裁剪掉,并剔除某些三角图元的面片,此阶段可配置。
屏幕映射,负责把每个图元的坐标转换到屏幕坐标系中,不可配置和编程。
1. 几何阶段
- 顶点着色器
输入来自CPU,处理单位是顶点,输入进来的每一个顶点都会调用一次顶点着色器,其本身不能创建或销毁任何顶点,而且无法得到顶点与顶点之间的关系,正是因为其相互独立性,GPU可以利用本身的特性并行化处理每一个顶点,这意味着这一阶段的处理速度会很快。
主要工作是坐标变换和逐顶点光照
坐标变换,顶点着色器可以在这一步改变顶点的位置,最基本的工作是,把顶点坐标从模型空间转换到齐次裁剪坐标空间,
即o.pos = UnityObjectToClipPos(v.vertex)
,接着再由硬件做透视除法,最终得到归一化的设备坐标NDC
- 裁剪
- 屏幕映射
此步的输入坐标仍然是三维坐标系下的坐标,其任务是把每个图元的x和y坐标转换到屏幕坐标系。
由于输入的坐标范围在-1到1,因此过程实际是一个缩放的过程。
屏幕映射不会对z坐标做任何处理,屏幕坐标系和z坐标一起构成了一个坐标系,叫窗口坐标系。
屏幕映射得到的屏幕坐标决定了这个顶点对应屏幕上哪个像素以及距离这个像素有多远
2. 光栅化阶段
从上一个阶段输出的信息是屏幕坐标系下的顶点位置以及它们相关的额外信息,如z坐标(深度值),法线方向,视角方向等。
此阶段有两个重要目标:
- 计算每个图元覆盖了哪些像素
- 以及为这些像素计算它们的颜色
-
三角形设置
这个阶段会计算光栅化一个三角形所需的信息。
上一阶段输出的都是三角网格的顶点,即三角网格每条边的两个端点,但如果要得到整个三角形网格对像素的覆盖情况,我们就必须计算每条边上的像素坐标,为了能够计算边界像素的坐标信息,我们就需要得到三角形边界的表示方式,此过程就叫三角形设置 -
三角形遍历
此阶段将会检查每个像素是否被一个三角形网格所覆盖,如果被覆盖,就生成一个片元,这个阶段也被称为扫描变换
其会使用三角网格的3个顶点信息对整个覆盖区域的像素进行插值
此步输出得到一个片元序列,一个片元并不是真正意义上的像素,而是包含了很多状态的集合,这些状态用于计算每个像素的最终颜色,这些状态包括但不限于屏幕坐标,深度信息,以及几何阶段输出的顶点信息,法线,纹理坐标等。 -
片元着色器
前面的阶段并不会影响屏幕上每个像素的颜色值,而是会产生一系列数据信息,用来表述一个三角网格是怎样覆盖每个像素的。
这一阶段可以完成很多重要渲染技术,其中最重要的技术之一是纹理采样。
片元着色器只能影响单个片元 -
逐片元操作
此阶段的任务主要有
- 决定每个片元的可见性,这涉及很多测试工作,例如深度测试,模板测试等
- 如果一个片元通过了所有测试,就需要把这个片元的颜色值和已经存储在颜色缓冲区的颜色进行混合