可见表面检测
当我们查看包含非透明物体和表面的图片时,我们无法从视野中看到那些位于靠近眼睛的物体后面的物体。我们必须移除这些隐藏的表面才能获得逼真的屏幕图像。识别和移除这些表面称为隐藏表面问题。
有两种方法可以消除隐藏表面问题:对象空间方法和图像空间方法。对象空间方法在物理坐标系中实现,而图像空间方法在屏幕坐标系中实现。
当我们想在 2D 屏幕上显示 3D 物体时,我们需要识别从所选观看位置可见的屏幕部分。
深度缓冲区(Z 缓冲区)方法
此方法由 Cutmull 开发。它是一种图像空间方法。基本思想是测试每个表面的 Z 深度以确定最近(可见)的表面。
在此方法中,每个表面在表面上一次一个像素位置单独处理。比较像素的深度值,最近(最小 z)的表面确定要在帧缓冲区中显示的颜色。
它非常有效地应用于多边形表面。表面可以按任何顺序处理。为了从较远的多边形覆盖较近的多边形,使用了两个名为 帧缓冲区 和 深度缓冲区 的缓冲区。
深度缓冲区用于存储 (x, y) 位置的深度值,因为表面被处理(0 ≤ 深度 ≤ 1)。
帧缓冲区用于存储每个位置(x, y)的颜色值的强度值。
z 坐标通常归一化为范围 [0, 1]。 z 坐标的 0 值表示后裁剪窗格,z 坐标的 1 值表示前裁剪窗格。

算法
步骤 1 − 设置缓冲区值 −
深度缓冲区 (x, y) = 0
帧缓冲区 (x, y) = 背景颜色
步骤 2 − 处理每个多边形(一次一个)
对于多边形的每个投影(x,y)像素位置,计算深度z。
如果Z> 深度缓冲区(x,y)
计算表面颜色,
设置深度缓冲区(x,y)= z,
帧缓冲区(x,y)=表面颜色(x,y)
优点
- 易于实现。
- 如果在硬件中实现,它可以减少速度问题。
- 它一次处理一个对象。
缺点
- 需要大量内存。
- 这是一个耗时的过程。
扫描线方法
这是一种识别可见表面的图像空间方法。此方法仅具有单个扫描线的深度信息。为了获取一条扫描线的深度值,我们必须在处理下一条扫描线之前同时分组和处理与给定扫描线相交的所有多边形。为此维护了两个重要的表,边表和多边形表。
边表 − 它包含场景中每条线的坐标端点、每条线的反斜率以及指向多边形表以将边连接到表面的指针。
多边形表 −它包含平面系数、表面材料属性、其他表面数据,并且可能是指向边缘表的指针。

为了便于搜索与给定扫描线相交的表面,形成了一个边缘的活动列表。活动列表仅存储那些按 x 递增顺序与扫描线相交的边缘。还为每个表面设置了一个标志,以指示扫描线上的位置是在表面内还是表面外。
每条扫描线上的像素位置从左到右进行处理。在与表面的左侧交叉处,表面标志打开,在右侧,标志关闭。仅当多个表面的标志在某个扫描线位置打开时,才需要执行深度计算。
区域细分方法
区域细分方法的优势在于,它可以定位那些代表单个表面一部分的视图区域。将整个视图区域划分为越来越小的矩形,直到每个小区域都是单个可见表面的一部分的投影,或者根本没有表面。
继续此过程,直到细分区域很容易被分析为属于单个表面,或者缩小到单个像素的大小。一个简单的方法是在每个步骤中将区域连续划分为四个相等的部分。表面与指定区域边界可能有四种关系。
周围表面 − 完全包围该区域的表面。
重叠表面 −部分位于区域内、部分位于区域外的物体。
内表面 − 完全位于区域内。
外表面 − 完全位于区域外的物体。

