《shader入门精要》笔记-第2章-渲染流水线

看完数学部分后再来写的

CPU流水线

将数据加载到显存中

  1. 把渲染所需所有数据从硬盘加载到系统内存中
  2. 网格和纹理等数据又被加载到显存中

设置渲染状态

这些状态定义了场景中的网格是怎么被渲染的
例如,使用哪个顶点着色器/片元着色器,光源属性,材质等.
如果我们没有设置渲染状态,那么所有网格都将使用同一种渲染状态

调用DrawCall

Draw Call是一个命令,发起方是CPU,接收方是GPU.
这个命令仅仅会指向一个需要被渲染的图元的列表,而不再包含任何材质信息–因为已经在上个阶段完成了.

当给定一个Draw Call时,GPU会根据渲染状态(材质,纹理,着色器等)和所有输入的顶点数据来进行计算,最终输出到屏幕

GPU流水线

顶点数据 -> 顶点着色器 -> 曲面细分着色器 -> 几何着色器 -> 裁剪 -> 屏幕映射 -> 三角形设置 -> 三角形遍历 -> 片元着色器 -> 逐片元操作 -> 屏幕图像

顶点着色器

顶点无法销毁或创建顶点,也不可以获得顶点之间的联系.例如,我们无法判断两个顶点是否处于同一个网格.正是因为这样的相互独立性,GPU可以利用本身的特性并行化处理每一个顶点,这意味着这一阶段的处理速度会更快.
顶点着色器需要完成的主要工作有:坐标变换逐顶点光照
当然除了这两个主要任务外,顶点着色器还可以输出后续阶段所需的数据.

坐标变换

把顶点坐标从模型空间变换到齐次剪裁空间

剪裁

摄像机的视野范围内很有可能不会覆盖场景中的所有物体.不在摄像机视野范围内的物体不需要处理.剪裁就是为了完成这个目标而被提出来的.

我们无法通过编程来控制剪裁的过程,而是硬件上的固定操作,但我们可以自定义一个剪裁操作来对这一步进行配置.

屏幕映射

屏幕映射的任务是把每个图元的x,y坐标转换到屏幕坐标系.

三角形设置

从这一步开始进入光栅化阶段.
从上一个阶段输出的信息是屏幕坐标系下的顶点位置以及它们的额外信息,如深度值(z坐标),法线方向,视角方向等.
光栅化阶段有两个最重要的目标:计算每个图元覆盖了哪些像素,以及为这些像素计算它们的颜色.

三角形设置阶段会计算光栅化一个三角网格所需的信息.具体来说,上个阶段输出的都是三角网格顶点.但如果要得到整个三角网格对像素覆盖的情况,我们就必须计算每条边上的像素坐标.
为了能够计算边界像素的坐标信息,我们就需要得到三角形边界的表达方式.这样一个计算三角形网格表示数据的过程就叫做三角形设置.它的输出是为了给下一步做准备.

三角形遍历

三角形遍历阶段会检查每个像素是否被一个三角网格所覆盖.
如果被覆盖的话,就生成一个片元
而这个找到哪些像素被三角网格覆盖的过程就是三角形遍历,这个阶段也被称为扫描变换.

三角形遍历会根据上一个阶段的计算结果来判断一个三角网格覆盖了哪些像素,并使用三角网格三个顶点的顶点信息对整个覆盖区域的像素进行插值.

这一步的输出就是得到一个片元序列.
需要注意的是,一个片元并不是真正意义上的像素,而是包含了很多状态的集合,这些状态用于计算每个像素的最终颜色
这些状态包括了(但不限于)它的屏幕坐标,深度信息,以及其他从几何阶段输出的顶点信息,如法线,纹理坐标等.

片元着色器

前面的光栅化操作并不会影响屏幕上每个像素的颜色值,而是会产生一系列的数据信息,来描述一个三角网格是怎样覆盖每个像素的.而片元就是负责存储这样一系列数据.
真正会对像素产生影响的是下一个阶段–逐片元操作

片元着色器的输入是上一个阶段对顶点信息插值得到的结果.
更具体来说,是根据那些从顶点着色器中输出的数据差值得到的.
它的输出是一个或多个颜色值.

这一阶段可以完成很多重要的渲染技术,其中最重要的技术之一是纹理采样.
为了在片元着色器中进行纹理采样,我们通常会在顶点着色器阶段输出每个顶点对应的纹理坐标
然后经过光栅化阶段对三角形网格的三个顶点对应的纹理坐标进行插值后,就可以得到其覆盖片元的纹理坐标了.

片元着色器的局限在于,它仅可影响单个片元.
也就是说,在执行片元着色器时,它不可以将自己的任何结果发送给它的邻居们.
有一个情况例外,就是片元着色器可以访问到导数信息(扩展阅读)(smjb)

逐片元操作

也被称为输出合并阶段
这一阶段的几个重要任务:

  • 决定每个片元的可见性.
    这涉及很多测试工作,如深度测试,模板测试等
  • 合并
    如果一个片元通过了所以测试,就需要把这个片元的颜色值和已经存储在颜色缓冲区中的颜色进行混合

逐片元操作是高度可配置的.即我们可以设置每一步的操作细节.