渲染流水线
目录
总体介绍
在《Real-Time Rendering, Third Edition》一书中将一个渲染流程分成3个阶段:应用阶段(Application Stage)、几何阶段(Geometry Stage)、光栅化阶段(Rasterizer Stage)。
本文将根据这三个阶段依次介绍。
应用阶段
该阶段主要在CPU中完成。
完成三个任务:(1)把数据加载到显存中,准备场景数据。(2)进行不可见物体的剔除。(3)设置渲染状态。
输出:渲染图元。
几何阶段
该阶段主要在GPU中完成。
主要任务:把顶点坐标变换到屏幕空间中,再交给光栅器进行处理。
输出:屏幕空间的二维顶点坐标、顶点对应的深度值、着色等相关信息。
过程:
(蓝色表示GPU固定实现,绿色表示可编程控制,黄色表示可配置但不可编程)
顶点着色器(Vertex Shader)
主要任务:坐标变换、逐顶点光照。
坐标变换:输入的每个顶点都会调用一次,完成坐标变换。(模型空间->齐次裁剪空间)
模型空间到齐次裁剪坐标代码:
o.pos = mul(UNITY MVPv.position);
曲面细分着色器(Tessellation Shader)
将一个模型的面合理的分成更多小的面,从而提升模型精度,提高渲染效果,让物体更加趋近于真实世界。
几何着色器(Geometry Shader)
进行逐图元的着色操作。
裁剪(Clipping)
将不在摄像机视野内的顶点裁剪掉,并剔除某些三角图元的面片。
图元和摄像机视野关系:
- 完全在视野内
- 完全在视野外
- 部分在视野内
屏幕映射(Screen Mapping)
把裁剪后的齐次坐标转换到屏幕坐标系 (二维),Z轴不做处理。
窗口坐标系:屏幕坐标系和z坐标一起构成的坐标系。
屏幕坐标系的差异: OpenGL原点在左下角,Directx原点在左上角。
光栅化阶段
该阶段主要在GPU中完成。
主要任务:使用上阶段输入的顶点数据产生屏幕上像素,最终渲染出来图像。决定渲染图元中的哪些像素应该被绘制在屏靠上,对上一个阶段得到的逐顶点数据(例如纹理坐标、顶点坐标)进行插值,然后再进行逐像素处理。
过程:
(蓝色表示GPU固定实现,绿色表示可编程控制,黄色表示可配置但不可编程)
三角形设置(Triangle Setup)
把输入的顶点数据连接得到三角形面片。
三角形遍历(Triangle Traversal)
检查是否每个像素被一个三角形网格覆盖(也称为扫描变换),覆盖就会产生片元。
- 一个片元并不是真正意义上的像素,而是包含很多状态的最终集合。这些状态用于计算每个象素的最终颜色,
- 这些状态包含但不限于屏幕坐标、深度信息、顶点信息。
片元着色器(Fragment Shader)
实现逐片元的着色操作,纹理坐标进行插值。
逐片元操作(Per-Fragment Operations)
决定每个片元的可见性,片元的颜色和存储在颜色缓冲区的色彩进行合并。执行很多操作,如修改颜色、深度混合、是否进行混合等。
在DirectX中,这一阶段被称为输出合并阶段。(这个名称似乎更好理解这一阶段完成的任务)
模板测试(Depth Test)
通常用于限制渲染区域,或者渲染阴影,轮廓渲染等。
总结
值得一提的是,真正的实现过程远比上面讲到的要复杂。同时,我们这里给出的流水线名称、顺序可能和在一些资料上看到的不同。一个原因是由于图像编程接口(如 OpenGL 和 DirectX) 的实现不尽相同,另一个原因是 GPU 在底层可能做了很多优化。
希望本文对大家理解渲染流水线有一些帮助。