渲染管线(Randering Pipeline)
渲染管线是将网格、纹理等信息从加载到展现在屏幕上的整个过程,也叫做渲染流水线。是给定坐标系、镜头、物体、纹理、光源等信息后如何呈现为二维画面的流程。这些流程以流水线的方式工作。相对于没有流水线的渲染方式,流水线各个环节互相干扰小,渲染效率也高了很多。
下图为有流水线和无流水线的效率比对:
Shader按管线分类一般分为固定渲染管线和可编程渲染管线。早期GPU遵循固定管线(Existing Fixed Function Pipeline),光源算法相对固定,只能通过贴图来改变,通常只有塑料的质感,无法操作间接光及环境光,早已过时。
下图为常见图形API从固定管线向可编程管线进化的版本:
3D API | 最后支持固定管线的版本 | 第一个支持可编程管线的版本 |
---|---|---|
OpenGL | 1.5 | 2.0 |
OpenGL ES | 1.1 | 2.0 |
DirectX | 7.0 | 8.0 |
实际上现阶段所使用的渲染管线都是可编程渲染管线,原有的固定渲染管线功能也基本上被新的可编程管线模拟替代,大部分后期发布的显卡都已经彻底移除了固定渲染管线的概念。
渲染流程
渲染的整个流程是由CPU发起的,游戏本身使用CPU判断哪些物体需要渲染,找到需要渲染的物体后逐个调用系统对应的图形API,每一个物体都会调用一次DrawCall,这个DrawCall就是CPU通知显卡开始渲染的过程。当显卡接收到DrawCall后,会对指定的物体进行处理,最终显示在屏幕上。下图为渲染流程概念图:
可编程渲染管线
渲染管线从概念上划分大致可以分为三个阶段:
- 应用阶段(Application Stage);
- 几何阶段(Geometry Stage);
- 光栅化阶段(Rasterizor Stage)。
每个阶段都有其独有的子流水线。如下图所示:
应用阶段
应用阶段工作是在CPU中进行的,主要有三大任务:
- 准备场景数据(相机、光源、模型等);
- 粗粒度剔除(Culling),将不可见物体剔除;
- 设置渲染状态,包括材质(漫反射颜色、高光反射颜色等)、纹理、shader等。
这一阶段最重要的工作是输出渲染几何信息,即渲染图元(Rendering Primitives),渲染图元可以是点、线、三角面等几何信息,这些渲染图元将会被传递给下一个阶段。
注意:应用阶段是开发者主导的,与Shader基本无关。
应用阶段又可以大致分为三个阶段:
- 把数据加载到显存中;
- 设置渲染状态;
- 调用DrawCall。
把数据加载到显存中
所有渲染数据都是从硬盘加载到内存中,然后将其中的网格、纹理、顶点位置信息、法线方向、顶点颜色、纹理坐标等数据加载到显存中。这是因为显卡访问显存更快,且大多数显卡对于RAM没有直接访问权。
有部分信息加载到显存(VRAM)后就可以从内存中移除了,但有些数据仍然需要访问,例如:CPU访问网格数据进行碰撞监测。
数据加载完成后,渲染数据将会同时存在于硬盘、内存、显存中,而内存和显存的空间是有限的,所以优秀的开发者应该更多的考虑减少空间占用,减轻硬件负荷,以此提高游戏运行效率。
设置渲染状态
渲染状态定义了网格是如何被渲染的,包括使用哪个顶点着色器/片元着色器、光源属性、材质等。
调用DrawCall
DrawCall是从CPU向GPU发送的一个命令,这个命令指定一个需要被渲染的图元(Primitives)列表,通知GPU将其渲染。
几何阶段、光栅化阶段
几何阶段和光栅化阶段的工作是在GPU中进行的,而GPU只给了部分控制权限。实际上这两个阶段可以分为若干个更小的流水线阶段,这些流水线阶段有GPU来实现,每个阶段提供了不同的可配置性和可编程性。
GPU渲染管线是以接收顶点数据作为入口,这些数据是由应用阶段加载到显存中,再由DrawCall指定的。
更多内容请查看总目录【Unity】Unity学习笔记目录整理