好久没更新了~
由于对NPR方面比较感兴趣,所以任性了一下,先翻译了这一章~
业余翻译,若有不周到之处,还请多多指教!
实时渲染(第四版)Real-Time Rendering (Fourth Edition)
第15章 非真实感渲染 Chapter 15 Non-Photorealistic Rendering
“使用诸如‘非线性科学’之类的术语就像将大部分动物学称为‘对非大象的动物之研究’。”
“Using a term like ‘nonlinear science’ is like referring to the bulk of zoology as ‘the study of nonelephant animals.’ ”
——斯坦尼斯瓦夫·乌兰Stanislaw Ulam
真实的渲染试图使图像与照片无法区分。非真实感渲染(Non-photorealistic rendering,NPR)也称为风格化渲染,它的渲染目标很广泛。NPR 某些形式的目标之一是创建类似于技术插图的图像。只有那些与特定应用程序目标相关的细节才是应该显示的细节。例如,发亮的法拉利发动机的照片可能有助于将汽车出售给客户,但要修理发动机,简化的画线并突出显示相关部件可能更有意义(并且打印成本更低)。
NPR 的另一个领域是模拟绘画风格和自然媒介,例如笔和墨水,木炭和水彩。这是一个巨大的领域,可以运用多种多样的算法来尝试捕捉各种绘画媒介的感觉。一些示例如图 15.1 所示。有两本较旧的书籍介绍了技术性和绘画性 NPR 算法 [563,1719]。鉴于这种广度,我们在这里着重于渲染笔触和线条的技术。我们的目标是介绍一些用于实时渲染的 NPR 算法。本章从详细讨论实现卡通渲染样式的方式开始,然后讨论了 NPR 领域中的其他主题。最后,本章将以各种线条渲染的技术作为结尾。
15.1 卡通着色 Toon Shading
就像改变字体会给文本带来不同的感觉一样,不同的渲染样式也具有自己的情绪,含义和词汇。NPR,cel 或卡通渲染(toon rendering)的一种特殊形式引起了广泛的关注。由于这种风格与卡通十分相像,因此具有幻想和童年相关的内涵。卡通着色的最简单方法是用实线绘制对象,并以实线分隔不同的纯色区域。这种风格流行的一个原因在McCloud的经典著作Understanding Comics [1157] 中有提到,它被称为“通过简化进行放大”。通过简化和消除混乱,可以增强与演示相关的信息的效果。对于卡通人物,那些以简单样式绘制的人物将被更广泛的受众认同。
卡通渲染样式已在计算机图形学中使用了数十年,以将三维模型与二维 cel 动画集成在一起。与其他 NPR 样式相比,它很容易定义,因此非常适合通过计算机自动生成。许多视频游戏都很好地使用了它 [250,1224,1761] 。参见图 15.2。
图15.2. 游戏 《大神》(Okami) 中的实时 NPR 渲染示例。(图片由Capcom Entertainment,Inc.提供)
对象的轮廓通常以黑色渲染,从而放大了它的卡通外观。下一节将介绍如何查找和渲染这些轮廓。卡通表面着色有几种不同的方法。两种最常用的方法是用纯色(无照明,unlit)填充网格区域,或使用两色方法来表示已照明和阴影的区域。当在阴影法线和光源方向的点积大于某个值时,通过使用较浅的颜色,可以在像素着色器中轻松执行两色调方法(有时称为硬阴影),如果不是,则使用较暗的色调。当照明更加复杂时,另一种方法是量化最终图像本身。也称为色调分离(posterization),这是获取连续范围的值并将其转换为几个调子的一个过程,每个色调之间都有很大的变化。参见图 15.3。量化 RGB 值可能会导致令人不愉快的色调偏移(hue shifts),因为每个单独的通道都以与其他通道不紧密相关的方式进行更改。选择保留色调的颜色空间(例如HSV,HSL或Y’CbCr)是更好的选择。或者,可以定义一维函数或纹理以将强度级别重新映射为特定的阴影或颜色。纹理也可以使用量化或其他过滤器进行预处理。第 665 页的图 15.16 显示了具有更多颜色级别的另一个示例。
图15.3. 左侧的基本渲染依次应用了实心填充,色调分离(posterization)和铅笔着色技术。(由Quidam制作的Jade2模型,由wismo [1449] 发布,Creative Commons 2.5归因许可证。)
Barla 等人 [104] 通过使用二维贴图代替一维阴影纹理来增加与视图相关的效果。通过表面的深度或方向可以访问贴图的第二维度。例如,当距离较远或移动较快时,这可使对象平滑地变得柔和。该算法与各种其他着色方程式和绘制的纹理相结合,在《军团要塞2》游戏中使用,以融合卡通和真实的风格 [1224]。卡通着色器上的变体可以用于其他目的,例如在表现表面或地形上的特征时提高其对比度 [1520]。
15.2 外轮廓线渲染 Outline Rendering
用于 Cel 边缘渲染的算法反映了 NPR 的一些主要主题和技术。我们的目标是提出一种能体现区域轮廓的算法。可以将使用的方法大致分类为基于表面着色,程序化几何体,图像处理,几何边缘检测或它们的混合方法。
- 边界(boundary)或边界边缘(border edge)是两个三角形不共享的边界,例如,一张纸的边缘。实体通常没有边界边缘。
- 折痕(crease),硬边缘或特征边缘是两个三角形共享的边缘,并且两个三角形之间的角度(称为二面角)大于某个预定义值。好的默认折痕角为60度 [972]。例如,一个立方体具有折痕边缘。折痕边缘可进一步细分为山脊(ridge)和山谷(valley)边缘。
- 当共享其两个三角形的材质不同或以其他方式引起阴影变化时,将出现材质边缘(material edge)。它也可以是艺术家希望一直显示的边缘,例如角色头部的抬头纹或分隔相同颜色的裤子和衬衫的线。
- 等高线边缘(contour edge)是其中两个相邻三角形与某个方向向量(通常是眼睛的一个方向)相比面向不同方向的边缘。
- 轮廓边缘(silhouette edge)是沿着对象轮廓的轮廓边缘,即,它在图像平面中将对象与背景分开。
参见图 15.4。这种分类基于文献中的常用用法,但是存在一些变化,例如,我们称之为折痕,而材质边缘有时在其他地方称为边界边缘。
图15.4. 顶部打开的盒子,前面有条纹。显示了边界(boundary,B),折痕(crease,C),材质(material,M)和轮廓(silhouette,S)边缘。根据给定的定义,没有一个边界边缘被视为轮廓边缘,因为这些边缘仅具有一个相邻的多边形。
我们在这里区分轮廓和轮廓边缘。两者都是边缘,表面的一部分沿该边缘面向观察者,另一部分面向外。外轮廓边缘(Silhouette Edges)是轮廓边缘(contour edges)的子集,轮廓边缘将对象与另一个对象或背景分开。例如,在头部的侧视图中,即使耳朵出现在头部的轮廓轮廓内,耳朵也会形成轮廓边缘。图 15.3 中的其他示例包括鼻子,两个弯曲的手指以及其中的头发部位。在一些早期文献中,轮廓边缘(contour edges)被称为外轮廓(silhouettes),但是通常是指轮廓边缘的全部类别。而且,轮廓线边缘不应与地形图上使用的轮廓线混淆。
请注意,边界边缘(boundary edges)与轮廓(contour)或外轮廓边缘(silhouette edges)不同。轮廓和轮廓边缘由视图方向定义,而边界边缘与视图无关。提示轮廓(Suggestive contours) [335] 由从原始角度看几乎是轮廓的位置形成。它们提供了附加的边缘,有助于传达物体的形状。参见图15.5。尽管我们的重点主要是检测和渲染轮廓边缘,但是其他类型的笔触也做了很多工作 [281、1014、1521]。我们也会将重点放在为多边形模型找到此类边缘上。B´enard等人 [132] 讨论了寻找由细分曲面或其他高阶定义组成的模型轮廓的方法。
图15.5. 从左到右:silhouette,contour, 和 contour 以及暗示的轮廓边缘。(图片由Doug DeCarlo,Adam Finkelstein,Szymon Rusinkiewicz和Anthony Santella提供。
15.2.1 着色法线轮廓描边 Shading Normal Contour Edges
与第 15.1 节中的表面着色器类似,着色法线与眼睛观察方向之间的点积可用于给出轮廓边缘 [562]。如果该值接近零,则曲面几乎在眼睛的边缘,因此很可能在轮廓边缘附近。将此类区域涂成黑色,随着点积的增加,颜色逐渐变为白色。参见图 15.6。在可编程着色器之前,该算法是使用带有黑环的球形环境贴图,或将 mipmap 金字塔纹理的最顶层着色为黑色来实现的 [448]。如今,这种着色可以直接在像素着色器中实现,方法是在屏幕法线垂直于视图方向时使其变黑。
图15.6. 当轮廓线的阴影法线与视图方向垂直时,通过使表面变暗来阴影轮廓边缘。通过加宽衰减角,可以显示较粗的边缘。(图片由肯尼·霍夫(Kenny Hoff)提供。)
从某种意义上说,这种着色与边缘光(rim lighting)相反,在边缘光中,光照亮了对象的轮廓。在这里,场景是从眼睛所在的位置照亮的,并且衰减过大,边缘变暗。也可以将其视为图像处理中的阈值(thresholding)滤波器,其中,只要表面低于特定强度,图像就会转换为黑色,否则转换为白色。
该方法的一个特点或缺点是,轮廓线的绘制宽度取决于表面的曲率。此方法适用于没有折痕边缘的曲面模型,例如,轮廓上的区域通常将具有法线指向几乎垂直于视图方向的像素。该算法在诸如立方体的模型上失败,因为折痕边缘附近的表面积将不具有此属性。它也可能破裂,甚至在弯曲的表面上看起来也很糟糕,因为当物体很远并且在轮廓边缘附近采样的某些法线可能不是近乎垂直的。Goodwin 等人 [565] 注意这个基本概念仍然如何作为视觉提示有效,并讨论如何将照明,曲率和距离结合起来确定笔触粗细。
15.2.2 程序化几何轮廓获取 Procedural Geometry Silhouetting
Rossignac 和 van Emmerik [1510] 提出了最早的实时轮廓边缘渲染技术,后来 Raskar 和 Cohen [1460] 对其进行了改进。一般的想法是正常地渲染正面,然后以使背面轮廓可见的方式渲染背面。渲染这些背面有多种方法,每种方法都有其优点和缺点。并且每种方法的第一步都是绘制正面。然后,打开正面剔除,关闭背面剔除,以便仅渲染背面。
渲染轮廓的一种方法是仅绘制背面的边缘(而不是表面)。使用偏移(biasing)或其他技术(第 15.4 节)可确保其中一些轮廓线正好在正面的前方绘制。这样,只有正面和背面相交的边缘才可见 [969,1510]。
使这些线条更宽的一种方法是将模型背面本身变为黑色,然后再次向前偏移。Raskar 和 Cohen 提供了几种偏移方法,例如以固定量进行平移,或者以补偿 z 深度的非线性性质的量进行平移,或者使用诸如 OpenGL 的 glPolygonOffset 之类的深度斜率偏移调用。Lengyel [1022] 讨论了如何通过修改透视矩阵来提供更好的深度控制。所有这些方法的问题在于它们不能创建宽度一致的线。为此,向前偏移的量不仅取决于背面,而且还取决于相邻的正面。参见图 15.7。背面的坡度可用于使多边形向前偏置,但是线的粗细也将取决于正面的角度。
图15.7. 通过将背面向前平移来完成的 z-bias silhouetting 方法。如果正面以不同的角度(如右图所示),则可以看到不同数量的背面。(在Raskar 和 Cohen [1460] 之后的插图。)
Raskar 和 Cohen [1460,1461] 通过将每个背面三角形沿其边缘加宽至能够看到连续的边缘线,从而解决了相邻的依赖性问题。即,三角形的斜率和与观看者的距离确定三角形扩展了多少。一种方法是将每个三角形的三个顶点沿其平面向外扩展。渲染三角形的一种更安全的方法是将三角形的每个边缘向外移动并连接边缘。这样做可以避免顶点远离原始三角形。参见图 15.8。请注意,此方法不需要偏移,因为背面会扩展到正面的边缘之外。有关这三种方法的结果,请参见图 15.9。这种加粗技术更加可控且一致,并且已成功用于波斯王子(Prince of Persia) [1138] 和爆炸头武士 (Afro Samurai)[250] 等视频游戏中的角色描边。
图15.8. 三角形扩张。在左侧,背面三角形沿其平面扩展。每个边缘在世界空间中移动的量不同,以使所得边缘在屏幕空间中具有相同的厚度。对于细长的三角形,若其中一个角变长,此技术会露馅。在右侧,将三角形的边缘扩展并合并以形成斜切的角,以避免出现此问题。
图15.9. 轮廓线的轮廓使用带有粗线,z 偏移和加宽三角形算法的背面轮廓线绘制。由于小细节的偏移问题,背面边缘技术使线和不均匀线之间的连接不良。因为依赖于正面的角度,所以z-bias 技术给出的边缘宽度是不均匀的。(图片由 Raskar 和 Cohen [1460] 提供。)
在刚刚给出的方法中,背面三角形沿其原来的平面进行扩展。另一种方法是通过沿共享顶点法线来移动顶点,使其背面向外移动,其角度与距眼睛的 z 距离成比例 [671]。这称为外壳(shell)方法或光环(halo)方法,因为偏移的背面会形成围绕原始对象的外壳。假设有一个球体。首先,我们正常渲染球体,然后以相对于球体中心 5 像素宽的半径扩展球体。也就是说,如果将球体的中心移动一个像素相当于在世界空间中将其移动 3 毫米,则将球体的半径增加 15 毫米。扩展出的背面仅以黑色显示。那么轮廓边缘将为 5 像素宽。参见图 15.10。沿着顶点的法线向外移动顶点对顶点着色器来说是一项完美的任务。这种扩展方法有时称为外壳映射(shell mapping)。该方法易于实现,高效,鲁棒并且性能稳定。参见图 15.11。可以通过对背面的角度进一步扩展,和对这些底面进行着色,来产生力场或光晕的效果。
图 15.10 三角形外壳技术通过沿其顶点法线偏移表面来创建第二个表面。
图 15.11 游戏《巨大损伤》(Cel Damage) 的实时卡通风格渲染示例,使用背面外壳扩展来形成轮廓边缘以及显着的折痕边缘绘图。(图片由Pseudo Interactive Inc.提供)
这种外壳技术有几个潜在的陷阱。想象一下,正面朝一个立方体看,只有一个面是可见的。形成轮廓边缘的四个背面中的每个背面都将沿其对应的立方体面的方向移动,因此在拐角处会留有间隙。发生这种情况的原因是,尽管在每个角上只有一个顶点,但是每个面都有一个不同的顶点法线。问题在于,由于每个角顶点沿不同的方向扩展,因此扩展的多维数据集无法真正形成外壳。一种解决方案是强制相同位置的顶点共享单个新的平均顶点法线。另一种技术是在折痕处创建退化的几何形状,然后将其扩展为具有面积的三角形。Lira 等人 [1053] 使用附加的阈值纹理来控制每个顶点应该移动多少。
由于所有背面都沿着管线输送,因此外壳和加粗技术浪费了一些填充操作。所有这些技术的另外局限性在于,我们几乎无法控制边缘外观,并且半透明表面很难正确地渲染,具体取决于所使用的透明度算法。
整个几何技术类别描边的一项有价值的特点是,在渲染过程中不需要连接信息或边缘列表。每个三角形均独立于其余三角形进行处理,因此,此类技术适用于 GPU 实现 [1461]。
此类算法仅渲染轮廓边缘。Raskar [1461] 为在变形模型上绘制山脊折痕边缘提供了一个巧妙的解决方案,而无需创建和访问边缘连通性的数据结构。这个想法是沿着要渲染的三角形的每个边缘生成一个附加的多边形。这些边缘多边形通过用户定义的临界二面角弯曲而远离三角形的平面,该角决定了何时应可见折痕。如果在任何给定的时刻,两个相邻的三角形都大于此折角,则边缘多边形将可见,否则它们将被三角形隐藏。参见图 15.12。谷底边缘可以通过类似的技术来实现,但是需要模板缓冲区和多 Pass。
图 15.12 在边缘连接的两个三角形的侧视图,每个三角形都附有一个小的“鳍”。当两个三角形沿边缘弯曲时,鳍片朝可见方向移动。右边的鳍被暴露。显示为黑色,使这些看起来像是山脊边缘。
15.2.3 使用图像处理方法的边缘检测 Edge Detection by Image Processing
上一节中的算法有时会归类为基于图像的算法,因为屏幕分辨率决定了它们的执行方式。但有另一种类的算法更直接地基于图像,因为它完全对存储在图像缓冲区中的数据进行操作,并且不修改(甚至不直接知道)场景中的几何形状。
Saito 和 Takahashi [1528] 首先介绍了这种 G 缓冲区概念,该概念也用于延迟着色(第20.1节)。Decaudin [336] 扩展了 G 缓冲区的使用来执行卡通渲染。基本思想很简单:可以通过对各种信息缓冲区执行图像处理算法来实现 NPR 渲染。通过寻找相邻 z 缓冲区值的不连续性,可以找到许多轮廓边缘位置。相邻表面法线值的不连续性通常表示轮廓和边界边缘的位置。以环境颜色或带有对象标识值渲染场景可用于检测材质,边界和真实轮廓边缘。
检测和渲染这些边缘包括两部分。首先,渲染场景的几何体,并使用像素着色器保存各种渲染目标所需的深度,法线,对象 ID 或其他数据。然后以与第 12.1 节中所述类似的方式执行后处理过程。后处理 Pass 对每个像素周围的邻域进行采样,并根据这些采样输出结果。例如,假设我们对场景中的每个对象都有唯一的标识值。在每个像素处,我们可以对该 ID 进行采样,并将其与测试像素角落处的四个相邻像素ID值进行比较。如果任何 ID 与测试像素的ID不同,则输出黑色,否则输出白色。对所有八个相邻像素进行采样会更加安全,但采样成本更高。这种简单的测试可用于绘制大多数对象的边界和轮廓边缘(真实轮廓)。材质 ID 则可用于查找材质边缘。
轮廓边缘可以通过在普通和深度缓冲区上使用各种过滤器来找到。例如,如果相邻像素之间的深度差高于某个阈值,则轮廓边缘很可能存在,因此将像素设为黑色。相比简单地判断相邻像素是否与我们的样本相匹配,我们更需要其他更精细的边缘检测算子。我们不会在这里讨论各种边缘检测滤波器的优缺点,例如罗伯茨交叉(Roberts cross),索伯尔(Sobel)和斯查尔(Scharr),因为图像处理相关的文献已经广泛地涵盖了这些问题 [559,1729]。由于此类运算符的结果不一定是布尔值,因此我们可以在某些区域中调整其阈值或在黑白之间淡入淡出。请注意,法线缓冲区还可以检测折痕边缘,因为法线之间的较大差异可以表示轮廓或折痕边缘。Thibault 和 Cavanaugh [1761] 讨论了他们如何将这种技术与深度缓冲区一起用于《无主之地》游戏。除其他技术外,他们还修改了 Sobel 滤波器,以便它创建单像素宽的轮廓线和深度计算以提高精度。参见图 15.13。也可以沿另一个方向移动,通过忽略相邻深度差异很大的边缘,从而仅在阴影周围添加轮廓 [1138]。
图15.13 在《无主之地》(Borderlands)游戏中修改了 Sobel 边缘检测。最终发布的版本(此处不予展示)通过遮盖前景中草的边缘 [1761] 进一步改善了外观。(图片由Gearbox Software,LLC提供。)
扩张算子(dilation operator)是一种形态学算子,用于加厚检测到的边缘 [226、1217]。生成边缘图像后,将应用单独的 Pass。在每个像素处,都会检查像素值及其周围值(在某个半径范围内)。找到的最暗像素值将作为输出返回。这样,一条细黑线将被搜索区域的直径加粗。多 Pass 可用于进一步加厚描边(但可能消耗过大),权衡的结果是,每个Pass需要的样本数量会大大减少,以抵消额外Pass的成本。不同的计算结果可以具有不同的厚度,例如,可以使轮廓边缘比其他轮廓边缘更厚。相关的腐蚀算子(erosion operator)可用于细化描边或其他效果。一些计算结果可见图 15.14。
图15.14. 法线贴图(左上)和深度图(中上)对其值应用了 Sobel 边缘检测,结果分别显示在左下和中下。右上方的图像是使用膨胀(dilation)的加厚的合成图像。右下角的最终渲染是通过使用 Gooch 着色方法对图像进行着色并在边缘进行合成来完成的。(图片由 ATI Technologies Inc. 的 Drew Card 和 Jason L. Mitchell 提供)
这种算法有几个优点。与大多数其他技术不同,它可以处理所有类型的平面或曲面。网格不必连接,甚至不必保持一致,因为该方法是基于图像的。
这种技术的缺陷相对较少。对于接近边缘的表面,z 深度比较滤波器可能会错误地检测到整个表面上的轮廓边缘像素。z 深度比较的另一个问题是,如果差异很小,则轮廓边缘可能会丢失。例如,桌上的一张纸通常会遗漏边缘。类似的,法线贴图滤波器也将丢失这张纸的边缘,因为它们的法线是相同的。这仍然不是万无一失的;例如,一张折叠到其自身上的纸将在边缘重叠处造成无法检测的边缘 [725]。另外,生成的线条会显示出阶梯状锯齿,但是第 5.4.2 节中描述的各种形态抗锯齿技术可以很好地与这种高对比度输出以及后代化等技术配合使用,以改善边缘质量。
边缘检测也可能以相反的方式造成失败,例如在不存在边缘的地方创建边缘。确定什么能构成边缘并不是一项简单易行的操作。确定构成边缘的方法并非万无一失。例如,想象一下玫瑰,细圆柱的茎。镜头靠近时,样本像素附近的茎法线变化不大,因此没有检测到边缘。随着我们的镜头远离玫瑰,法线在像素之间的变化将更快,直到由于这些差异而在某个点附近的边缘可能发生错误的边缘检测。从深度图来检测边缘也会发生类似的问题,而透视图对深度的影响是需要补偿的另一个因素。Decaudin [336] 提供了一种通过处理法线贴图和深度图的梯度而不仅仅是值本身来寻找变化的改进方法。确定各种像素差异如何转换为颜色变化是一个经常需要针对内容进行调整的过程 [250,1761]。参见图15.15。
图15.15. 各种边缘方法。诸如皱纹之类的特征边缘是纹理本身的一部分,由艺术家预先添加。角色的轮廓通过背面挤压生成。使用图像处理边缘检测以不同的权重生成轮廓边缘。左边图片的权重太小,因此这些边缘不清晰。中间图片显示轮廓,特别是在鼻子和嘴唇的轮廓边缘。右侧图片显示了权重过大的失真[250]。(Afro Samurai ®&© 2006 TAKASHI OKAZAKI, GONZO / SAMURAI PROJECT.Program © 2009 BANDAI NAMCO Entertainment America Inc.)
一旦生成笔触,就可以根据需要执行进一步的图像处理。由于笔触可以在单独的缓冲区中创建,因此可以对其进行单独修改,然后在表面上进行合成。例如,可以使用噪波功能分别使线条和表面磨损和摆动,从而在两者之间形成小的间隙并呈现手绘效果。纸张的高度场可作用于渲染,固体材料(例如木炭)沉积在凹凸点的顶部,或水彩颜料堆积在凹处。有关示例,请参见图15.16。
图15.16. 左侧的鱼模型通过边缘检测,后处理,噪声扰动,模糊和融合在纸上,在右侧进行渲染。(图片由Autodesk,Inc.提供)
在这里,我们将专注于使用几何或其他非图形数据(例如法线,深度和ID)检测边缘。正如其名,图像处理技术被用于处理图像,并且这种边缘检测技术可以用于颜色缓冲器。有一种称为高斯差分(difference of Gaussians,DoG)的方法,它使用两个不同的高斯滤波器对图像进行两次处理,然后从一个结果中减去另一个结果。目前已经发现这种边缘检测方法对于NPR能产生令人特别愉悦的结果,此方法被用于生成各种艺术风格的图像,例如铅笔阴影和粉彩[949,1896,1966]。
在许多NPR技术中,图像后处理计算在模拟艺术媒介(例如水彩和丙烯酸涂料)中都具有突出的特点。在这个领域有大量的研究,对于交互式应用程序,许多挑战在于尝试以最少的纹理样本数量来最大程度地完成效果。双边(Bilateral),均值偏移(mean-shift),以及Kuwahara过滤器可以在GPU上使用,以保留边缘和平滑区域,使其看起来好像被手工绘制一样[58,948]。Kyprianidis等人 [949]提供了该领域的图像处理效果的全面回顾和分类。Montesdeoca等人的工作 [1237]是将许多简单的技术组合到以交互速率运行的水彩效果中的一个很好的例子。用水彩风格绘制的模型如图15.17所示。
15.2.4 几何轮廓边缘检测 Geometric Contour Edge Detection
到目前为止给出的方法的一个问题是,边缘的风格化是有限的。我们不能轻易使线条看起来是虚线,更不能说是手绘的或像笔触一样。对于这种操作,我们需要找到轮廓边缘并将其直接渲染。具有独立的独立边缘实体可以创建其他效果,例如当模型网格在冻结状态中抖动时,轮廓的突然变形。
在轮廓边缘中,两个相邻的三角形之一朝向观看者,另一个则背对着观察者。其测试的方式是
其中和 是两个三角形法线,是从眼睛到边缘(即到任一端点)的视图方向。为了使该测试正常进行,必须使表面始终保持固定方向(第16.3节)。
在模型中查找轮廓边缘的蛮力方法是遍历边缘列表并执行此测试[1130]。Lander [972]指出,值得进行的优化是识别和忽略平面多边形内部的边。也就是说,给定一个相连的三角形网格,如果一条边的两个相邻三角形位于同一平面上,则该边不可能是轮廓边。在一个简单的时钟模型上执行此测试,可以将边缘计数从444个边缘减少到256个。此外,如果模型定义了实体,则凹形边缘永远不会是轮廓边缘。Buchanan和Sousa [207]通过重复使用每个面的点积测试,避免了对每个边缘进行单独的点积测试的需要。
从头开始检测每个帧的轮廓边缘可能会很昂贵。如果摄像机视图和对象在帧与帧之间移动不大,则可以合理地假设先前帧的轮廓边缘可能仍然是有效的轮廓边缘。Aila和Miettinen [13]将有效距离与每个边缘相关联。该距离是观察者可以移动的距离,并且轮廓边缘仍保持其状态。在任何实体模型中,每个单独的轮廓始终由一条闭合曲线组成,称为外轮廓环(silhouette loop),或更恰当的说是轮廓环(contour loop)。对于对象边界内的轮廓,环的某些部分可能会被遮盖。甚至实际的轮廓也可能由几个环组成,其中部分环在轮廓内或被其他表面隐藏。因此,每个顶点必须具有偶数个轮廓边[23]。参见图15.18。请注意,跟随网格边缘时,环在三个维度上经常会参差不齐,z深度会明显变化。如果需要形成更平滑曲线的边缘(例如,通过距离更改厚度[565]),则可以执行其他处理以在三角形的法线之间进行插值,以近似三角形内部的真实轮廓边缘[725,726]。
译者注:
silhouette 物体的外轮廓
contour 物体的轮廓线,含内部线条
Edge 物体边缘的曲线,偏向平面物体
Outline、profile 物体大概的轮廓外形
图15.18. 轮廓环(Contour loops)。左侧是相机的模型视图。中间以蓝色显示了背对摄像机的三角形。右侧显示了脸部一个区域的特写。注意复杂性以及一些轮廓线如何隐藏在鼻子后面。(模型由Chris Landreth提供,图像由Pierre B´enard和Aaron Hertzmann [132]提供。)
从一帧到另一帧跟踪环位置可能比从头开始创建环要快。Markosian等人 [1125]从一组环开始,使用随机搜索算法在相机移动时更新此环。当模型改变方向时,也会创建并破坏轮廓环。Kalnins等人 [848] 指出了当两个环合并时,需要采取纠正措施,否则将看到从一帧到下一帧的明显跳跃。他们使用像素搜索和“投票”(vote)算法来尝试保持帧与帧之间的轮廓一致性。
这样的技术可以大大提高性能,但可能不准确。而线性方法则很精确,但很昂贵。使用相机访问轮廓边的分层方法结合了速度和精度。对于非动画模型的正交视图,Gooch等人 [562]使用高斯映射的层次结构来确定轮廓边缘。Sander等人 [1539]使用普通圆锥的n元树(第19.3节)。Hertzmann和Zorin [726]使用模型的双空间表示法,使他们可以在模型的边缘上施加层次结构。
所有这些显式的边缘检测方法都占用大量CPU并具有较差的缓存一致性,因为形成轮廓的边缘分散在整个边缘列表中。为了避免这些成本,顶点着色器可以用于检测和渲染轮廓边缘[226]。这个想法是将模型的每个边缘作为两个三角形形成退化的四边形,沿着管线向下发送,两个相邻的三角形法线附着在每个顶点上。当发现边缘是轮廓的一部分时,四边形的点将移动,以使其不再退化(即变为可见)。然后绘制该薄四边形的鳍(fin)。该技术基于与为阴影体积创建找到轮廓边缘所描述的思想相同的思想(第7.3节)。如果几何体着色器是管线的一部分,则不需要存储这些额外的鳍四边形,而是可以随时生成它们[282,299]。过于简单天真的实现方法会在鳍片之间留下裂缝和缝隙,这可以通过修改鳍片的形状来纠正[723,1169,1492]。
15.2.5 隐藏线删除 Hidden Line Removal
找到轮廓后,将渲染线条。明确找到边缘的一个优点是您可以将其样式化为笔触,绘画笔触或所需的任何其他介质。笔画可以是基本线条,带纹理的冒名顶替者(第13.6.4节),原始元素集或其他您想尝试的东西。
尝试使用几何边缘的另一个复杂之处在于,并非所有这些边缘实际上都是可见的。建立z缓冲区的渲染表面可以掩盖隐藏的几何边缘,这对于简单的样式(例如虚线)可能就足够了。Cole和Finkelstein [282]通过沿线本身的脊线采样z深度,将其扩展到表示线的四边形。但是,使用这些方法时,沿线的每个点都是独立绘制的,因此事先没有明确定义的开始和结束位置。对于轮廓线或其他边缘(其中的线段用于定义笔触或其他连续对象),我们需要知道每个笔触何时出现以及何时消失。确定每个线段的可见性称为隐藏线渲染,其中将处理一组线段以获取可见性,并返回较小的一组(可能会被裁剪的)线段。
Northrup和Markosian [1287]通过渲染对象的所有三角形和轮廓边并为每个对象分配不同的标识号来解决此问题。读取该ID缓冲区,并从中确定可见轮廓边缘。然后检查这些可见段是否重叠,并将它们链接在一起以形成平滑的笔触路径。如果屏幕上的线段很短,则此方法有效,但不包括对线段本身的剪辑。然后沿着这些重建的路径渲染风格化的笔画。笔触本身可以以许多不同的方式进行样式化,包括锥度,耀斑,摆动,超调和淡入的效果以及深度和距离提示。图15.19中显示了一个示例。
图15.19. 使用Northrup和Markosian的混合技术制作的图像。找到轮廓边,将其内置到链中并渲染为笔触。(图片由Lee Markosian提供。)
Cole和Finkelstein [282]提出了一组边缘的可见性计算方法。它们将每个线段存储为两个世界空间坐标值。一系列遍历在整个pass集合上运行像素着色器,剪切并确定每个pass的像素长度,然后为这些潜在像素位置的每个创建图集并确定可见性,然后使用此图集创建可见笔触。虽然很复杂,但该过程在GPU上相对较快,并且提供了具有已知开始和结束位置的可见笔触集。
风格化通常包括将一个或多个预制纹理应用于四边形线。Rougier [1516]讨论了一种不同的方法,以程序方式绘制虚线图案。每个线段访问一个纹理,该纹理存储所需的所有虚线图案。每个模式都编码为一组命令,这些命令指定虚线模式以及所使用的端盖(endcap)和联接类型。使用四边形的纹理坐标,每个图案都会控制着色器进行一系列测试,以测试有多少线覆盖四边形中每个点的像素。
确定轮廓边缘,将它们链接成连贯的链,然后确定每个链形成一个笔画的可见性很难完全并行化。产生高质量线型时的另一个问题是,对于下一帧,将再次绘制每个笔触,更改其长度或可能是第一次出现的笔触。B´enard等人 [130]提出了一种渲染方法的研究,该方法为沿边缘和图案的笔触提供时间上的连贯性。这不是一个已解决的问题,它可以通过计算来解决,因此研究还在继续[131]。
译者注:
Endcap,线段的末端外观