开发者遇到的典型美术相关问题回顾

[复制链接]
查看5308 | 回复9 | 2017-11-23 09:41:06 | 显示全部楼层 |阅读模式
本帖最后由 空白的灵魂 于 2017-11-23 10:00 编辑

我只是一个搬运工一下内容均为转发
Unreal Open Day 2017 活动上 Epic Games 开发者美术支持李文磊先生为到场的开发者做了名为"开发者遇到的典型美术相关问题回顾"的技术演讲,以下是演讲实录。
李文磊:大家好,我来自 Epic Games,我日常工作就是解决各个开发者的问题,特别是美术的问题,我想跟大家分享一下,我总结了一些问题,在今天跟大家过一下,我们可以一起看一下这个问题的表现是怎么样的,主要分析后面的原因,解决方法。

透明乱序问题
首先我想谈几个透明的问题,透明贴图透明材质的问题,因为透明的问题非常多,其中一个比较典型的是透明乱序的问题,它的表现大家都应该遇到过,就是透明物体和透明物体之间它的渲染有的时候在前,有的时候在后,根据移动会不断的变化。

所产生的原因是因为透明物体它不会被渲染到深度 buffer,大家可以看到左边的三个灰色的模型是不透明的物体,右边的三个彩色的是透明的物体,右边是一个深度 buffer,透明物体并没有在深度 buffer 中体现,没有深度就无法正确的排序,特别是象素级别的正确的排序。

UE4 提供了一些简单的方式,可以在物体的层级进行强制的排序,比如说我左边是一个正常的排序方式,红的最前面,绿的中间,黄的最后面,在 UE4 可以简单的设置它的排序的方式,我强制把黄色的渲染到了最前面,绿色的中间,红色的后面。
但是很多时候并没有那么简单,象素的级别我们很难做这样的排序和操作,比如这个烟雾的粒子特效,模型是片面组成的,一部分模型片面在后面,一部分在前面,这个时候我们就需要用一种比较迂回的方式。首先明确下,透明的排序问题基本上从 content 层面是没有什么好的解决方法,我们并不是试图去真正改变像素的前后排序,而是使用迂回的方式让其看起来没有乱序。比如说刚才水面上有雾效的例子,经常可以遇到,我们最简单的方式就是让烟雾在水面以下不画。首先先把这些雾渲染到所有的东西前面,用刚才提到的物体层级强制排序的方式。这样至少强行让所有的烟雾渲染到水面之上。
接下去需要解决像素级别的剔除。这里我做了一个简单的演示,这些面片就代表这些烟雾,平面就是水面,做了一个简单的 shader,在这 shader 里面拿到水面的高度。然后再  shader 里面我们做了一些交叉的地方的渐变,使用得到的黑白信息做 mask 来剔除掉水下的像素。


这是最终应用到实例上的演示。打开和没打开会有很大的差别,这是没有打开之前,打开以后,可以控制它的透明度以及上下,以及它的浓度。
但是在很多情况下没有仅仅是一个平面那么简单。比如说很复杂的一些透明的模型怎么样来做前后。一个种方式我们可以在材质里拿到透明物体的 PixelDepth,然后与一个非透明物体的 CustomDepth 比较来决定哪些像素该画,哪些不该画。

这里有一个球形。这里的关键是存在两个一模一样的球体,一个是非透明仅仅为了生成 CustomDepth (透明物体不能产生 CustomDepth,所以需要额外的非透明物体)。并且把非透明的那个球体 Disable Render to Main pass,然后使用上面的 shader 我们把面片模型的PixelDepth和球体产生的 CustomDepth 做比较,返回的值来产生球内黑色,球外白色的 Mask,有了这个 mask 我们可以剔除掉球背后的像素。
这种效果应用到实例上,比如应用到一个透明的人。左边的是穿透以后后面的面会被画出来非常难看,我们可以用刚才的方式做成右边的那样。


透明材质渲染开销问题
透明的另外一个问题就是效率,就是重复采样效率的渲染开销问题。因素一个是 shader 的复杂度,还有一个是 overlap 的数量,数量越多开销越大。
知道原因我们就可以很容易去寻找解决方法,即减少 shader 的复杂度以及减少重叠的几率。Shader 这块,受光与不受光(自发光)的 blend mode 开销差别非常大,所以对于一些蒸汽不需要光照的我们就让它自发光。减少 overlap 的努力我们可以从减少全透明区域的面积着手,我们提供一个 cutout 的功能,能够把自动判断贴图的边缘,把模型尽量的包裹贴图的 mask,这样使得面片的面积最小化,这样的作用就是让重叠的几率减小,可以减少开销。

