3D物体:由三角形组成的几何形状构成的物体
顶点:具有空间坐标和其他意义(颜色、纹理坐标)的点
纹理:映射到3D物体表面的图像,提供物体由某种材质构成的幻觉,物体定点存储的二维向量坐标,用于指定纹理如何映射到给定的表面
渲染管线:又叫渲染流水线,将数据从3D场景转换成2D图像,最终在屏幕上显示出来的总过程,其主要分为应用阶段、几何阶段、光栅阶段
片元:不是真正意义上的像素,而是很多状态的集合,这些状态用于计算每个像素的最终颜色,例如屏幕坐标、深度信息、几何阶段输出的顶点信息(法线、纹理坐标等)
渲染图元(render primitives):渲染所需的几何信息,点、线、面等,这些数据会传递给下一阶段——几何阶段
渲染流水线分为三个阶段
渲染图元(render primitives):渲染所需的几何信息,点、线、面等,这些数据会传递给下一阶段——几何阶段
由于应用阶段又CPU主导,并且下一阶段几何阶段是在GPU中进行,故而会涉及到CPU与GPU通信的问题,我们可知应用阶段的大致分为以下三步:
硬盘HDD ——>系统内存RAM ——>显存VRAM
所有渲染数据都需要先从磁盘中加载到系统内存,然后经过相关应用系统(Unity),将组织好的数据加载到显存中,主要是因为显卡对于显存的访问速度更快,且大多数显卡对于RAM没有直接的访问权限
渲染状态:定义场景中的网格是怎样被渲染,例如使用什么样的着色器、光源属性、材质
Draw Call:发起方位CPU接收方位GPU的指令,包含一个需要被渲染的图元列表
当给定了一个Draw Call的时候,GPU就会根据渲染状态和所有输入的顶点数据来进行计算,最终在屏幕上绘制出像素,此过程在GPU中进行,为GPU流水线
在渲染流水线的后两个阶段,即几何阶段和光栅化阶段,GPU通过实现流水线化,加快了渲染的速度,但这些阶段由GPU来实现,我们无法拥有绝对的掌控权,但是其提供了部分配置性和可编程性
几何阶段流程:顶点着色器 ——> 曲面细分着色器 ——> 几何着色器 ——> 裁剪 ——> 屏幕映射
接收参数:顶点数据
输入来自CPU,处理单位为顶点,本身不可以创造或销毁顶点,且无法获得顶点之间的互相关系,因此GPU可以利用相互的独立性并行优化每一个顶点,处理速度更快
工作内容:坐标变换和逐顶点光照、输出后续阶段所需数据
改变顶点位置(模拟水面、布料等效果)
把顶点坐标从模型空间转换到齐次裁剪空间,接着通常由硬件做透视除法,得到归一化设备坐标NDC
图元跟摄像机视野的三种关系:
输入参数:三维坐标系下的坐标(范围在单位立方体内)
目的:把每个图元的x和y坐标转换到屏幕坐标系(二维坐标系)下
屏幕映射不会对z坐标做任何处理,屏幕坐标系和z坐标一起构成了一个坐标系,叫做窗口坐标系,这些值会一起传递到光栅化阶段,屏幕映射得到的屏幕坐标决定了这个顶点对应屏幕上哪个像素以及距离这个像素由多远
OpenGL:把屏幕左下角当成最小的窗口坐标值
DirectX:把屏幕的左上角作为最小的窗口坐标值
输入数据:
目的:
计算光栅化一个三角形所需要的信息,通过上一阶段得到的顶点信息,得到三角形的表示方式,从而计算每条三角边上的像素坐标,它的输出为下一阶段的三角形遍历做准备
检查每一个像素是否被一个三角形网格所覆盖,如果是的话,则生成一个片元(fragment),该阶段会使用三角网格3个顶点的顶点信息对整个覆盖区域进行插值
输出:一个片元序列
可编程着色器阶段
输入:上一阶段对顶点信息插值的结果,根据从顶点着色器中输出的数据插值得到
输出:一个或者多个颜色值
这一阶段完成很多重要的渲染技术,其中之一有纹理采样,所需的纹理坐标,是在顶点着色器中输出每个顶点对应的纹理坐标,然后在光栅化阶段对三角网络的3个顶点对应的纹理坐标插值后,就可以得到其覆盖的片元的纹理坐标
局限性:仅可以影响单个片元,不可以将其执行的结果发送给其他片元
渲染流水线的最后一步,高度可配置
目的:合并
主要任务:
可见性判断的简单流程:
片元 ——> 模板测试 ——> 深度测试 ——> 混合 ——> 颜色缓冲区
测试的实际过程相较来说更为复杂,且不同图形接口(OpenGL和DirectX)的实现细节不尽相同
开启模板测试后,GPU会首先读取(使用读取码)模板缓冲区中该片元的模板值,然后将该值和读取(使用读取码)到的参考值进行比较,比较函数是又开发者指定的,如果这个片元没有通过这个测试则会被舍弃,不管一个片元有没有通过模板测试,都会根据模板测试和深度测试的结果来修改模板缓冲区的,这个修改操作也是开发者指定的,例如,在失败时模板缓冲区不变,通过时将模板缓冲区对应位置的值加1等
应用:限制渲染区域、渲染阴影、轮廓渲染(如何应用的?)
通过了模板测试之后才可以进入深度测试,开启深度配置后,GPU会把该片元的深度值和已经存在与深度缓冲区中的深度值进行比较,比较方法又开发者配置,通常比较函数式小于等于,即如果这个片元的深度值大于等于当前深度缓冲区的值,就舍弃。如果这个片元没有通过深度测试,就无法修改深度缓冲区的值,如果通过则可以通过开发者指定是否覆盖掉原有深度缓冲区中的深度值,通过开启/关闭深度写入来达到这个目的
如果一个片元通过了模板测试和深度测试就可以进入合并功能
渲染过程是一个物体接一个物体画到屏幕上的过程,每个像素的颜色信息存储在颜色缓冲区,在执行某次渲染的时候,颜色缓冲区中有了上次渲染的结果,我们使用当前渲染得到的颜色完全覆盖掉之前的结果,还是其他处理,需要得到解决
不透明物体:通过关闭混合操作,让片元着色器计算得到的颜色值直接覆盖掉颜色缓冲区的像素值
半透明物体:使用混合操作来使这个物体看起来是透明的,GPU取出源颜色(片元着色器得到的颜色)和目标颜色(颜色缓冲区中的颜色),将两种颜色进行混合,混合方式是根据开发者配置的混合函数
Early-Z技术:将深度测试提前到片元着色器之前的技术,好处在于尽早地知道了哪些片元是被舍弃的,对于这些片元可以不需要再使用片元着色器进行计算,大大提高了GPU的渲染性能