图形渲染管线
《Real Time Rendering 3rd》读书笔记
1 图像渲染管线架构概述 Architecture
渲染管线的主要功能就是决定在给定虚拟相机、三维物体、光源、照明模式,以及纹理等诸多条件的情况下,生成或绘制一幅二维图像的过程。
下图展示了使用渲染管线步骤。渲染出的图像的位置、形状是由它们的几何形状,环境特性,摄像机位置决定的。而物体的外观由材质特性,光源,纹理和着色模型确定。

相机放在棱椎的顶端(四条线段的交汇点),只有可视体内部的图元会被渲染。
在概念上可以将图形渲染管线分为三个阶段:
- 应用程序阶段(The Application Stage)
- 几何阶段(The Geometry Stage)
- 光栅化阶段(The Rasterizer Stage)
2 应用程序阶段 The Application Stage
应用程序阶段的主要任务:将需要在屏幕上显示出来绘制的几何体(也就是绘制图元,如点、线、矩形等)输入到绘制管线的下一个阶段-几何阶段。
渲染流水线的起点是CPU,及应用阶段。大致分为三个阶段:
- 把数据加载到显存中
- 设置渲染状态
- 调用DrawCall
那什么是设置渲染状态?定义场景中的模型是怎样被渲染的。DrawCall,就是一个调用命令,CPU通过调用DrawCall来告诉GPU开始进行一个渲染过程。DrawCall指向本次需要渲染的图元列表。
3 几何阶段 The Geometry Stage
几何阶段主要负责大部分多边形操作和顶点操作。可以将这个阶段进一步划分成如下几个功能阶段:
- 模型视图变换Model & View Transform
- 顶点着色Vertex Shading
- 投影 Projection
- 裁剪 Clipping
- 屏幕映射Screen Mapping

3.1 模型和视图变换 Model and View Transform

【总结】模型和视图变换阶段分为模型变换和视图变换。模型变换的目的是将模型从模型空间转换到齐次裁剪空间,而视图变换的目的是将摄像机放置于坐标原点,方便后续步骤的操作。
3.2 顶点着色 Vertex Shading
计算材质上的光照效果的这种操作被称为着色(shading),可以在每个顶点处存储各种材质数据,诸如点的位置,法线,颜色或计算着色方程所需的任何其它数字信息。顶点着色的结果(颜色,纹理坐标或任何其他种类的着色数据)计算完成后,会被发送到光栅化阶段以进行插值操作。着色计算是在世界空间中进行的。
【总结】顶点着色阶段的目的在于计算模型上顶点处材质的光照效果。
3.3 投影 Projection
在光照处理之后,渲染系统就开始进行投影操作,即将视体变换到一个对角顶点分别是(-1,-1,-1)和(1,1,1)单位立方体(unit cube)内,这个单位立方体通常也被称为规范立方体(Canonical View Volume,CVV)。
目前,主要有两种投影方法,即:
- 正交投影(orthographic projection)
- 透视投影(perspective projection)
如下图所示。

左边为正交投影,右边为透视投影
两种投影方式的主要异同点:
- 正交投影。正交投影的可视体通常是一个矩形,正交投影可以把这个视体变换为单位立方体。
- 透视投影。相比之下,透视投影比正交投影复杂一些。在这种投影中,越远离摄像机的物体,它在投影后看起来越小。透视投影的变换其实就是模拟人类感知物体的方式。
经过这些矩阵变换后,就将模型从三维空间投影到了二维的空间中。
【总结】投影阶段就是将模型从三维空间投射到了二维的空间中的过程。
3.4 裁剪 Clipping
只有当图元完全或部分存在于视体(也就是上文的规范立方体,CVV)内部的时候,才需要将其发送到光栅化阶段,这个阶段可以把这些图元在屏幕上绘制出来。
一个图元相对视体内部的位置,分为三种情况:完全位于内部、完全位于外部、部分位于内部。所以就要分情况进行处理:
- 当图元完全位于视体内部,那么它可以直接进行下一个阶段。
- 当图元完全位于视体外部,不会进入下一个阶段,可直接丢弃,因为它们无需进行渲染。
- 当图元部分位于视体内部,则需要对那些部分位于视体内的图元进行裁剪处理。
对部分位于视体内部的图元进行裁剪操作,这就是裁剪过程存在的意义。
裁剪过程如图。

【总结】裁剪阶段的目的,就是对部分位于视体内部的图元进行裁剪操作。
3.5 屏幕映射 Screen Mapping
进入到这个阶段时,每个图元的x和y坐标变换到了屏幕坐标系中,称为窗口坐标系。