外一个我们可以把透明物体的分辨率降低,这里有一个例子,我把它降成一半,减小透明填充和带宽的占用,减小开销,但是画面来看稍微模糊了一点,但是能接受的,有些时候你们可以用这样的方式大大减少透明物的开销。


透明的物体和背景之间的融合的效果
接下来关于透明的物体和背景之间的融合的效果问题,主要表现在背景过曝,缺少细节,透贴不干净等。
透明物体和背景在 Unreal 有多种的融合方式,我们就左边的贴图应用到右边的背景上面的效果来分析一下。
首先是一个 Additive 的效果,就是加上去的效果,经常用一些增量的效果。比如闪电,酷炫的法术等等,但是我们经常遇到就是背景非常亮的情况,产生过曝,贴图的细节就会丢失,就像右边白色背景的地方,基本上没有细节了。黑色的地方跟我原来的贴图是非常接近的,灰色的地方就是一半一半。

第二种是用 Translucent (透明)的混合模式,透明的混合模式可以很好的把需要透明的地方展现出来,但是半透明对于 aplha 通道的要求非常高,通道做得不好很有可能不是你需要的效果,或者透贴不干净,比如白色背景的地方前景可能会产生黑边,黑色背景的前景又可能会产生白边,对通道的品质要求很高。所以这里扣出来的效果不是很好,跟我们想象的不太一样。
还有一种模式是 Alpha  Composite 混合模式,就是用透明通道来控制背景被 add 的量,它的好处是什么?大家可以看到,在高亮背景上相对 additive 的混合模式是可以保留更多的细节,暗部也可以完全保留,另外就是不需要精确的 alpha 通道,我只要黑白灰,甚至它的 RGB 的通道就可以产生非常好的效果。

这里为进一步说明 Alpha  Composite 的工作原理,这是用透明材质来模拟 Alpha  Composite,基本上用背景的颜色和前景做一个加法再和本身的颜色做混合。
对于特效美术来说,有些时候可以考虑去使用这种混合模式来进行制作,来取得更好的透明前后景混合。(这是各个混合模式下透明效果放一起的比较)


漏光问题
接下来是几个漏光的问题,漏光有很多原因产生的,我想说动态的漏光,静态的相对原因单一,不在今天做讨论。
根据漏光现象分了以下几类:一个是影子没有贴合投射物,第二距离远了以后没有阴影;第三是动态的角色和静态的场景灯光不匹配;还有一个就是间接光的漏光,反射也是间接光的一种。

漏光问题:影子没有贴合投射物
动态影子没有贴合投射物,主要是三个原因,一个是影子本身的精度低了,第二个是影子的投射面积太大了,第三是影子偏移太大。
具体来看解决方法。对于影子本身的精度,首先我们要做的是调整影子相关的品质渲染 Scalability group 到最高等级,如果下图。这些可以直接使用 sg.shadowquality 4 来简单的达成
这样以后如果精度还达不到要求,我们需要根据使用的动态阴影类型来具体调整相关参数和设置。
对于 CSM Shadow 主要是阴影的距离和阴影的层级数。动图上大家可以看到默认情况下调整这两个参数以后的对比:

另外还有一个 per-object 阴影,和CSM不一样的,需要如下这些参数来进行调整,第一个主要是用来增加影子的精度的,UE4 里面对于动态影子有一个最小分辨率和最大分辨率,根据距离引擎会自动的调某一级的分辨率来显示,比如我在 100 米引擎调用 256 的精度,提高这个参数引擎可以调用更高级别精度;另外阴影最小分辨率设高,就可以强制使用更高的最小分辨率。

除了影子本身精度,刚才提到了影子投影的面积,类似投影仪一样,投到一百寸和三百寸,同样分辨率的画面在同样距离上三百寸更模糊,这是类似的。对于解决这个面积不同的光源有不同的方式
对于探照灯、聚光灯它的张角直接影响投射的面积,张角越小投射面积越小,所以小张角下同样的精度可以提高影子的精度。
对于点光源主要是一个距离,距离越近投射面积越小,精度越高。
对于直射光,物体的 bounds 越大影子的投射面积越大,因此也越模糊。所以尽量减小 bounds 的体积,增加精确度,贴合模型可以产生更高的阴影品质。
除此之外还有一些其他的方式,比如说阴影的一些滤镜,类似 PS 锐化的功能,这个只能适当的增加锐度;还有新增加的接触阴影,这个接触阴影是一种屏幕空间的阴影技术,非常小的细节的起伏没有足够的精度真实阴影的地方可以用这种阴影来表现。


