图形学基础 真假位移(法线贴图、凹凸贴图和位移贴图、向量位移贴图的对比与区别)

写在前面:

本文是在阅读了知乎题目为《高度图,视差贴图(Bump-maps),置换贴图(displacement),法线贴图的本质》一文后,对翻译内容有些疑问,故而去查阅原文,做出的翻译。翻译一法,仁者见仁,智者见智,在参考我的翻译之后如果发现有任何不准确之处,欢迎指正,同时也推荐去查阅知乎相关帖子,或者直接去阅读A站英文原文。
https://www.artstation.com/andreasmischok/blog/jzWz/fake-vs-true-displacement-part-12
至于我写这篇翻译的目的,是希望能够清晰得掌握(或者说确立)自己对于中文相应概念的对应,同时进行知识巩固。

注意:
翻译主要是基于我的英文水平,外加google翻译和维基百科的参照。
在翻译中每当出现新的技术名词,我都会将其列在文中,以小括号()进行区别。同时,我也会在内容中利用一些小括号补充我对于特定内容的理解和理论,不一定正确,仅仅是基于我在图形学浅薄的研究。我并不是图形学或者翻译学的权威,所以我建议是在参考这篇翻译的同时,对英文概念进行掌握。


正文:

虚假 vs 真实位移(Fake vs True Displacement)

凹凸贴图(bump-maps),法线贴图(normal-maps),位移(displacement)和向量位移贴图(vector displacement)。到现在你可能已经至少遇到过其中的某一个。虽然现在已经有很多关于他们的信息可供查询,但是看起来关于他们的区别和使用某一种特定类型贴图的效果仍然存在一些混淆和误解。这篇文章将会主要集中精力于需要注意的问题点,而不是具体如何去实现某一个效果。

上述四种纹理类型有一个共同的目的——为模型添加更多的表面细节,当然具体使用的方法各有不同。说到具体的方法,他们可以细分为两个大类,我将会称他们为真实的位移(true displacement)和虚假的位移(fake displacement)。单词“位移displacing”只是“移动moving”的同义词,这正指出了我们要讨论的区别的核心。真实的位移将会真正对顶点(vertices)进行移动,而虚假的位移则是在不改变集合的情况下尽力到达相同的显示效果。现在,我将集中于这两类贴图的区别,而不是将每个贴图类型都分开来分析。

在这里插入图片描述
总体上来讲,真实的位移可带来更加清晰的结果,但对渲染时间会产生很大的影响。

注:这里提一下高度图(height-map)。高度图一词描述了信息和数据是如何进行存储的,而不是它如何应用于网格之上。它可以作为凹凸贴图或位移贴图来进行使用。像Substance这样的软件会使用这个术语,因为软件本身并没有作出相关的声明,即你应该将高度图用作真实的位移或虚假的位移。*

在我们进一步讨论之前,我应该说明,作为一个特效师(vfx artist, 全称visual effect artist),我将会从视觉效果的视角并且使用路径追究渲染(path tracing rendering,与传统光栅化相对应)的方式来看待这个问题。如果你是使用不同的渲染方法(如游戏引擎),你得出的结果可能会不一样。真实的位移甚至有可能完全由引擎所支持。(译者注:这里译者的理解是,引擎所用的渲染并不是理论上的完全的光栅化或者完全的光追,而是某种针对平台进行过特定优化和改动的渲染模型。)

要理解虚假的位移是如何工作的,我们需要首先快速得过一遍路径追踪。简单来看:光线由场景中得光源发出,并在物体表面进行进行反弹直到他们到达相机。或者另一种,光线可能由相机出发并弹射直到到达光源。当然,无论是使用哪一种方式,都不会对我下面那要演示的效果产生影响。(译者注:真正的光追,除了考虑反射,还要考虑光线散射所需要消耗的光量,具体可以参考光辐射学)。

反射光线(reflected ray)的角度可以通过比较入射光线(incoming/incident ray)的角度和表面法线(surface normal)的角度从而计算得到。你们当中那些在学校学过向量数学的并且记性好的人,应该会认出“Normal”一词。在向量数学中(渲染的核心和基础),法线就是垂直于平面的向量。简单来将,我们可以说我们模型上的每一个面都是一个平面,因此每个面都有一个对应的法线。(译者注:对于没有基础或者遗忘了的人,向量可以理解为只有方向和长度的一个几何量,对应的单位向量就是单位长度的具有某一个方向的向量。)

