【转载】UE4 美术资源制作笔记 - Lens Flare 特效

615 阅读10分钟

原文链接: UE4 美术资源制作笔记 - Lens Flare 特效 | 鲨莉叶

Creation Date:1020
Author:Erica
Catalog:VFX; Material; Unreal4
Abstract:Lens Flare;

Preface:

物理学原理和部分实现来自于 YouTube 视频:

Lens Flares [2]. How to implement in Unity

有兴趣的朋友也可以查看原视频的讲解,会更清晰。

效果总览:

  • Unreal Lens Flare - Overview

ue_512.gif

Lens Flare 构成:

  • StarBurst(星型放射光)—— 星型的顶点数量取决于光圈的叶片数,光圈越小,星型的尖角就越明显(而且周围会出现光环)
  • Glow(光晕)—— 来自于成像表面的 back-scattering 反散射
  • Ghosts(鬼影)—— 鬼影的轮廓与光圈的形状一致
  • Streak(光束)—— 来自于电影拍摄中用的畸变镜头
  • Iris(色环)—— 畸变镜头副产物

Lens Flare 的轴线是光源和屏幕中心的连线,随着光源在屏幕空间的位置变化而变化

首先,根据原理,我们首先需要找到可见光源在屏幕上的位置,特意强调可见是因为在视角移动过程中,光源可能会被部分/完全遮挡,Lens Flare 也应该根据这种情况产生变化,才能贴近真实世界的效果。

首先我们需要获得物体在屏幕空间的坐标,当物体在屏幕空间内范围需要在(-1,1)便于判断物体是否在屏幕内。使用 ObjectPosition 连接 TransformPosition 可以得到 查看空间的坐标 ,但查看空间的坐标不等于 屏幕坐标 ,要想得到屏幕坐标,我们需要得到 物体视平面 上的 屏幕范围 ,再除以 查看空间坐标

要得到目前的 物体视平面大小,可以通过 0.5 视场角正切.x 分量 乘上 z 轴距离 得到视平面 x 轴的 1/2 宽度y 轴也可以这么处理。但是还有一种计算方式同样可以得到 y 轴的坐标,而且能够简化之后的计算:取得摄像机视野的 宽高比 ,将 y 轴坐标乘以 x/y 来拉伸 y 轴坐标,使视野变成一个边长为 x正方形 ,那么处理视场角 x 轴的数据也就可以用于 y 轴了。具体如下图所示。

  • 光源屏幕坐标计算

image.png

当我们获得了物体(之后会被放在光源处)的坐标,我们就可以将之前提到的 Lens Flare 构成元素和效果添加到材质中。

StarBurst(星型放射光)

它具有的性质包括:形状亮度旋转角度大小,这些属性用常规的 UV 操作就可以提升出变量了,具体实现如图所示,这里就不多赘述了。

image.png

除此之外,所有在粒子中的面片都需要和模型进行 近远距离测试 ,避免穿帮

  • 距离测试部分,输出到透明度节点

image.png

StarBurst 等贴图还需要根据 前景的遮挡 进行一定变化,在这里我使用了 深度差 判断物体前方是否有遮挡物,如果有就将贴图缩小,直到完全消失。

image.png

Glow(光晕)

与光晕表现有关的要素主要是 光源是否在视野范围内 ,但是在从视野范围内远离时,光晕需要渐变消失的过程,因此添加了一个 Out of View Fade Range,用来线性地控制光晕在远离屏幕后的渐隐,此处主要是通过 缩小光晕贴图 来表现渐隐。

image.png

以及常规 UV 操作:

image.png

Ghosts(鬼影)

Ghost 是 以光源为中心,沿着光源与屏幕中心连线运动的两个伪影,且伪影与光源的距离同光源与屏幕中心的距离正相关,伪影的形状则与光圈形状匹配。

得到了这些信息之后我们就可以对伪影贴图在屏幕上的位置进行运算了:

首先得到屏幕中心与光源位置的连线,这根连线是穿过坐标原点的一次函数,上文计算出的 ScreenPos 就可以直接用于计算斜率,得到移动贴图时坐标的偏移单位向量 (x,y),再通过将 粒子位置与屏幕中心的距离向量长度 乘以一个系数来调整伪影沿这个函数移动的距离,也就是将 偏移单位向量 拉伸。但是要注意,鬼影的偏移并非以屏幕中心为锚点,而是以粒子位置为锚点,于是我们叠加粒子的屏幕位置,就得到了 Ghost 贴图偏移的最终移动向量。

为了得到一对对称的 Ghost ,我们在第一步计算出偏移单位向量取反,以 Add 的方式将两个贴图叠加,Ghost 的移动就完成了。

另外当我们观察真实的镜头眩光现象,会发现 Ghost 的大小也是与 粒子-屏幕中心距离 相关的,于是我们在 Ghost 贴图的 UV 计算上添加 缩放系数 ,同样与 粒子-屏幕中心距离 正相关。

最后通过 粒子-屏幕中心距离 控制透明度的变化:越远离粒子中心透明度越低,Ghost 的步骤就结束了。

  • Ghost 坐标计算

image.png

  • Ghost 贴图缩放 位移 颜色 透明度

