渲染管线
应用阶段
准备好场景数据,包括 Camera 的位置、朝向,视锥体,场景物件、光源信息,渲染对象的渲染状态准备包括材质、纹理、Shader 等基本信息,调用渲染图元的指令。
- 把数据加载到显存
- 设置渲染状态
- 调用 DrawCall
几何阶段
传入顶点数据,经过顶点着色器、曲面细分着色器、几何着色器、三角形裁剪、屏幕映射。
- 顶点着色器:操作顶点,可编程。主要是坐标变换和逐顶点光照,输出后续阶段需要的数据,从模型空间到齐次裁剪空间。
- 曲面细分着色器、几何着色器:目前在手机上支持不是很好,手机渲染基本上不能用。
- 三角形裁剪:把那些不在摄像机视野范围内的顶点裁剪掉,并剔除掉不在屏幕范围内的顶点。这个过程可配置。
- 屏幕映射:把图元的顶点坐标转化为屏幕坐标系的二维坐标,输入的是三维坐标(归一化的 NDC 坐标)。
光栅化阶段
光栅化阶段的目的有两个:①计算每个图元覆盖了那些像素,②为这些像素计算他们的颜色。
- 三角形设置:上一个阶段,我们已经拿到了图元顶点的屏幕二维坐标,包括顶点法线、深度值、视角方向等信息,根据这些信息,我们来计算光栅化一个三角形所需要的信息,比如该三角形包含那些像素点等。
- 三角形遍历:在这个阶段会检测每个像素的中心(或者说每个采样点)是否被三角形覆盖,像素中三角形覆盖的部分会生成一个 fragment,而寻找采样点或者像素位于哪个三角形上,这一过程被称为三角形遍历。而三角形中我们所生成的每一个fragment,其属性都由三角形的顶点插值而来。这些属性包括fragment 的深度和从几何阶段传输来的其他着色数据
- 片元着色器:可编程,作用是处理上一个阶段生成的每个片元,最终计算出每个像素的最终颜色。实际上就是数据的集合。这个数据集合包含每个像素的各个颜色分量和像素透明度的值。
- 逐片元操作:修改颜色,修改深度,混合
- 屏幕图像
顶点数据
一个模型或者图形是由点线面构成的,为了让计算机绘制出这个图形,就必须告诉计算机这些数据的值,顶点数据包括顶点坐标、坐标的法线、坐标的切线、颜色等信息。 对于 OpenGL,这些数据一般都是向量结构体。对于游戏引擎,这些数据来自导入的模型中。在开始渲染之前,CPU 会获取这些数据,然后传递给 GPU,作为最原始数据,做好计算准备。
顶点着色器
顶点着色器(vertex shader) 在渲染管线中的作用非常大,是渲染管线的第一个可编程着色器。处理单元是顶点数据。顶点着色器的主要功能是对坐标进行变换。将输入的局部左边变换到世界坐标、观察坐标和裁剪坐标。 除此之外当然也可以进行光照着色,但是着色效果远不如在片元着色器中进行光照着色,因为计算量较小。
图元装配
图元装配(primitive assembly)是对传入的顶点数据进行重新组装,将顶点着色器的输出作为输入。 这一点正验证了渲染的过程是以流水线的形式进行的,图元装配会将顶点装配成指定的图形,与此同时,会进行裁剪、表面剔除等操作,以减少不必要的计算,加速渲染过程。
几何着色器
几何着色器(geometry shader)会将图元装配阶段的数据作为输入数据。几何着色器属于不可编程阶段,由硬件设备自动完成, 其重要作用是对顶点数据进行重构, 可以在此阶段产生新的顶点数据,来弥补之前存在的一些问题。以便为接下来要进行的操作做好充分的准备工作。
光栅化
光栅化阶段(rasterization stage)的数据输入来自几何着色器的输出数据,为了实现顶点到屏幕像素的映射。 光栅化的作用就是将两个顶点之间缺少的像素点通过插值的形式进行补充,生成片元着色器可以处理的片段。此阶段由硬件完成插值极端。在插值的过程中,会将不可见的顶点进行剔除。
片元着色器
片元着色器处理的对象是像素点的颜色信息,也是最终显示在屏幕上的像素点,在这个过程中,可以处理光照和阴影计算,将处理完的值保存至缓冲区中。
混合处理阶段
混合处理阶段属于屏幕后期梳理范围,这意味着此阶段主要做的任务为屏幕优化操作,通过片元着色器得到的像素,有些不能被显示出来,比如透明度为 0 的像素点,对于这类像素点,我们需要进行测试,测试的范围包括 Alpha 测试、模板测试和深度测试等。不能通过测试的像素点将会被丢弃,就不会参与接下来的操作;通过测试的像素会进入混合阶段。混合阶段主要是处理透明物体,混合阶段不需要进行编程,但是常见的渲染管线接口会开放初一些参数给程序员做调整。