在这里插入图片描述
注:实际上,多边形并不总是平面的。未来解决这个麻烦,渲染引擎将所有的多边形,包括四边形,都细分为了三角形,然后再计算所有构成面的三角形的平均法线。

法线贴图之所以这样命名是因为他们允许以像素的维度存储一个自定义的表面法线。这意味这你可以自由地操纵光线的弹跳方向,而无需改变几何形体。同样这意味着对于光线来说,法线贴图和凹凸贴图看起来是一样的。

在这里插入图片描述
我们可以通过修正表面法线的角度来模拟真实的位移的结果。在这个简单的例子中,它可能看起来还不错,但是不去对集合形体进行变形是以一些缺陷为代价的。使用哪种子类型纹理(凹凸或法线,位移或向量位移),以及纹理是通过烘焙得到还是预先制作的,都不会造成任何影响,缺陷仅取决于类别,因为它们全都源于以下事实: 虚假的位移不会使几何变形,而真实的位移则会使几何变形。

对灯光的影响

在观察例子时你观察到的第一个事情可能会是阴影(shadows)的缺失。真实的位移不仅会影响基本网格体产生的阴影的形状,它还可以创建新的形状,并产生完全的新的阴影。这一阴影可能会产生在自生身上(self-shadowing),同样也可能会投射到别的物体身上。
在这里插入图片描述
替换模型将会导致在自身上产生阴影的现象(self-shadowing,译者注:担心解释得不清晰,这里再备注一遍英文),因为光线不会击中表面上的同一位置(译者注:与未变形之前的网格体模型相比的同一位置)。如果在这个图中光源时太阳(平行光线),那么使用真实的位移可能会产生一个覆盖所有红色区域的阴影,而使用虚假的阴影则不会有这一效果。
在这里插入图片描述
参考这个简单的渲染案例,你可以看到照明情况的大致方向可以在两种方法(真实的位移和虚假的位移)中都体现出来,但是在使用虚假的位移时几何学层面的实际的阴影是被丢失掉了。

体现这种效果的一个很胖的例子是创建一面砖墙,当然是一个平面基础几何去体现。使用真实的位移,墙壁缝隙间的阴影会赋予墙面一个很强烈的深度的感觉,而没有这些阴影的情况下(应用虚假的位移)会导致看上去很平坦。
在这里插入图片描述

但是还需要说清楚一点,阴影的缺失并不是与光线交互中唯一的视觉上的区别。在不常规的真实的位移情况下,我们会增加物体的表面,这会导致更大数量的反弹光。这会导致黑暗区域在使用虚假的位移时看起来是不太自然的黑。

在这里插入图片描述
在小金字塔的渲染中(为了演示阴影生成),我增加了渲染的对比度,来掩盖这种效果,以专注于在一个时间点只专注于一个效果上。参照未经编辑的渲染,弹射的光的缺失将会变得愈发可见。
在这里插入图片描述
忽略了阴影生成的缺失和弹射光,还有另外的一种效果属于是对照明的影响。即几何体是如何接受阴影的。
在这里插入图片描述
就像前面中的一个例子中那样,红色代表阴影。通过比较由球体投射到我们物体上的阴影的高度,可以证明阴影的形状只会受到真实位移的影响。
在这里插入图片描述
在平面上分别应用真实的位移和虚假的位移得到一个波状平面,即有简单的上下波动。只有使用真真实的位移的平面上投射出来的影子会相应的产生变形,从而增加了深度感。

我到目前为止所提到的所有效果都会受到入射光的角度与相机角度的影响。如果你的相机与光源对齐,那么所有这些效果似乎都会消失。例如,阴影的变形会减少,因为相机的视图也会发生同样的变形。
在这里插入图片描述
此外,更多得阴影将会被几何体本身所挡住。
在这里插入图片描述
虽然这效果不错,但它并不是一个真正的解决方案。他们创建和增强的阴影和形状有助于使整个场景看起来有趣。如果你使用的是多个光源,那么你只能将相机与其中一个光源对齐。因此,不要让这影响你照亮场景方式方法或是相机的摆放位置。