image.png

Streak(光束)

光束部分分了两个内容,一个是细长的光束本体,另一个则是沿光束方向移动的伪影

首先光束的贴图本身是不随着粒子在屏幕上的位置进行位移的,它的变化形式是亮度,在粒子坐标远离屏幕中心的时候,光束最亮的部分向更靠近屏幕中心的一端移动,为此,我们采用了遮罩加强的方式,使光束高光部分能够较为平滑地融合,加强特定区域的亮度。

首先是遮罩的计算,遮罩是一个径向遮罩,它的半径和强度都是通过参数来控制的,方便美术们调整效果,至于遮罩的平移,和 Ghost 很类似,只不过镜头的相对运动和遮罩 UV 的相对运动是相反方向的,但是由于遮罩只在光束方向,也就是 x 轴上运动,所以计算要相对 Ghost 更简单:

  • 光束高光遮罩的计算

image.png

然后普通地将光束加强就可以了:

image.png

除光束主体外,我们还给光束部分添加了一点小装饰,类似于 Ghost ,但是只在光束方向移动的伪影:

image.png

伪影的偏移逻辑和 Ghost 是完全一样的,而且只用在 x 轴操作即可,相对来说更方便一些。

Iris(色环)

色环的计算是最复杂的,但是效果的想法很好理解,我们将光环分离成遮罩贴图本体两个部分,遮罩 负责制作随视角变化而以粒子为锚点旋转的动态,同时遮罩本身也会有宽度的变化,相当于单独圈定贴图的显示区域;而 贴图本体 负责彩虹光环的固有色,以及最为基础的消隐。

贴图本体的操作相对简单,所以先将这部分制作出来:

image.png

注: Iris 部分的最左边 VectorLength 都是连接粒子屏幕位置的

贴图的缩放是与粒子的可见性相关的,上图里上面的 IrisColor 是使用曲线生成的彩虹光环,效果没有贴图这么好,但是会灵活一些,这里可以先不看上半部分,下面和 RingSize 进行插值的 Alpha 是粒子的深度,在被遮挡的过程中贴图会逐渐缩小式渐隐。

遮罩的情况就相对复杂很多,包括范围的圈定旋转的循环边界的羽化等等:

首先遮罩是一个不常规的图形,我的做法是将遮罩简化为两个简单图形,逐个计算再使用乘法将有效部分叠出来:

  • 遮罩示意图

我们需要的是蓝色与红色重叠的部分,因此我们需要分别计算红色的环形和蓝色的扇形,相对来说我们就把问题简化了。之所以这样拆,是因为这两个部分可以单独负责遮罩的两个运动,这样在计算的时候就不容易混在一起,扇形负责旋转而环形负责缩放。

环形 的缩放相对来说比较简单,所以我们先计算环形部分遮罩,使用 sine 就可以较为简单地计算出两边渐变羽化的环形选区了,而且由于我们的贴图本身就是环形的,容错率更高,所以用 sine 即使范围有些不合理也不容易出现视觉上明显的错误,比使用两个径向的椭圆套接计算量小一些:

image.png

注: Iris 部分的最左边 VectorLength 都是连接粒子屏幕位置的

扇形 部分我是从效果上进行推理的,为了准确描述一个扇形区域(这个扇形区域不需要半径的大小,因为环形已经控制了),我只需要扇形旋转的起始点,还有扇形的圆心角大小,因此倒推出我们需要一根中心轴,用来计算两个中心对称的部分,中心轴只需要提供斜率即可,那么我们可以用三角函数简单地从角度转换为直线斜率。至于扇形圆心角部分,直接开放给参数就可以了。

有一需要注意的地方,就是这个扇形需要在 UV 上没有断点、能够在理论上向一个方向无限旋转而数据不会溢出(简单粗暴地叠加角度肯定是不合理的),因此需要在计算角度的时候进行取余

此外在计算的时候选择合适的算法也是很重要的,尽量不要使用 反三角函数 这种消耗很大的函数,有时候数学上合理的计算不一定适合计算机的处理,尤其是 GPU 的处理。

image.png

上半部分是普通的 UV 计算,使扇形的中心在 UV 中心,下半部分就是对角度的计算,轴向和扇形的角度最好在这里统一计算,方便后面的三角函数计算。

image.png

这里的思想是将单位圆被四条射线切割,同时利用中轴线和边界的距离作线性衰减,就可以做出羽化边界了,最后将遮罩与遮罩相乘、遮罩与贴图相乘,一个可以随着视角旋转的扇形光环就完成了。

到此为止,LensFlare 的各个元素就制作完成了,但是为了能够在游戏里使用,还需要对它的可见性、整体效果进行一些处理。

整体效果主要包括 距离显隐距离缩放可见性遮罩可见性测试

image.png

标记绿色的部分表示借鉴了其他大佬的做法,补充了在距离上的可见性、缩放变化

  • 材质细节面板

此外还要记得将材质的 混合模式 以及 着色模型 改掉,由于我们自行进行了 深度测试消隐操作 ,就可以关掉自带的深度测试了,否则容易出现面片穿插的 Bug 。

效果参考:

▼[UE4] Marketplace - Custom Lens Flare VFX - Overview