📌
Foundations of 3D CG
  • 前言
  • I 基础入门
    • 第一章 简介
    • 第二章 线性
    • 第三章 仿射
    • 第四章 坐标系相关性(Respect)
    • 第五章 图形学中的坐标系
    • (WIP) 第六章 Hello World 3D
  • II 旋转与插值
    • 第七章 四元数(有点技术性)
    • (WIP) 第八章 球形:轨迹与弧
    • (WIP) 第九章 平滑插值
  • III 相机与光栅化
    • 第十章 投影
    • 第十一章 深度
    • 第十二章 从顶点到像素
    • 第十三章 变化变量
  • IV 像素及其相关内容
    • 第十四章 材质
    • 第十五章 纹理映射
    • 第十六章 采样
    • 第十七章 重建
    • 第十八章 重采样
  • V 高级话题
    • 第十九章 色彩
    • 第二十章 什么是光线追踪
    • 第二十一章 光(偏技术)
    • 第二十二章 几何建模:基础简介
    • 第二十三章 动画:甚至不能称之为简介
  • 附录
    • A Hello World 2D
    • B 仿射函数
Powered by GitBook
On this page
  • 11.1 可见性(visibility)
  • 11.2 基础数学模型

Was this helpful?

  1. III 相机与光栅化

第十一章 深度

Previous第十章 投影Next第十二章 从顶点到像素

Last updated 2 years ago

Was this helpful?

11.1 可见性(visibility)

在物理世界中,如果物体 A 位于物体 B 的前方,则来自物体 B 方向的光,会在到达摄影机前被物体 A 挡住,因而不会出现在画面中(例如,图10.2中的蓝色六边形)。在计算机图形学中,我们需要以计算的方式对其建模。

对于确保只有对摄影机可见的面(surface)出现在渲染画面(image)中,有很多实现方式。其中一种是,将三角面根据它们在摄影机方向的深度进行排序,再由后至前绘制它们。这一思想在于最前面的三角面会重新绘制并覆盖在其后方的三角面上,从而得到正确的渲染画面。这一方法称作画家方式(painter's approach)的思路,它存在一些难以处理的点。例如,一个场景中也许包含有相互穿插的三角面。它也许还会包含图 11.1 中可见性循环(visibility cycles)这样的穿插三角面的情况。

另一种广泛使用的方式,我们将会在第 20 章中讨论,即光线追踪(ray casting)。这个方式,是对每一个像素,显式的计算沿着该像素方向的视线与场景的交点。使用距离最近的交点来计算该像素的颜色。

可见性计算也可以用于加速渲染过程。如果我们知道一个物体会被挡住,从一开始我们就不用去渲染它。这可以使用在诸如室内场景中,我们通常不会看到房间外很远的东西。在这种情境下,我们可以使用保守可见性检测(conservative visibility test);这一检测可以很快告诉我们一个物体是可能,或者完全不可能具有可见性。如果一个物体可能是可见的,那么我们使用 z-buffer 继续渲染该物体。但如果该物体完全不可能可见,那么我们可以将整个绘制省略掉。

11.2 基础数学模型

在 OpenGL 中,我们使用 z-buffer 来计算可见性。为了使用 z-buffer,除了一个点 [xn,yn][x_n, y_n][xn​,yn​]坐标系向量之外,我们还需要一个深度值。为了实现这一点,对于视角坐标系下描述的每一个点,我们使用以下矩阵表达式来定义坐标系[xn,yn,zn]t[x_n, y_n, z_n]^t [xn​,yn​,zn​]t:

[xnwnynwnznwnwn]=[xcyczcwc]=[sx0−cx00sy−cy0000100−10][xeyeze1].(11.1)\left[ \begin{matrix} x_nw_n \\ y_nw_n \\ z_nw_n \\ w_n \end{matrix} \right] = \left[ \begin{matrix} x_c \\ y_c \\ z_c \\ w_c \end{matrix} \right] = \left[ \begin{matrix} s_x & 0 & -c_x & 0 \\ 0 & s_y & -c_y & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & -1 & 0 \end{matrix} \right] \left[ \begin{matrix} x_e \\ y_e \\ z_e \\ 1 \end{matrix} \right] . \tag{11.1}​xn​wn​yn​wn​zn​wn​wn​​​=​xc​yc​zc​wc​​​=​sx​000​0sy​00​−cx​−cy​0−1​0010​​​xe​ye​ze​1​​.(11.1)

同样,其原始输出称为裁剪坐标(clip coordinates),并且,同之前一样,为了得到xn x_nxn​​与yny_nyn​​的值,我们需要除以wnw_nwn​​的值。但是现在我们还有zn=−1zez_n=\frac{-1}{z_e}zn​=ze​−1​的值。我们计划使用znz_nzn​​的值在 z-buffer 中进行深度比较。

首先,我们先来验证公式(11.1)给出的znz_nzn​​值的确可以用于深度比较。给定两点p~1\tilde{p}^1p~​1​和p~2{\tilde{p}}^2p~​2在视角坐标系下的坐标[xe1,ye1,ze1,1]t[{x_e}^1, {y_e}^1, {z_e}^1, 1]^t [xe​1,ye​1,ze​1,1]t和[xe2,ye2,ze2,1]t[{x_e}^2, {y_e}^2, {z_e}^2, 1]^t[xe​2,ye​2,ze​2,1]t,假设它们均位于视点前方(即ze2<ze1{z_e}^2 < {z_e}^1ze​2<ze​1)。那么 −1ze2<−1ze1- \frac{1}{{z_e}^2} < - \frac{1}{{z_e}^1}−ze​21​<−ze​11​,意味着zn2<zn1{z_n}^2 < {z_n}^1zn​2<zn​1。

汇总在一起,我们现在可以将视角坐标系向归一化设备坐标系(NDC)转换的过程考虑为纯粹的 3D 几何变换。这一变换通常既非线性,也非仿射,而被称作三维投影变换(3D projective transformation)。

投影变换很有意思;例如,在上述的情形中,任何ze=0z_e=0ze​=0​的点都会导致除零的问题。就目前而言,对我们来说关于投影变换最重要的方面在于(随后会展开解释),它可以保留点与点之间的共线性和共面性(如图 11.2 和 11.3)。共线性意味着,如果三个或多个点位于一条直线上,变换后的点仍然会位于一条线上。

共面性的意义在于,我们知道对于在固定某个三角面上的固定点a,ba, ba,b 以及 ccc ,我们会有zn=axn+byn+cz_n = ax_n + by_n + czn​=axn​+byn​+c​。因此,在已知三角面上三个顶点时,通过 2D 平面图像上的线性插值,可以正确计算得到其中某点的znz_nzn​值。(附录 B 中有关于线性插值的内容)。

注意,尽管如此,投影变换不会保留距离。再次看看图 11.2 以及 11.3,我们可以看出,在二维平面上距离相等的像素,并不对应着视角空间下距离相等的几何点。同样,这些等距分布的像素,也不会对应归一化设备坐标系下等距的点。

由于距离上的失真,在屏幕空间下对zez_eze​​的线性插值会得到错误的结果。考虑图 11.4 所示的情况,有两个交叉的线段,分别为橘黄色与蓝色。其顶点的zez_eze​​值如图所示。两线段恰好在图像的正中间处交叉,因此在正确的图像中,上半部分应当为蓝色,而下半部分应当为橘黄色。如果我们对每个线段在图像空间中进行线性插值,

三个三角面构成了一个可见性循环。不可能将它们由后至前排序。