漏光问题:远距离阴影消失产生漏光
接下来一个是刚才提到的距离拉远以后没有影子的问题,这个默认情况下是引擎的一种优化行为,在很远的距离不需要渲染,但是有的时候需要高品质或者影视级别的渲染 需要很远的距离,即使阴影在屏幕上已经很小,仍然希望被渲染。

在默认情况精度不够的情况我们可以通过一些方式调整,首先就是刚才提到过的  Scalability group,把阴影相关的 SG 设置到影视级。
但是这里相关的参数不是所有跟距离有关,这些参数是跟距离有关的。
r.Shadow.FadeResolution 控制影子在屏幕上到达一个什么样的分辨率时将会被渐隐掉;默认是 64,如果减小这个数值可以使得影子在更远的距离才被渐隐掉r.Shadow.RadiusThrehold 这个类似于上面的作用,是一个阈值,决定影子在这个阈值之下的大小将不会被渲染;减小这个阈值可以提高影子被渲染的距离。默认是 0.03,0.02 或者 0.01 可以大大提高远距离的阴影被渲染的距离 r.Shadow.DistanceScale 默认是 1, 更大的值将增加阴影开始渐隐的距离。
对于不同的阴影类型我们用不同的参数来解决远距离无阴影的问题。


漏光问题:室内动态角色受光与静态场景不匹配
另外一个经常碰到的就是动态物体和使用静态灯光的静态物体光照不能很好的衔接。这里的例子反映了角色(动态)同一环境下的室内要比静态物体亮。
这个问题主要是角色受到的间接光(来自 lighting Cache)并不精确造成的。也就是照明角色的 lighting cache 可能是来自室外而漏光了。解决方法是增加 lighting cache 的精度。在 build lightmass 的时候这些参数的调整可以提高这些间接光的精度。调整以后大家可以看到角色基本和场景光线可以匹配了

漏光问题:间接光漏光;反射漏光
下面是一个间接光的漏光,包括反射,因为反射也是间接光的一种。大家可以看到,这个场景,外面是一个太阳和一个天空,室内完全照不到太阳光,太阳没有直接照到这个物体上,物体仅受间接光照明,物体自身以及物体和房间之间都是没有任何的间接光光线的遮蔽的。

这是我们需要得到的效果,左边是自身的光线遮蔽,右边是这个物体和场景之间的光线的遮蔽。
问题的原因是引擎默认情况下为了效率是不开启间接光的遮蔽。
在最新的引擎版本中我们就场景物体加了一个 Distance Field indirectShadow,产生一个间接光的遮蔽,是使用物体的 DistanceField 来计算间接光的柔和阴影。另外我们可以通过材质给物体增加间接光自阴影,间接光的遮蔽。AO 的材质 input 仅对间接光会产生屏蔽,比如来自 lighting Cache 的照明,或者来自反射球的照明和反射;对于直接光是不具有屏蔽作用,因此效果更加接近物理实际。

这里我可以动态的在引擎里调整一些材质和阴影参数来增加和减少刚才说到的两种间接光阴影的量。
对于角色来说也可以投射间接光阴影,但是动画的物体是通过胶囊体作为投射的,而非 DiatanceField。如图这个是非常漂亮的阴影,特别是在完全无直接光的地方,有这些阴影人物更加立体,明确于周围环境的关系,否则无影子角色就像浮在空中一样,这图看上去对比很明显。

图像模糊和残影问题
接下来的一个常见问题,就是残影。因为在 UE 里我们默认使用的是一种 TAA 抗锯齿的方式,它的原理基本上就是在渲染的时候把每帧图像做一些次像素级别的小抖动,在最后合成,如果图像细节量特别大在 TAA 努力抹平锯齿的过程中就会产生瑕疵,这种瑕疵就是这里看到的运动的时候产生的残影。
我可以减小法线贴图的强度;改变 Mipmap 的算法,我们提供了很多的算法,比如这种情况我用一些比较模糊的算法来减少。另外 SSR 反射以及 SSAO 这些其实在 TAA 情况都会加剧这种问题,所以一旦遇到这些问题,大家可以一个一个的分析排除,主要是我提到的前面三个,其他的大家可以察看一下。