【总结】屏幕映射阶段的主要目的,就是将之前步骤得到的坐标映射到对应的屏幕坐标系上。
4 光栅化阶段 The Rasterizer Stage
给定经过变换和投影之后的顶点,颜色以及纹理坐标,给每个像素(Pixel)正确配色,以便正确绘制整幅图像。这个过个过程叫光栅化(rasterization),即从二维顶点所处的屏幕空间到屏幕上的像素的转换。
与几何阶段相似,该阶段细分为几个功能阶段:
- 三角形设定(Triangle Setup)阶段
- 三角形遍历(Triangle Traversal)阶段
- 像素着色(Pixel Shading)阶段
- 融合(Merging)阶段
如图所示:

4.1 三角形设置 Triangle Setup
上一阶段输出的是三角形网格的顶点,即我们得到的是三角形每条边的两个点。但如果要得到整个三角形网格对像素的覆盖情况,就必须计算每条边上的像素坐标。为了能够计算边界像素的坐标信息,就需要得到三角形边界的表示方式。这样一个计算三角形网格表示数据的过程叫三角形设置。
4.2 三角形遍历 Triangle Traversal
据上一阶段的计算结果来判断一个三角形网格覆盖了哪些像素,被覆盖的像素,就会对应生成一个片元(fragment),并使用三角网格的3个顶点的顶点信息对整个覆盖区域的像素进行插值,得到片元中的状态。这一步输出的就是一个片元序列。
需要注意的是,一个片元并不是真正意义上的像素,而是包含了很多状态的集合,这些状态用于计算每个像素的最终颜色。包含了屏幕坐标,深度信息,以及从几何阶段输出的顶点信息,例如法线、纹理坐标等。
4.3 像素着色 Pixel Shading
所有逐像素的着色计算都在像素着色阶段进行,使用插值得来的着色数据作为输入,输出结果为一种或多种将被传送到下一阶段的颜色信息。纹理贴图操作就是在这阶段进行的。
【总结】像素着色阶段的主要目的是计算所有需逐像素操作的过程。
4.4 融合 Merging
- 决定每个片元的可见性。例如模板测试、深度测试等。
- 如果一个片元通过了所有的测试,就需要把这个片元的颜色值和已经存储在颜色缓冲区中的颜色进行混合。
模板测试(Stencil Test):
如果开启了模板测试,GPU会首先读取(使用读取掩码)模板缓冲区中该片元位置的模版缓冲值(Stencil buffer),然后将该值和读取到的参考值(Reference buffer)进行比较,比较函数由开发者指定,例如小于时舍弃该片元等。模板测试通常用于限制渲染的区域。还有些高级用法,渲染阴影、轮廓渲染等。
深度测试(Depth Test):
如果开启了深度测试,GPU将会把该片元的深度值与已经存在于深度缓冲区的深度值进行比较。比较函数由开发者指定。通常比较函数是小于等于的关系,才会让它通过测试,即如果这个片元的深度值大于等于当前缓冲区的值,就会舍弃它。因为我们只想显示出离摄像机最近的物体,那些被其他物体遮挡的就不需要出现在屏幕上。如果通过了测试,开发者可以通过开启/关闭深度写入,指定是否要用这个片元的深度值覆盖原有的深度值。
混合(Blend):
对于不透明物体,关闭混合操作,这样片元着色器计算得到的颜色值就可以直接覆盖掉已经存在于颜色缓冲区的颜色值。对于半透明物体,需要使用混合操作,让物体看起来是透明的。开启混合功能,GPU会把片元着色器计算得到的颜色值和已经存在于颜色缓冲区的颜色值,进行混合。
帧缓冲区:
默认情况下OpenGL使用帧缓冲区作为渲染的目的地。颜色缓冲区是必不可少的,其他缓冲区可以存在可以不存在。
帧缓冲区(FrameBuffer)包括下面三个缓冲区:
- 颜色缓冲区(ColorBuffer)
- 深度缓冲区(DepthBuffer)
- 模板缓冲区(StencilBuffer)
双重缓冲策略:
最后,为了避免我们看到正在进行光栅化的图元,GPU会使用双重缓冲的策略。对场景的渲染是放在幕后的,当场景被渲染到后置缓冲中,GPU就会交换后置缓冲区和前置缓冲区中的内容,而前置缓冲区是之前显示在屏幕上的图像。由此,保证我们看到的图像总是连续的。
本文经作者同意,转自知乎@鹅厂程序小哥(https://www.zhihu.com/people/tencentboy),原文链接(https://zhuanlan.zhihu.com/p/343073329)
本文详细介绍了图形渲染管线的各个阶段,包括应用程序阶段、几何阶段和光栅化阶段。在应用程序阶段,CPU通过设置渲染状态和调用DrawCall将数据输入管线。几何阶段涉及模型视图变换、顶点着色、投影、裁剪等步骤,将三维模型转换为二维图像。光栅化阶段则包括三角形设置、遍历、像素着色和融合,最终决定每个像素的颜色并完成图像的绘制。每个阶段都对渲染效果起着关键作用。
2673

被折叠的 条评论
为什么被折叠?