观察最后的渲染,你可能已经注意到别的一些东西了。虽然法线贴图重现了相同的亮度值,但金字塔看起来仍然非常平坦。这是由于下面我要介绍的一个效应。

视差(Parallax)

作为透视的主要原理之一,视差描述了在移动相机时物体之间产生的看似相互移动的视觉效应。它不限于单独的分离的物体对象,它也会发生在3D空间中的任意两个给定的点。这意味着使用真实的位移的网格变形会对它产生影响。
在这里插入图片描述
我使用了红色的线标记所有三个对象上深度相同的位置区域,以便它们可以作为参考点。在另一方面,蓝色的线用作代表我们希望有视觉深度的位置。从上方直视向下看,真实的位移和虚假的位移几乎是相同的,但是在视线与平面接近重合的角度,低面数(lowpoly)/虚假的位移这两个版本的线条将保持相互间均匀的间距,而使用真实的位移的网格上线似乎是会移动。如果我们把相机倾斜程度再调高一点,平面靠后方的蓝色线就会完全消失在中心红线后。(译者注:这里我尽可能尊重原文的描述,简单来讲,其实还是回归到视差对深度感的影响)如果将蓝色线向上推,这时效果将发生反转,即前方蓝线几乎覆盖掉中心的红线。
在这里插入图片描述
一些游戏引擎提供了一种伪造视差的方法,称为视差映射(parallax-mapping),它的工作原理是将2D扭曲效果
(distortion)应用到渲染的像素上,(译者注:可以理解为在产生计算机画面后又ps了一下,是一种后处理方法)而不是几何体上。这提供了一些不错的额外保真度,但也导致性能上的问题。

奇怪的知识点:一些艺术家在一些真正有趣的方式来使用视差。一个很好的例子是Patrick Hughes。参看下面的视频,其中展示他的其中一件作品。

https://youtu.be/cDGlprrEPv4

90度角

可以使用真实的位移创建90度垂直偏移,相对的,在虚假的位移里则无法有相同的效果。从理论上来讲,垂直角度可以存储在法线贴图中,但这样做并没有任何意义,因为他们在逻辑上不会在低多边形网格上有任何相对应的区域。
在这里插入图片描述
上图中的绿色线代表我们基本网格的表面(译者注:整个图片的底部),而红色线代表高面数网格,即我们想要将高面数纹络烘培到网格上。源自我们的低面数网格的梯度显示了生成的法线贴图应该具有的值。高面数网格的每个表面角度都可以分配到我们的低面数网格上的一个区域,当然除了区域 1 和 2 之间的垂直角度,是因为它与基本网格没有任何的相关的宽度?凹凸贴图(bump map)也有这个问题,因为它们的本质是在渲染时转换为了表面法线。下面的第一张图片显示了用于烘烤法线和位移的高面数网格的侧视图,而第二张图片是使用烘焙纹理的渲染结果。
在这里插入图片描述
在这里插入图片描述
正如你所看到的,其他较大的角度仍然可以存储在法线贴图中,即便他们以微小的区域来表示,但是90度角已经完全消失。需要注意,通常应该避免使用纹理来创建较大的角度,即使是使用真实的位移贴图也是如此。由于这种位移贴图将拉伸其他纹理的像素。

轮廓(sihouette)

当只看轮廓时,虚假的位移不会改变几何形状也特别明显。在极端情况下,内部重叠甚至可能发生同样的情况,例如鼻子覆盖角色脸颊的一部分。

通常,有两种方法可以看到这种效果。应该柔和的轮廓变成块儿状或者说,应该有很多高频细节的轮廓突然缺少上述的细节。
在这里插入图片描述
在这里插入图片描述
次表面散射(sub surface scattering,即常说的SSS或3s效果)

如果你正在处理的资产应用到了SSS,那么你也可能察觉到虚假的位移的另一个缺点。
在这里插入图片描述
SSS的计算是随机化光线穿过物体时的角度。这意味着它们对表面角度的依赖比对网格的厚度和实际形状的依赖要小得多。在使用虚假的位移时,我们在示例中看到任何效果的唯一原因是从黑暗处到达相机的唯一光线是散射光线,而明亮区域则是所有光线的混合体。这给了较暗的区域一个红色的色调,但是在真实性方面则会大打折扣。

黑色区域或被拉伸的反射

