《Real-Time Rendering 3rd 提炼总结》简记与思考 1 - 图形渲染管线

1,217 阅读8分钟

图形渲染管线

图形渲染管线的三个阶段:

  1. 应用程序阶段 The Application Stage
  2. 几何阶段 The Geometry Stage
  3. 光栅化阶段 The Rasterizer Stage

image.png

应用阶段

应用阶段通过软件方式来实现,诸如碰撞检测、输入检测,动画等在该阶段实现。应用程序将摄像机位置、光照和模型的图元输出到几何阶段。

图元 (primitive) 由顶点 (vertex) 组成,可能是一个顶点、一条线段、一个三角形或者多边形,都可以成为图元。而片元(fragment)是图元经过光栅化后,被分割成像素大小的单位,与像素不同的是,片元还持有深度值、纹理坐标、法线等信息。片元在经过各种测试后,竞争上岗,才能成为真正显示在屏幕上的一个个只包含 RGBA 信息的像素。

几何阶段

几何阶段对多边形和顶点操作:

  1. 模型视点变换 Model & View Transform
  2. 顶点着色 Vertex Shading
  3. 投影 Projection
  4. 裁剪 Clipping
  5. 屏幕映射 Screen Mapping

image.png

几何阶段计算量非常高,在单光源情况下每个顶点大约需要100次的浮点运算。

模型视点变换

模型需要通过模型变换,将模型的坐标和法线变换到世界空间,所有的模型经过变换后都位于唯一的世界空间中。为了便于投影和剪裁,需要将摄像机变换到世界空间的原点,并且世界空间中的所有模型都应该和摄像机一起变换,这一变换称为视点变换,变换后的空间称为相机空间(观察空间)。

image.png

顶点着色

在该阶段的计算会作用于顶点(逐顶点),计算后的位置、法线和纹理颜色等可以传递到光栅化阶段,进行三角形插值操作。

顶点着色阶段的目的在于确定模型上顶点处材质的光照效果。

投影

投影变换会将视体变换到规范立方体 (Canonical View Volume) 范围内,主要有两种投影方法:

  1. 正交投影
  2. 透视投影

正交投影就是平移变换和缩放变换的组合,先将视体平移到相机空间原点,然后将长方体缩放为单位立方体。透视投影的过程是先将视体挤压成长方体,即正交投影的视体形状,之后再进行正交投影变换即可。

image.png

投影阶段将模型从三维投射到了二维

裁剪

投影变换后,图元相对于视体的位置情况有三种:

  1. 完全位于内部
  2. 完全位于外部
  3. 部分位于内部

完全位于外部的直接剔除,完全位于内部的直接下一阶段,部分位于内部的则需要裁剪。

裁剪阶段的目的,就是对部分位于视体内部的图元进行裁剪操作。

image.png

屏幕映射

在屏幕映射阶段,坐标依旧是三维的,但显示状态在经过投影阶段后已经成了二维。每个图元的 x 和 y 坐标变换到了屏幕坐标系中,屏幕坐标系连同 z 坐标一起称为窗口坐标系。

image.png

屏幕映射阶段的主要目的,是将之前步骤得到的坐标映射到对应的屏幕坐标系上。

光栅化阶段

光栅化阶段可以分为以下几个阶段:

  1. 三角形设定(Triangle Setup)阶段
  2. 三角形遍历(Triangle Traversal)阶段
  3. 像素着色(Pixel Shading)阶段
  4. 融合(Merging)阶段

image.png

给定经过变换和投影之后的顶点,颜色以及纹理坐标(均来自于几何阶段),给每个像素 (Pixel)正确配色,以便正确绘制整幅图像。这个过个过程叫光珊化(rasterization)或扫描变换(scan conversion)。

三角形设定

三角形设定阶段主要用来计算三角形表面的差异和三角形表面的其他相关数据。该数据主要用于扫描转换(scan conversion),以及由几何阶段处理的各种着色数据的插值操作所用。该过程在专门为其设计的硬件上执行。

三角形遍历

三角形遍历阶段要进行逐像素检查,判断像素的中心是否被三角形所覆盖以生成片段。而片段的属性则由三角形的顶点插值得到。

找到哪些采样点或像素在三角形中的过程通常叫三角形遍历(TriangleTraversal)或 扫描转换(scan conversion)。

像素着色

所有逐像素的着色计算都在像素着色阶段进行,使用插值得来的着色数据作为输入,输出结果为一种或多种将被传送到下一阶段的颜色信息。纹理贴图操作就是在这阶段进行的。