确定区域内表面可见性的测试可以用这四种分类来表述。如果以下条件之一为真,则不需要对指定区域进行进一步细分 −
- 所有表面都是相对于区域的外部表面。
- 只有一个内部、重叠或周围的表面位于区域中。
- 周围的表面遮挡了区域边界内的所有其他表面。
背面检测
一种用于识别多面体背面的快速而简单的对象空间方法基于"内外"测试。如果内部点沿着表面的视线,则点 (x, y, z) 位于具有平面参数 A、B、C 和 D 的多边形表面"内部",该多边形一定是背面(我们位于该面内,从我们的观察位置看不到它的正面)。
我们可以通过考虑多边形表面的法线向量 N 来简化此测试,该法线向量具有笛卡尔分量 (A、B、C)。
一般而言,如果 V 是从眼睛(或"相机")位置观察方向的向量,则如果
V.N > 0
此外,如果将对象描述转换为投影坐标,并且您的观察方向与观察 z 轴平行,则 −
V = (0, 0, Vz) 和 V.N = VZC
因此,我们只需要考虑法线向量 N 的分量 C 的符号。
在右手观察系统中,观察方向沿负 $Z_{V}$ 轴,如果 C < 0,则多边形为背面。此外,我们看不到任何法线具有 z 分量 C = 0 的面,因为您的观察方向朝向该多边形。因此,一般来说,如果多边形的法线向量具有 z 分量值,我们可以将其标记为背面 −
C <= 0

类似的方法可用于采用左手观察系统的包中。在这些包中,平面参数 A、B、C 和 D 可以根据顺时针方向指定的多边形顶点坐标计算出来(与右手系统中使用的逆时针方向不同)。
此外,背面具有指向观察位置的法向量,当观察方向沿正 $Z_{v}$ 轴时,由 C >= 0 标识。通过检查定义对象的不同平面的参数 C,我们可以立即识别所有背面。

A 缓冲区方法
A 缓冲区方法是深度缓冲区方法的扩展。 A 缓冲区方法是 Lucas 电影工作室为渲染系统 Renders Everything You Ever Saw (REYES) 开发的一种可见性检测方法。
A 缓冲区扩展了深度缓冲区方法以允许透明度。A 缓冲区中的关键数据结构是累积缓冲区。

A 缓冲区中的每个位置都有两个字段 −
深度字段 − 它存储正实数或负实数
强度字段 −它存储表面强度信息或指针值

如果深度 >= 0,则存储在该位置的数字是与相应像素区域重叠的单个表面的深度。然后,强度字段存储该点处表面颜色的 RGB 分量和像素覆盖率百分比。
如果深度 < 0,则表示多个表面对像素强度的贡献。然后,强度字段存储指向表面数据链接列表的指针。A 缓冲区中的表面缓冲区包括 −
- RGB 强度分量
- 不透明度参数
- 深度
- 区域覆盖百分比
- 表面标识符
该算法的执行方式与深度缓冲区算法相同。深度和不透明度值用于确定像素的最终颜色。
深度排序方法
深度排序方法同时使用图像空间和对象空间操作。深度排序方法执行两个基本功能 −
首先,按深度递减的顺序对表面进行排序。
其次,按顺序对表面进行扫描转换,从深度最大的表面开始。
多边形表面的扫描转换在图像空间中执行。这种解决隐藏面问题的方法通常被称为画家算法。下图显示了深度排序的效果 −

该算法首先按深度排序。例如,多边形的初始"深度"估计可以取为多边形任何顶点最接近的 z 值。
让我们取列表末尾的多边形 P。考虑所有 z 范围与 P 重叠的多边形 Q。在绘制 P 之前,我们进行以下测试。如果以下任何测试为正,那么我们可以假设 P 可以在 Q 之前绘制。
- x 范围不重叠吗?
- y 范围不重叠吗?
- 从视点来看,P 是否完全位于 Q 平面的另一侧?
- Q 是否完全位于 P 平面的同一侧(与视点相同)?
- 多边形的投影不重叠吗?
如果所有测试都失败,则我们使用另一个平面来分割 P 或 Q。新切割的多边形将插入深度顺序,然后继续该过程。从理论上讲,这种分区可以生成 O(n2) 个单独的多边形,但实际上,多边形的数量要少得多。
二叉空间分区 (BSP) 树
二叉空间分区用于计算可见性。要构建 BSP 树,应该从多边形开始并标记所有边。每次只处理一条边,延伸每条边,使平面一分为二。将第一条边作为根放入树中。根据后续边是在内部还是外部来添加它们。跨越树中已有边的延伸的边被分成两条,并将两条都添加到树中。

从上图中,首先将 A 作为根。
列出图 (a) 中的所有节点。
将根 A 前面的所有节点放在节点 A 的左侧,将根 A 后面的所有节点放在右侧,如图 (b) 所示。
先处理所有前面的节点,然后再处理后面的节点。
如图 (c) 所示,我们将首先处理节点 B。由于节点 B 前面没有任何内容,因此我们将其置为 NIL。但是,节点 C 位于节点 B 后面,因此节点 C 将移至节点 B 的右侧。
对节点 D 重复相同过程。