# 图形渲染管线


## ***引言***

*本博客介绍了实时图形学中的核心组件，它被称为“图形渲染管线（graphics rendering pipeline）”，也被简称为“管线”。*

*渲染管线的核心功能就是利用给定的虚拟相机、三维物体、光源等信息，来生成或者渲染（render）一张二维图像。因此， 渲染管线是实时渲染中的底层工具*

## ***渲染管线的架构***

*一种粗略的划分方法是将渲染管线分为四个阶段——应用阶段（application）、几何处理阶段（geometry processing）、光栅化阶段（rasterization）和像素处理阶段（pixel processing）*

![渲染管线的架构](https://raw.githubusercontent.com/vlicecream/cloudImage/main/image-20250909232828388.png)

*渲染速度可以用每秒帧数（FPS）来进行表示，即每秒显示的帧数；也可以用赫兹 （Hz）来进行表示，这个单位代表了 ，即更新的频率。*

1. *应用阶段（application）是由应用程序进行驱动的，它在软件中进行实现，运行在通用 CPU 上。这些 CPU 一般都具有多个核心，可以并行处理多个线程 （thread）的任务，这使得 CPU 可以高效执行由应用阶段所负责的各种任务，一般 CPU 会负责碰撞检测，全局加速算法，动画，物理模拟等任务，具体会执行哪些任 务取决于应用程序的类型。*
2. *下一个主要阶段是几何处理阶段（geometry processing），它负责处理变换（transform），投影（projection）以及其他所有和 几何处理相关的任务。这个阶段需要计算哪些物体会被绘制，应该如何进行绘制，以 及应当在哪里绘制等问题。几何阶段通常运行在硬件处理单元（GPU）上，它包含一 系列的可编程单元和固定操作硬件。*
3. *光栅化阶段（rasterization）通常会将构成一个 三角形的三个顶点作为输入，找到所有位于三角形内部的像素，并将其转发到下一个 阶段中。*
4. *最后一个阶段是像素处理阶段（pixel processing），对于每个像素而言， 都会执行一个程序来决定它的颜色；并执行深度测试，来判断这个像素是否可见；这 里还可以执行一些逐像素的操作，例如将新计算的颜色和之前的颜色进行混合。*

*光栅化阶段和像素处理阶段同样完全运行在 GPU 上*

## ***应用阶段***

*由于应用阶段通常都运行在 CPU 上， 因此开发者可以完全控制在应用阶段发生的事情*

*有一些应用阶段中的任务也可以让 GPU 来进行执行，即通过使用一个叫做计算着色器（compute shader）的独立模式，该模式会将 GPU 视为一个高度并行 的通用处理器，而忽略其专门用于图形渲染的特殊功能*

*在应用阶段的最后，需要进行渲染的几何物体会被输入到几何处理阶段中，这些几何物体被称作为渲染图元（rendering primitive），即点、线和三角形。*

*碰撞检测（collision detection）通常会在这个阶段中实现。当检测到两个物体之间的碰撞之后，会产生相应的响应，并返回给碰撞物体，同时也返回给力反馈设备（如果有的话）。*

*应用阶段同样也是处理其他来源输入的地方，例如键盘、鼠标或者头戴式显示器等，会根据不同的输入，从而采取不同的操作。此外，一些加速算法例如特殊的剔除算法等，以及渲染管线剩余部分无法处理的一切问题，都会在应用阶段中完成。*

## ***几何处理阶段***

*运行在 GPU 上的几何处理阶段会负责大部分的逐三角形（per-triangle）和逐顶点 （per-vertex）操作。将几何处理阶段再细分下去，可以划分为以下几个功能性阶段：顶点着色（vertex shading）、投影（projection）、裁剪（clipping）和屏幕映射（screen mapping），如图 2.3 所示.*

![几何处理阶段](https://raw.githubusercontent.com/vlicecream/cloudImage/main/image-20250909234033002.png)

### ***顶点着色***

*顶点着色（vertex shading）的任务主要有两个*

1. *一个是计算顶点的位置*
2. *另一个是计算那些开发人员想要作为顶点数据进行输出的任何参数，例如法线（normal）和纹理坐标（texture coordinate）等*

*顶点着色器如今是一个更加通用的单元，它负责计算并设置与每个顶点都相关的数据。例如顶点着色器可以用来计算物体的动画。*

*首先我们描述一下顶点位置是如何被计算出来的，它需要一组顶点坐标来作为输入。 在物体最终进入屏幕的过程中，它需要在不同的空间（space）或者坐标系 （coordinate system）下，进行若干次变换*

*接下来，我们将描述顶点着色的第二类输出。为了创建一个真实的场景，仅仅是渲染物体的位置和形状是不够的，我们还需要对物体的外观信息进行建模，包括物体的材质（material）信息以及光源照射在物体表面上的效果。从最简单的颜色描述到基于物理的详细描述，材质和光源可以通过很多方式进行建模。*

*确定光照作用于材质上所产生的效果，这个操作被称为着色*

*顶点着色的结果（可能是颜色、向量、纹理坐标或者其他类型的着色数据）会被发送到光栅化阶段中进行插值，并在像素处理阶段中用于计算表面的着色。*

*作为顶点着色的一部分，渲染系统还会进行投影操作和裁剪操作，这两个操作会将整个可视空间变换为一个标准立方体，这个标准立方体被称为规范可视空间（canonical view volume）*

*首先会进行投影操作，这是在 GPU 上的顶点着色器中完成；*

*有两种常见的投影方法， 一种是正交投影（orthographic），也可以叫做平行投影（parallel）；另一种是透视投影（perspective）*

### ***可选的顶点管理***

*每个渲染管线中，都会有刚才所描述的顶点处理阶段，当完成顶点处理之后，还有几个可以在 GPU 上执行的可选操作，它们的执行顺序如下：曲面细分 （tessellation）、几何着色（geometry shading）和流式输出（stream out）。*

#### ***曲面细分***

*想象有一个用三角形表示的曲面小球，我们从远看看的就是一个小球，但是离近看就会发现三角形，所以曲面细分就可以帮我们为一个曲面生成数量合适的三角形，这样就可以做到性能与质量兼顾*

*曲面细分阶段本身也包含了一系列子阶段——壳着色器 （hull shader）、曲面细分器（tessellator）和域着色器（domain shader），它们可以将当前的顶点集合（通常）转换为更大的顶点集合，从而创建出更多的三角形。*

#### ***几何着色器***

*这个着色器出现的比曲面细分着色器更早，因此在 GPU 上也更加常见。它和曲面细分着色器的相似点在于，它也将各种类型的图元作为输入，然后生成新的顶点。*

*这是一个较为简单的阶段，因为它能够创建的范围是有限的，能够输出的图元则更加有限*

*几何着色器有好几种用途， 其中最流行的一种就是用来生成粒子。想象我们正在模拟一个烟花爆炸的过程，每颗火花都可以表示为一个点，即一个简单的顶点。*

#### ***流式输出***

*这阶段我们可以把GPU作为一个几何引擎*

*说人话就是把数据放在缓冲区，而不是直接输入到渲染管线后面流程并且直接输出到屏幕*

*这个阶段通常会用于粒子模拟，例如我们刚才所举的烟花案例*

### ***裁剪***

*我们只需要可视空间里面的图元，如果在可视空间外，则可以不用显示，如果一个三角形有一部分在可视空间外，就会直接裁剪，抛弃可视空间外的顶点，生成新的顶点*

*我们使用投影矩阵来将可视空间变成一个立方体，这意味着所有的图元都需要被这个标准立方体所裁剪。使用观察变换和投影变换可以保证裁剪的一致性*

*这里我们会采用投影变换的四维齐次坐标去完成这个剪切操作*

### ***屏幕映射***

*只有位于可视空间的图元我们才会传递到屏幕映射阶段。当这些图元进入到这个阶段的时候，坐标还是三维的，所以需要映射到屏幕的二维坐标*

## ***光栅化阶段***

*所有在前一阶段中被保留下来的图元，在这个阶段中都会进行光栅化，即找到所有位于图元内部的像素，然后将其发送管线的像素处理阶段*

## ***像素处理阶段***

*这一步的目标是计算出每个可见图元所覆盖像素的颜色值*

## ***总结***

*本章节介绍的就是面向实时渲染程序的API以及图形硬件发展而来的结果。*

*离线渲染中也有一套渲染管线，但是经历了与实时渲染完全不同的有演化路径*

