渲染流水线是将模型、光照、纹理等数据渲染成一幅2D图像的一个序列过程。
渲染流水线的功能
总结的来说渲染流水线的主要功能是在给定虚拟相机、光源、照明模式、三维物体以及纹理等诸多条件生成一幅二维图像的过程。
如上图,左侧的三维物体经过渲染流水线最终成为了右侧的2D图像,这其中影响2D图像生成的条件有相机位置,相机FOV值,相机投影方式,模型数据,贴图格式,着色器等诸多条件。
关于渲染流水线的发展
渲染流水线的发展主要分为两个阶段:固定管线阶段和可编程管线阶段。
固定管线阶段
在图形学发展的早期,开发者对图形的渲染拥有着很大的控制权,开发者通过调用硬件供应商提供的函数库来进行渲染,调用的渲染接口也是比较底层的,同时也存在着兼容性的问题。随着图形学的发展,图形核心系统(GKS)、开发者层次式交互图形系统(PHIGS)和OpenGL的出现 ,开发者开发的图形应用只需要简单的修改即可在不同的设备下使用。开发者对图形接口的调用都采用固定的方式来处理,这种方式被称为固定功能渲染流水线。固定流水线可以理解为对于多个渲染开关的设置。
可编程管线阶段
随着图形学的发展,开发者需要对整个渲染流水线有更大的控制权,图形设计者在渲染过程中增加了hook函数,用于突破固定流水线的限制。这个阶段开发者对于整个流水线的控制不再只有开关式的了,而是可以通过编程来定制的。
渲染流水线的3个阶段
渲染流水线根据其发生的位置和作用可以分为:
- 应用阶段
- 几何阶段
- 光栅化阶段
其中应用阶段在CPU中进行,而几何阶段和光栅化阶段则是在GPU中进行,后面两个阶段也被称为GPU流水线。
应用阶段
在应用阶段中,模型、贴图等数据从硬盘加载到了内存,再加载到了显存,方便GPU进行读取。(如下图)
主要任务
应用阶段由CPU负责,主要分为三个部分:
- 准备场景中需要渲染的数据
- 进行粗粒度剔除,把不可见的物体剔除
- 设置好物体的渲染状态(贴图、纹理和Shader等)
- 调用Draw Call
输出
- 图元的顶点数据
- 摄像机位置
- 光照纹理等
应用阶段是图形渲染流水线的起点,他的任务是将需要在屏幕上绘制的图元(具体包括顶点数据、摄像机位置和光照纹理),输出给渲染管线的下一阶段——几何阶段。
GPU流水线
几何阶段和光栅化阶段都是在GPU中进行的,这两个阶段称为**GPU流水线。**GPU流水线中包含多个过程,有些可编程,有些可配置,有些只能硬件调用。
上图为GPU流水线的概览,绿色表示该阶段是可编程控制的,黄色表示该阶段可配置但不可编程,蓝色表示该阶段是有GPU固定实现的,开发者没有控制权。虚线表示该阶段是可选的。
几何阶段
几何阶段的主要目的是将顶点数据最终进行屏幕映射。
顶点数据包括位置、法线、颜色、纹理坐标、切线方向、副法线方向、混合权重等
主要过程
几何阶段总的来说有以下几个过程
- 将图元通过模型变换到世界坐标中
- 根据光照、纹理等来计算顶点处材质的光照着色效果
- 根据摄像机位置、取景范围进行观察变换和裁剪
- 进行屏幕映射,把三维模型转换到屏幕坐标
接下来对几何阶段的各个阶段进行详细说明:
1.顶点着色器
- 顶点着色器主要负责坐标转换,将顶点坐标从模型空间转换到齐次裁剪空间
- 顶点光照
2.裁剪
将不在相机视野范围内的物体剔除,若某物体部分在视野外,其它在视野内的话,视野外的顶点则会用一个新的顶点代替。
3.屏幕映射
将每一个图元的坐标转换到屏幕坐标系中
输出
- 变换和投影后的顶点
- 颜色
- 纹理
光栅化阶段
光栅化的主要目的是对三角形逐个进行遍历获得屏幕上每个像素的颜色值。
1.三角形设置
三角形设置会计算光栅化一个三角网格所需的信息,将几何阶段获得的三角形顶点连接成三角形的边。
2.三角形遍历
三角形遍历会遍历每个三角形,将其覆盖的每一个像素点生成一个片元(包含屏幕坐标、深度信息、顶点信息、法线纹理坐标等,但不包含颜色信息),片元的状态是三个顶点插值的结果。
3.片元着色器
片元着色器将上一个阶段对顶点信息的颜色进行插值来取得每个像素点的颜色。
4.逐片元操作
这一阶段主要是对片元进行多个测试,来决定这个片元的颜色是否要与颜色缓冲区中的颜色进行合并,如深度测试、模版测试等。如果一个片元通过了所有的测试,那么就会将其颜色值与颜色缓冲区中的颜色进行合并。
下图是片元颜色与颜色缓冲区中颜色合并的具体过程:
输出
屏幕的各个像素的颜色值
参考:
https://www.cnblogs.com/luming1979/p/3627382.html
https://cg.informatik.uni-freiburg.de/course_notes/graphics_01_pipeline.pdf
《Unity Shader入门精要》