融合

  1. 颜色缓冲:是一个和像素数一样大小的数组,存储每个像素的片元颜色
  2. 深度测试:有一个深度缓冲,其大小与颜色缓冲区相同,光栅化时计算每个像素绘制的图元的 Z 值,与原先的进行比较,
  3. 透明度测试:在深度测试前检查片段的alpha 值
  4. 模板缓冲:记录图元位置的缓存,可以利用这个缓冲,决定是否绘制,可以制作mask等效果
  5. 帧缓冲:通常包含一个系统所具有的所有缓冲器,但有时也可以认为是颜色缓冲器和 z 缓冲器的组合。
  6. 累计缓冲:用于景深、反走样、软阴影和运动模糊等效果,用一组操作符对图像进行累积,是对帧缓冲器 的补充。

思考

裁剪剔除的具体操作是什么?

以下内容引用自知乎用户 Clawko 的文章

  1. 从零开始的软渲染器(2.5)- 再谈裁剪与剔除 - 知乎 (zhihu.com)
  2. 一篇文章彻底弄懂齐次裁剪 - 知乎 (zhihu.com)

传统的裁剪剔除一共有三次:

  1. 视锥剔除:通过包围盒将物体包起来,与视锥体做碰撞检测,直接提出完全不可见物体。
  2. 视口剔除:在裁剪空间做透视除法之前进行,物体如果在摄像机位置会使透视除法除零。对视口外的直接丢弃,部分位于视口内的进行裁剪并生成新的多边形。这一步消耗性能,GPU不适合做判断条件多的工作。现代GPU通常使用一个比视口打很多倍以上的虚拟视口进行裁剪。对于超出一点点的建议直接绘制出来,不会浪费太多性能。
  3. 背面剔除:在顶点着色器和片段着色器之间运行,剔除背向面。
  4. 遮挡剔除:主要用于静态物体多的场景,该文不做赘述。

如何理解齐次坐标与透视除法?

以下内容引用自简书用户StanGame的文章

  1. 写给大家看的“透视除法” —— 齐次坐标和投影 - 简书 (jianshu.com)

齐次坐标的 ww 分量的意义是视点到某个平面的垂直距离。而 ww 就是摄像机到视体每个平面的垂直距离。如果我们移动摄像机前进,即 ww 变小,则摄像机的视体投影到平面上的物体被缩小了(视体和摄像机一起移动)。

image.png 在图形学中,只有 w=1 w = 1 才是 “正确的”。而在数学中,齐次坐标没有“不正确”的说法。我们使齐次坐标的 ww 分量保持为 11,仅仅是计算机图形学中的投影变换。由于透视投影变换会使变换后的点的齐次坐标 w=zw = z ,因此需要对变换后的点坐标除以 zz 。同时这也会导致位于视点平面上的物体点坐标除的是 00 ,这显然不行。

如下图所示,两个三角形面,其中一个三角形其中一个顶点位于视点后方,设点 Pback=(x,y,zb,1)P_{back} = (x,y,z_b,1),再设一在视体中点 Pfront=(x,y,zf,1)P_{front} = (x,y,z_f,1),显然 zb>0,zf<0z_b>0,z_f<0

对两点做透视变换后,则点 Pback=(x,y,zb,zb)P_{back} = (x',y',z_b',-z_b),点 Pfront=(x,y,zf,zf)P_{front}=(x',y',z_f',-z_f),且由于投影变换到NDC空间时会变换左右手坐标系,故此时 zb<0,zf>0z_b'<0,z_f'>0

如果不进行裁剪就对齐次坐标做透视除法,使点 Pback,PfrontP_{back},P_{front} 点除以各自的 ww 分量后可得点 Pback=(x,y,zbzb,1)P_{back} = (x',y',\frac{z_b'}{-z_b},1),点 Pfront=(x,y,zfzf,1)P_{front}=(x',y',\frac{z_f'}{-z_f},1),其中 zb<0,zb<0,zf>0,zf>0z_b'<0,-z_b<0,z_f'>0, -z_f>0

故做透视除法后,点 PbackP_{back}zzzbzb>0\frac{z_b'}{-z_b}>0,符合我们的预期,但透视除法后点 PfrontP_{front}zzzfzf>0\frac{z_f'}{-z_f}>0,也为正值,但我们预期该点应该在 z-z 轴上的。

因此实际操作中,我们需要先将视点平面背后的点剔除掉,再进行透视除法。并且对于视点平面上的点,由于z=0z=0,会导致该点的 ww 分量也为 00,即透视除法时会出现除零的错误,因此也要剔除。

image.png