渲染过程 - 通常从是三维场景出发、生成一张二维图像,由CPU和GPU共同合作完成。且通常分为以下几个概念阶段:
应用阶段通常有开发者主导,由CPU实现,并且输出渲染所需的几何信息 - 渲染图元(Renderding primitives),其主要有3个任务:
用于决定绘制的图元是什么、在哪里绘制、如何绘制等。
主要任务是决定每个渲染图元中那些像素应该被绘制在屏幕上。
渲染流程的起点是应用阶段,应用阶段大致分为三步:
经历过Draw Call后,GPU会根据渲染状态(材质、纹理、着色器等)和所有的图元(输入的顶点数据)来进行计算,最终输出成屏幕上的像素。
当GPU从CPU哪里得到Draw Call(渲染命令)后,就会进行一系列的操作,最终把图元渲染到屏幕上。
几何阶段和光栅化阶段的实现载体是GPU,其中又可以分为若干小的阶段,由GPU实现,每个阶段提供了可编程或可配置性。
顶点着色器(Vertex Shader)是流水线的第一个阶段,输入来自CPU。顶点着色器的处理单元是顶点,每个顶点都会调用一次顶点着色器。
其主要工作有:坐标变换和逐顶点光照,以及输出后续阶段所需的数据。
坐标变换就是对顶点的坐标进行某种变换(矩阵),也可以在这一步改变顶点的位置。其中最基本也是必须完成的一个工作是,把顶点坐标从模型空间转换到齐次裁剪坐标空间。
// 将顶点坐标转换到齐次裁剪坐标系下,再通过透视法
// 得到归一化的设备坐标(NDC normalized device coordinate)
o.pos = mul(UNITY_MATRIX_MVP, v.position);
一个图元与摄像机视野的关系有:
完全在视野内的图元会继续传递给下一个阶段,完全不在视野内的就不会被继续传递,而部分在视野内的图元则需要进行裁剪处理。裁剪过程会使用一些新顶点代替旧顶点。
屏幕映射(Screen Mapping)的任务是把三维坐标系下的坐标,转换到屏幕坐标系(Screen Coordinates)下。
此外,屏幕坐标系和z坐标一起构成了窗口坐标系(Windows Coordinate)。
几何阶段结束所输出的信息是屏幕坐标系下的顶点位置以及和他们相关的额外信息,如:深度值(z坐标)、法线方向、视角方向。
三角形遍历(Triangle Traversal)阶段将检查每个像素是否被一个三角网格所覆盖,如果覆盖就会生成一个片元(fragment),这样一个过程就是三角形遍历。
遍历后还会对覆盖区域的像素进行插值。输出结果是一个片元序列,其是包含了很多状态的集合,用于计算最终颜色(屏幕坐标、深度信息、顶点信息、法线、纹理等)。
片元着色器是重要的可编程阶段。前面阶段产出的片元用于存储一系列的信息。真正对像素产生影响的是下一个阶段 - 逐片元操作。
片元着色器的输入是插值后得到的,而输出是一个或多个颜色。
逐片元操作(Per-Fragment Operations)步骤的主要目的是合并,其用于:
模型图元经过各种计算和测试后,就会显示在屏幕上。为了避免看到正在光栅化的图元,GPU会使用双重缓冲(Double Buffering)策略。对场景的渲染时在幕后发生的,在后置缓冲(Back Buffer)中。一旦被渲染到后置缓冲中,GPU就会交换后置缓冲区与前置缓冲区(Front Buffer),而前置缓冲区是之前显示在屏幕上的图像。