效果拆解

【UE4】赛博朋克2077场景扫描推进效果 来自深夜小编 CG文章_CG资源

效果拆解


*文章授权转自微信公众号【包小猩CG杂货店】


好像又鸽了半年没发东西(来自一位年更UP的喃喃自语)


言归正传,2077出来也有一个多星期了,在游玩时发现有许多效果做得很棒,特别是按tab扫描时,推动鼠标滚轮会有马赛克过渡的效果,好像图片传输速度很慢,被一层层加载出来一样。话不多说先看游戏内效果:


效果拆解


接下来我们进行效果拆解。在做任何效果之前都需要进行拆解,这样才能明确方向。我决定从颜色元素和动画三个方向进行拆解,这样做就更有条理,确保不会漏细节。大家对照脑图和上面的动图一起食用,应该可以get到我总结的这些部分。



下面我们根据总结的要点展开讲解。



效果制作


在正式讲解之前我想让大家看看我最后实现的效果



1.像素化处理

整个效果中最重要的也是最明显的部分,就是不同大小的像素过渡。在这里,我选择使用最大64x64的像素作为首次像素化的尺寸,然后不断细分像素大小,由 64x6 4变成 32x32 ,再到16x16,以此类推下去,最终显示出原始图片。(效果上有点像四叉树)