除了因缺乏弹射光而引起的不自然的黑暗区域外,还有另一种影响导致类似的缺陷。使用虚假的位移时,表面法线和光线角度的某种特定组合可能导致反射光线,而这条反射光线的路径则需要穿过物体本身的表面。
在这里插入图片描述
因为我们没有试图渲染一个透明的表面,所以这没有任何意义。为了解决这个问题,渲染工作者想出了多种方法来处理这种情况。选用哪一种取决于你所用的渲染引擎。可供选择的选项有:

  • 直接消灭光线

  • 以不同的方式重定向光线

  • 在这些不正常的区域忽略掉法线贴图

Arnold就是其中的一个引擎,它只简单地杀死那些产生错误的光线,导致部分黑色反射(partially black reflection 译者注:即无反射产生)。在另一方面,真实的位移则会使光线从物体表面多进行几次反弹。
在这里插入图片描述
其他渲染器,如Blender的Cycle引擎将重定向光线到平行于低面数网格的表面,这会产生与原反射方向最接近的可能反射光线。虽然这可以防止它们被吸收掉,但它将会导致很多彼此接近的像素接收相同的输出向量,我们认为这些像素是被拉伸的反射。
在这里插入图片描述
到现在,虽然我还没有体验过使用第三个选项的渲染器,但我知道对应的情况。应用软边缘(soft edge)/平滑法线(smooth normal)(同一事物的不同命名约定)到网格插值从而实现对表面法线的插值处理,以模拟出更平滑的网格外观。
在这里插入图片描述
一般来说,渲染器与平滑法线的交互方式与虚假的位移相同。如果你将平滑法线应用到立方体上,陡峭的角度加上表面法线,如果渲染者不在三个选项之间做出选择,则会导致同样的两难境地。我不知道为什么,但Arnold会以不同的方式处理平滑法线,相较于虚假的位移。每当光线将要穿过物体时,它就会忽略平滑法线而不是杀死光线。
在这里插入图片描述
虽然全部这三种解决方案的结果在我的例子中都看起来很糟糕,但问题其实并不像看上去那么糟。为这些渲染过程我使用了非常大的纹理(像经常那样,纹理越大,相应的缺点也会被放大)。通常你都不会遇到需要你使用位移(无论真实的还是虚假的)的同时,应用如此大的纹理。你可以看到当从一个角度观察场景时,我的纹理是多么强大(译者注:即反映多少的细节)。
在这里插入图片描述
此外,还有另一个因素掩盖了这个问题,即实际的渲染比镜像反弹更为复杂。如果你正在渲染闪闪发光的铬,那么是的,你可能需要小心了,但一旦你引入了一些镜面粗糙度(specular roughness)或介电材料(dielectric material)(非金属),这种效果将开始逐渐失去作用。

镜面粗糙度是在微观层面模仿表面不完美性,这是通过对反射的角度添加随机偏移而做到的。表面越粗糙,可能的偏移范围就越大。

在这里插入图片描述
弹射的随机化模糊了反射,导致更少的光线/采样得到不合理角度的反射。单凭这一点并不能完全解决问题,你仍然会看到反射的保真度差异,但是不会像之前那么明显了。

在这里插入图片描述

介电材料会以一个完全随机的角度反射大部分击中他们的光线,这被称为漫反射(diffuse reflection),只有很小一部分被反射为镜面反射。这意味着即使表面完全光滑,问题也几乎不会引起注意。
在这里插入图片描述
这些图像是在Arnold渲染的,当我们单独观察镜面反射时,我们仍然可以看到黑色区域时,但是在最终的渲染结果中这些黑色区域已经几乎不会引起注意了。

曲面细分(Tessellation / Subdivision)

到目前为止,我提到的所有缺陷都是关于虚假的位移,但是接下来的是关于使用真实的位移的一个缺陷。

仅真实的位移就只能创建/重新创建多边形所支持的细节量。这意味着我们首先必须对网格进行细分。如果我们细分得不够充分,我们最终可能会得到一个无法支持存储在我们的纹理中的所有更精细的细节的几何体。这意味着你可能需要大量细分你的模型,从而致使场景变得非常繁重。幸运的是,渲染引擎现在某些特性。这些特性允许渲染引擎自动添加无法被几何体支持的细节,像虚拟的位移这样的。在某些渲染器中,此功能默认禁用,因此请检查该功能。令人讨厌的是,目前还没有任何标准化的命名约定。例如,Arnold称它为Autobump,而Cycle渲染引擎则称它为位移+凹凸(displacement + bump)。