画模型的法线问题
模型动画的法线问题,特别是做面部动画的时候,这一看就知道是在动画以后它的法线产生的问题,因为法线在没有闭眼是朝上的,闭眼以后还是朝上的,这是引擎默认的行为,骨骼模型动画并不实时根据周边法线更新;在做前期动画的时候,我如果骨骼带动了那些点,骨骼是移动的,而不是旋转的,它没有一个旋转的信息传达给法线,所以这些法线是不知道骨骼是旋转的,直接骨骼往下拉就会产生这些问题。

这是原理图,上边是 MAX 里,直接移动骨骼,蓝色得法线是会更新的,下边是 UE 默认情况是不动的,所以产生了那种变黑的问题。
目前的解决方法比较简单的就是我们可以使用 SkinCache,把信息放到 Skin cache 里面,默认是不打开的,我们引擎不是所有的功能都非常完善,大家提问题也是改进我们引擎的机会,所以比如说像这些东西一开始是一个实验性的功能,然后根据开发者的反馈不断的改进,我相信以后放在一个 UI 里勾一个标签就可以了。目前需要把以下的变量加入到ConsoleVariables.ini 里重启编辑器,然后勾选相应 skeletalmesh 下的 Recompute Tangent 即可。

另外就是使用一些其他方式,比如用 Morph Target,还有 Alembic 点缓存形式,还有做动画的时候,尽量的旋转,而不是直接拖拉骨骼,在做角色动画的时候因为大部分只是旋转而已,但是面部动画很多时候很方便是拖动而已。

动画在某些时刻与外部软件中不一样
接下来的问题就是动画在外部软件里跟看到的,比如 max 里,与动画导入 UE4 后看到的不太一样,尤其在动画速度非常快的时候,或者摄像机动画。
原因这里提到两点,一个就是动画插值与不插值会产生失真;第二个是关键帧数据丢失。我们看一下这两张图,左边我在 Max 做一个动画,导入引擎以后所有的动画都以四分之一的速度播放,我们引擎里渲染的 FPS 很快,而且是不固定的,根据你机器不同,播放的时候都会在关键帧之间做线性插值。UE4 中在表现关键帧间的动画位置时会默认使用线性的插值,当两个关键帧上动作的位置差别很大时,插值的准确性就降低,尤其在速度快的动画上,这种差别有时候会非常大
比如这个球是绕着这个环转的,但是有时候有一点偏,那是因为插值精度的问题。如下图,绿色是 MAX 里的效果,导入 UE4 后(红色)经过关键帧插值后的播放效果,可以看到在关键帧之间球的位置虽然是顺滑的,但有些失真,与圆环是有小偏差的。
另外一个原因是关键信息丢失。绿色是 Max 里面 60 帧每秒,每个奇数帧上移了一个单位,所以大家可以看到,转的时候还在跳动,导入 UE 后(红色) 这些就没有了。
如果结果对于插值精度敏感,我们需要来解决这个问题。知道原因解决就方便了,首先可以不要插值,我把这个插值 关掉,就跟播放器里面的一样;另外对于输出动画的帧率,我可以使用用固定的帧率渲染/输出,比如 30 帧的 Frame 也会产生最终的不插值的效果,可以解决这个问题。
另外一个原因是关键帧信息丢失。绿色是 Max 里面 60 帧每秒,每个奇数帧上移了一个单位,所以大家可以看到,转的时候还在跳动,导入 UE (红色) 这些就没有了,因为用了 30 帧每秒的帧率重采样,所有的奇数帧就被丢掉了。为了确保不失真, 高帧率动画导入引擎如果使用 30 帧重采样,这些关键帧动画就要在偶数帧上可以被采样到的地方。
解决方式是导入的时候不重采样,截图说明了在导入导出的时候的设置来避免重采样。


反射球的消耗问题
关于反射球消耗的问题,我们有两种反射捕捉 capture,盒子形状的以及球型的。反射球的消耗大的地方是重复采样的地方,就是反射球的边缘半透明的地方。我们可以把它理解成跟透明物体一样,全部不透明的地方其实消耗是固定的,半透的地方重采样次数越多开销越大。为了证实这一点我把很大的反射球笼罩到很小的地面上,这块地面所有的地方都是百分之百的反射,但是我放了 28 个反射球,只有一个反射球的开销,因为只有一个采样。
如果我把这 28 个移到旁边的地方,让半透明的地方进行混合,它就会大大增加开销,因为被重采样了几十次。
理解这个原理以后这里有一个模拟的图大家可以知道这些反射球之间怎么样越亮的地方是开销越大的,首先看怎么减少开销,减少个数有时候精度不够高,所以怎么样避免边缘的地方的重叠才是关键,比如说我用方形的其实这些边缘的地方就比较容易避免重叠,因为方形容易控制边界,圆形的比较难,另外可以先放一个大的,再放几个小的,总之你知道原理以后其实很容易自己去根据实际情况避免重采样开销。
动画序列输出合成问题
现在很多的开发者特别是做影视的遇到一个问题,最终输出的画面和输出的通道不能很好的合成到一块。最终画面是抗过锯齿的,但是其他通道未抗锯齿的。
这个原因是最终画面是做了 TAA,G-buffer 是没有经过最终 TAA。为了 TAA 做准备, G-buffer 会在次像素做一个抖动,然后在最终的后期里通过这些抖动才能做合成的抗锯齿。但是如果我们直接输出没有最终合成的经过抗锯齿的 G-buffer,大家就能看到如视频上那样的抖动效果。