由于像素化制作很简单,直接上节点图(这里将功能写成material function):(对像素化制作不清楚的同学可以看这篇文章:#像素艺术# - 使用UE4还原CRT像素效果的思路及方法


UnitResolution:像素化一个区域的分辨率

这套节点主要思路就是将屏幕像素划分给定像素化大小的区域,然后添加半个像素的宽度来修复floor的偏移(像素化的画面就会和原始图像对齐)


于是我们就能得到如下所示的画面


单元格分辨率:64x64


单元格分辨率:32x32

单元格分辨率:16x16


通过修改像素大小可以得到不同分辨率的结果,这也是画面像素细分后的层级效果。由于像素大小是不断二分的,所以上一层级的像素内刚好能装下4个下一层级的像素块,以此类推最后一层就为原图



2.像素化动画

接下来我们要将不同分辨率的图像混合起来,实现从中心到外围的像素大小渐变。画面中心为小像素块,画面外围为大像素块,如下图所示:



但是单纯这样一张图显然是不够的,我们需要让他动起来。制作动画的大致思路就是先制作n层不同细分的像素化效果,然后对每个层级制作动画偏移并混合。这样不同层级出现会有先后顺序,就能实现从中心扩散,且不断细分的动画效果。

我们首先着手中心向外扩散的效果,使用spheremask最适合不过了,但在spheremask之前我们需要对像素化的uv做一些细节操作。


首先是对uv做屏幕的长宽比修正,因为我们希望不管屏幕比例为多少,最后的扩散区域都是圆形。修复原理主要是对uv做了屏幕比例的反向修正,节点图如下:



左端输入像素化uv,右端输出修正长宽比的uv



然后我们将制作好的uv应用spheremask,并添加两个float输入:Process和ProcessBias,分别控制整体效果 进度 和 进度偏移



随后我们在外层按照不同分辨率排布n个刚刚写好的像素化功能,再将每层的ProcessBias调整下,混合输出的mask通过调整process即可得到如下动图效果


可以看到现在已经有多层不同分辨率的层级混合了,但混合的边缘太过于规整,于是我们需要用一张noise贴图进行扰乱,这张noise我选择使用bluenoise,因为得到的效果较为均匀。

这张noise其实也不是单纯的一通道灰度noise,我使用了两个通道,这两个通道中储存了不同的blue noise,然后我用这张noise的红绿通道,对像素化后uv的x和y轴做了随机效果(如果只使用一张噪波对两个轴向做noise的效果很容易得到具有方向性偏移的结果)。




可以看到蓝色框内的是Noise节点部分。这里需要注意的是,Noise 需要做一下范围映射再和 UV 混合,映射操作将 Noise 本身 0-1 的区间变成 -1 - 1 的区间。目的是为了在轴的正反都有随机位移,使结果更加随机,而不会出现方向性



接下来我们只需要控制 Process 数值即可实现从中心扩散的动画效果了。


但 Process 取值的区间是 0-1 吗?


很显然不是的。这里有个细节需要说明,由于每个层级都做了Process Bias的进度偏移,所以我们的 Process 进度数值需要满足最大偏移层的进度完成(最大偏移层就是拥有最大 Process Bias 值的像素化层),具体计算需要将 process 的 0-1 区间变成 “0” 到 “1+最大Bias” 区间,计算过程如下图所示



做到这里我们可以得到如下的动画效果:


3.扫描描边加亮

如果仔细观察原图可以发现,在物体边缘和画面高亮部分会有一层描边,如下图所示:



这里我选择采用 画面高亮区域 混合 深度描边 实现这个效果。深度描边我只采用屏幕 V 轴方向偏移,偏移大小为 0.5 个当前层级像素宽度,这样做的好处是描边会出现不连续的断开,效果呈现较为随机。


画面高亮区域:



 在节点中有个进度权重输入是之前没有提及的,在这里解释一下:因为描边在整个进度范围内肯定不是统一的,在原图中观察得出进度开始时最亮,进度最后会慢慢变暗。所以我在这里用每层不同单元格大小计算分配了权重,节点如下图所示:


可以看到当单元格为最大值64时,权重为1,单元格为32时权重为1/2,单元格16时权重为1/4。以此类推,最后一层的单元格权重为1/64。这样就能完美控制每个层级的描边亮度权重,非常好用。

细心的朋友可能会发现在节点中,进度权重后面Pow了一个0.25。这是为了让整个权重变化幅度放缓,在实际使用中可以将 0.25 变成参数供调整。


注:从左到右依此为4个层级的描边,可以看到亮度是逐级递减的


这样通过控制亮度变化,整个动画层次感会大大提高。


深度描边区域:



BaseWeight:上面介绍的随进度变化的权重,但这里我在后面添加了一个 cosine ,让整个权重发生了变化,因为 深度描边是开始和结束时很暗,中间层级很亮



SlightlyScale:非常细节的像素动态追赶调整,后续会详细分析

SkyMask:距离Mask,在一定距离之后描边就不显示了

BiasedUV:计算描边使用的偏移后的UV

DepthEdge:描边计算部分

深度描边我采用了最常规的制作方法,拿到场景深度只计算屏幕v方向偏移描边。

这里需要提及的是,我在深度描边中加入了暗角权重,也就是屏幕中心的深度描边会亮些,周围的会变暗,节点写在DepthEdge下面,可以看到我做了一个乘1.414的操作,这是为了让计算暗角的四周最大值为1,方便后续的1减操作。

而1.414这个值也不是Magic Number,是1除根号0.5的结果,至于为什么要这样算就留给大家自己思考了,其实就是最简单的三角函数计算。


最后结果如下所示:


深度描边(开始和结束较暗,中间阶段变亮)


画面较亮区域描边(亮度不断变暗)


刚刚说到节点中有个叫SlightlyScale的东西,这个究竟是干什么用的呢?我们先来看两张对比动图




画面较亮区域描边(亮度不断变暗)

刚刚说到节点中有个叫SlightlyScale的东西,这个究竟是干什么用的呢?我们先来看两张对比动图


SlightlyScale原理其实非常简单,就是将画面根据像素化进度往画面中间缩放,0.95为第一层级的缩放,1为最后一层级的缩放。lerp下方连入的部分为上面描边部分提及的BaseWeight。


4.细节部分

接下来就是细节部分了,主要设置了角色蓝图中的摄像机推镜动画,以及对上文制作的像素化后处理材质进行切换



最后在后处理材质中添加一张ui。其实这里做Widget会更好,因为懒所以没做(记得这里要对图像做长宽比的修复,最后的长宽比应该是屏幕长宽比和图片长宽比共同作用的结果)





5.总结


看到这里,是不是发现看似复杂的效果,实现起来却异常简单。


其实有时候,作为一名 TA 不一定非要写多牛逼的算法、抄多 dio 的论文、码多晦涩难懂的 code 显得自己多牛逼。反而些最不起眼最普通的效果如果有能力完成一套完整出众技术解决方案,达到最高品质同时满足各方需求,这才是王道也许这套东西并没有用到多牛逼的技,但~


Who Cares?



发现写文章比做东西的时间都要长,效果做了一天,写文章却用了两天。。。所以还请大家多多支持点赞关注转发,你的支持就是我更新的动力!!




*文章授权转自微信公众号【包小猩CG杂货店】

加载中