初步对该功能进行体验,请查看下面的比较,这两个网格被细分了三次,但是只有组合的方法可以提供所有细节。
在这里插入图片描述
可悲的是,此功能并非完全没有bug,有很多情况可以导致运行错误。例如,不冻结/应用你的物体对象的缩放尺度。使用带有向量位移贴图的Autobump也可能遇到困难。

特别是当你开始的时候,通过创建比较渲染来确保一切按预期运行是个很好的做法。一个使用Autobump结合你预期的细分的次数和一个没有Autobump,但是有着非常高的细分量,以此来确保结果正确匹配。

注意在某些渲染器中,必须要单独启动带有SSS着色器(shader)的Autobump。使用虚假的位移的问题仍将发生在那些由Autobump功能添加的细节上,即使在毛孔等细微的细节上它们不会很强大。

结论

真实的位移和虚假的位移都是增加模型保真度的好方法。 我有意使用了非常有力的例子来非常清楚地展示所有的缺陷。但是 不要让这些成为你拒绝使用虚假的位移贴图(例如法线贴图)的理由。(译者注:他们都有他们存在的意义和必要。)

基本规则是,你的纹理越是发挥全部的效力,缺陷就会愈加明显。 因此,无论你要使用哪种方法,都应始终尝试使用基本拓扑捕获所有定义的形状。 在使用虚假的位移时这非常重要,但在使用真实的位移时也同样很重要。 如果你遵循这个简单的规则,那么两种方法都可以达到几乎相同的结果。 你能发现下图中哪些使用了真实的位移,哪些使用虚假的位移吗?
在这里插入图片描述
与任何复杂的主题一样,选择取决于情景(译者注:上下文),这是质量和性能之间的微妙平衡。如果您正在处理背景资产,那么使用真实的位移技术来减慢渲染时间可能不值得的,尤其是如果你的场景包含大量的资产时。

另一方面,如果您正在处理主角资产,使用真实的位移仍然可能是最佳的选择,因为它会简单地呈现更清晰的结果。即使在我向您展示的上一个渲染中,这两种方法在质量方面仍然存在一些差异。

但是规则也有例外。例如,如果你的时间安排非常紧凑,那么使用虚假的位移而不是真实的位移可以帮助你加快渲染速度。并且由于你将需要渲染序列,因此,与每个额外帧做乘法的渲单位渲染时间也会更短。

或者我们假设你需要一种特定的材质,并且你可以在线上找到的所有优质纹理仅仅是一个法线贴图,并且你也没有时间去自己创建材质。在这种情况下,即使你的资产是主角资产,你也可能要用一种使用法线贴图的材质。许多扫描材料可能就是属于这种情况,因为捕获高质量的法线贴图比创建高质量的位移贴图更快更容易。如果你对如何完成此操作感兴趣,那么下面的文章可能对您很有趣。 (不建议使用智能手机阅读)

https://magazine.substance3d.com/your-smartphone-is-a-material-scanner-vol-ii/

即使你由更复杂的3D形状,例如人脸,类似的技术也可以用来创建高质量的法线贴图。


译者的思考:

自己在有些时候会有看文章不带脑子的,做一些书籍或者是帖子翻译的目的是希望自己能够去思考所阅读的东西。比如说displacement map一词,我在阅读国内帖子和文章时候,有时候会读到“位移贴图”,而有时则是“置换贴图”,这使我在做概念对应的时候产生了一些误解。但是真正去理解,或者说定义一个词的并不是找一个合适的翻译就好了,无论是“置换”也好,“位移”也罢,并不能通过一个字面翻译就完整得传达这个技术点的原理。我希望大家在读过文章之后,说起displacement map,脑子里出现的并不是“位移”或是“置换”,而是这背后的运行于理论空间的模型,这样可能才不枉费花费的阅读时间。

当然,最后的最后,虽然这是一篇外文的翻译,也希望大家不要迷信外文,google有google的好,百度也有百度的便利。不做知乎口头王者,不做论坛洗地水军。多方参照、有自己的理论体系、有自己的坚持和思考才是学习的正确方法。

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值