解决方法就是我们把 G-buffer 做一下 TAA 然后再输出。在后期的材质中拿到 G-buffer 并把它放到 Tonemapping 前去处理,这样最终的输出会经过 TAA。然后把的这些 PP 的材质我们可以应用 postprocess volume 里或者输出面板中 postprocess material 指定框中起作用。

其实引擎自带了一些 buffer 的可视化后期材质,大家可以去这个路径下找到,新的版本里这些 buffer 的预览材质都已经做了 TAA,之前是没有的,最近我发现都做了,所以这些大家可以去参考一下甚至可以直接拿来用。

关于寻找答案
以上这些就是我今天想跟大家过的常见的问题,最后我想提一下关于寻找答案,怎么自己解决问题。首先我们有一个范例场景大家也许都知道,从我工作接触的情况来看也有很多的人不知道。我们范例场景是一个项目,里面有几十张地图,每个地图里把引擎某块功能都以实例的方式列出来;对于美术,文字描述再多也不如实际的范例来的直观,建议大家下载学习。
第二个是搜索,大部分的问题大家都可以搜到,因为很多的问题别人都遇到过,但是搜索关键是需要搜索恰当的关键词,这个很重要。所以我建议大家能用英文关键词搜索就用英文关键词,如果一定要用中文,可以去查一下我们文档里英文翻译过来是什么中文,基本全球范围遇到问题的人肯定比国内要多,因此有更多的几率搜到答案。
另外一个是官方的博客和视频,我自己也经常看会更新最新的东西,比如最新我们更新的 Tonemapping 的算法,一更新很多人就抱怨说我这些颜色都不一样了,我们就马上放出来一个视频解释它的原理,为什么要这样做等等;最近又放出了一些照片级别的角色的制作素材。
最后一个是提问方式;这个是关系到解决问题的效率,比如说你提供的时候提供足够的信息,重复步骤版本号,反复的时间就会减少。 谢谢。


评分

参与人数 2能量币 +20 收起 理由
letian100 + 10 很给力!
MAX-萨 + 10 很给力!

查看全部评分

squallsanke | 2017-11-23 10:38:34 | 显示全部楼层
好东西,支持支持
回复 支持 反对

使用道具 举报

黑白Black | 2017-11-23 11:16:43 | 显示全部楼层
少有的营养贴,楼主太有心了,感谢感谢
回复 支持 反对

使用道具 举报

洋无敌 | 2017-11-23 15:08:37 | 显示全部楼层
学习了 open day 学了一下 讲太快没太理解 谢谢了
回复 支持 反对

使用道具 举报

被动怪 | 2017-11-30 10:26:28 | 显示全部楼层
真心不错!!!
回复

使用道具 举报

TC王者 | 2017-12-14 14:26:38 | 显示全部楼层
我一定是用了假的UE4
回复 支持 反对

使用道具 举报

letian100 | 2018-1-17 20:44:29 | 显示全部楼层
感谢灵魂版主,辛苦辛苦。感谢为大家带来这么多
回复 支持 反对

使用道具 举报

hyc8898 | 2018-1-17 22:10:47 | 显示全部楼层
本帖最后由 hyc8898 于 2018-1-17 22:11 编辑

人世间竟有如此好文,长见识了
回复 支持 反对

使用道具 举报

teatimeif | 2018-1-29 13:01:42 | 显示全部楼层
太有用了 Mark
回复 支持 反对

使用道具 举报

墨丶羲 | 2019-4-17 17:46:11 | 显示全部楼层
楼主辛苦了,真的很有用的东西。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

39

主题

183

回帖

3002

积分

初始化成员

积分
3002

初阶编码勋章创阶使勋章无常勋章高阶编码勋章架构师勋章