查看: 19|回复: 0

Unreal美术资源制作笔记 - Lens Flare特效

[复制链接]

6

主题

1

听众

51

积分

问题学生

Rank: 1

升级   25.5%

发表于 2021-2-23 15:09 |显示全部楼层
*Creation Date:1020
*Author:Erica
*Catalog:VFX; Material; Unreal4
*Abstract:Lens Flare;
Preface:

物理学原理和部分实现来自于YouTube视频:
有兴趣的朋友也可以查看原视频的讲解,会更清晰。
效果总览:

Lens Flare构成:

StarBurst(星型放射光)——星型的顶点数量取决于光圈的叶片数,光圈越小,星型的尖角就越明显(而且周围会出现光环)
Glow(光晕)——来自于成像表面的back-scattering反散射
Ghosts(鬼影)——鬼影的轮廓与光圈的形状一致
Streak(光束)——来自于电影拍摄中用的畸变镜头
Iris(色环)——畸变镜头副产物
*Lens Flare的轴线是光源和屏幕中心的连线,随着光源在屏幕空间的位置变化而变化
首先,根据原理,我们首先需要找到可见光源在屏幕上的位置,特意强调可见是因为在视角移动过程中,光源可能会被部分/完全遮挡,Lens Flare也应该根据这种情况产生变化,才能贴近真实世界的效果。
首先我们需要获得物体在屏幕空间的坐标,当物体在屏幕空间内范围需要在(-1,1)便于判断物体是否在屏幕内。使用ObjectPosition连接TransformPosition可以得到查看空间的坐标,但查看空间的坐标不等于屏幕坐标,要想得到屏幕坐标,我们需要得到物体视平面上的屏幕范围,再除以查看空间坐标。
要得到目前的物体视平面大小,可以通过0.5视场角的正切.x * z轴距离得到视平面1/2x轴宽度,y轴也可以这么处理。但是还有一种计算方式同样可以得到y轴的坐标,而且能够简化之后的计算:取得摄像机视野的宽高比,将y轴坐标乘以x/y来拉伸y轴坐标,使视野变成一个边长为x的正方形,那么处理视场角x轴的数据也就可以用于y轴了。
光源屏幕坐标计算当我们获得了物体(之后会被放在光源处)的坐标,我们就可以将之前提到的Lens Flare构成元素和效果添加到材质中。
StarBurst(星型放射光)

它具有的性质包括:形状、亮度、旋转角度、大小,这些属性用常规的UV操作就可以提升出变量了,具体实现如图所示,这里就不多赘述了。
除此之外,所有在粒子中的面片都需要和模型进行近远距离测试,避免穿帮
距离测试部分,输出到透明度节点
StarBurst等贴图还需要根据前景的遮挡进行一定变化,在这里我使用了深度差判断物体前方是否有遮挡物,如果有就将贴图缩小,直到完全消失。
Glow(光晕)

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

Ghost是以光源为中心,沿着光源与屏幕中心连线运动的两个伪影,且伪影与光源的距离同光源与屏幕中心的距离正相关,伪影的形状则与光圈形状匹配。
得到了这些信息之后我们就可以对伪影贴图在屏幕上的位置进行运算了:
首先得到屏幕中心与光源位置的连线,这根连线是穿过坐标原点的一次函数,上文计算出的ScreenPos就可以直接用于计算斜率,得到移动贴图时坐标的偏移单位向量(x,y),再通过将粒子位置与屏幕中心的距离向量长度乘以一个系数来调整伪影沿这个函数移动的距离,也就是将偏移单位向量拉伸。但是要注意,鬼影的偏移并非以屏幕中心为锚点,而是以粒子位置为锚点,于是我们叠加粒子的屏幕位置,就得到了Ghost贴图偏移的最终移动向量。
为了得到一对对称的Ghost,我们在第一步计算出偏移单位向量取反,以Add的方式将两个贴图叠加,Ghost的移动就完成了。
另外当我们观察真实的镜头眩光现象,会发现Ghost的大小也是与粒子-屏幕中心距离相关的,于是我们在Ghost贴图的UV计算上添加缩放系数,同样与粒子-屏幕中心距离正相关。
最后通过粒子-屏幕中心距离控制透明度的变化:越远离粒子中心透明度越低,Ghost的步骤就结束了。
Ghost坐标计算
Ghost贴图缩放 位移 颜色 透明度
Streak(光束)

光束部分分了两个内容,一个是细长的光束本体,另一个则是沿光束方向移动的伪影
首先光束的贴图本身是不随着粒子在屏幕上的位置进行位移的,它的变化形式是亮度,在粒子坐标远离屏幕中心的时候,光束最亮的部分向更靠近屏幕中心的一端移动,为此,我们采用了遮罩加强的方式,使光束高光部分能够较为平滑地融合,加强特定区域的亮度。
首先是遮罩的计算,遮罩是一个径向遮罩,它的半径和强度都是通过参来控制的,方便美术们调整效果,至于遮罩的平移,和Ghost很类似,只不过镜头的相对运动和遮罩UV的相对运动是相反方向的,但是由于遮罩只在光束方向,也就是x轴上运动,所以计算要相对Ghost更简单:
光束高光遮罩的计算
然后普通地将光束加强就可以了:
除光束主体外,我们还给光束部分添加了一点小装饰,类似于Ghost,但是只在光束方向移动的伪影:
伪影的偏移逻辑和Ghost是完全一样的,而且只用在x轴操作即可,相对来说更方便一些。
Iris(色环)

色环的计算是最复杂的,但是效果的想法很好理解,我们将光环分离成遮罩和贴图本体两个部分,遮罩负责制作随视角变化而以粒子为锚点旋转的动态,同时遮罩本身也会有宽度的变化,相当于单独圈定贴图的显示区域;而贴图本体负责彩虹光环的固有色,以及最为基础的消隐。
贴图本体的操作相对简单,所以先将这部分制作出来:
注:Iris部分的最左边VectorLength都是连接粒子屏幕位置的
贴图的缩放是与粒子的可见性相关的,上图里上面的IrisColor是使用曲线生成的彩虹光环,效果没有贴图这么好,但是会灵活一些,这里可以先不看上半部分,下面和RingSize进行插值的Alpha是粒子的深度,在被遮挡的过程中贴图会逐渐缩小式渐隐。
遮罩的情况就相对复杂很多,包括范围的圈定、旋转的循环、边界的羽化等等:
首先遮罩是一个不常规的图形,我的做法是将遮罩简化为两个简单图形,逐个计算再使用乘法将有效部分叠出来:
遮罩示意图
我们需要的是蓝色与红色重叠的部分,因此我们需要分别计算红色的环形和蓝色的扇形,相对来说我们就把问题简化了。之所以这样拆,是因为这两个部分可以单独负责遮罩的两个运动,这样在计算的时候就不容易混在一起,扇形负责旋转而环形负责缩放。
环形的缩放相对来说比较简单,所以我们先计算环形部分遮罩,使用sine就可以较为简单地计算出两边渐变羽化的环形选区了,而且由于我们的贴图本身就是环形的,容错率更高,所以用sine即使范围有些不合理也不容易出现视觉上明显的错误,比使用两个径向的椭圆套接计算量小一些:
注:Iris部分的最左边VectorLength都是连接粒子屏幕位置的
扇形部分我是从效果上进行推理的,为了准确描述一个扇形区域(这个扇形区域不需要半径的大小,因为环形已经控制了),我只需要扇形旋转的起始点,还有扇形的圆心角大小,因此倒推出我们需要一根中心轴,用来计算两个中心对称的部分,中心轴只需要提供斜率即可,那么我们可以用三角函数简单地从角度转换为直线斜率。至于扇形圆心角部分,直接开放给参数就可以了。
有一需要注意的地方,就是这个扇形需要在UV上没有断点、能够在理论上向一个方向无限旋转而数据不会溢出(简单粗暴地叠加角度肯定是不合理的),因此需要在计算角度的时候进行取余。
此外在计算的时候选择合适的算法也是很重要的,尽量不要使用反三角函数这种消耗很大的函数,有时候数学上合理的计算不一定适合计算机的处理,尤其是GPU的处理。
上半部分是普通的UV计算,使扇形的中心在UV中心,下半部分就是对角度的计算,轴向和扇形的角度最好在这里统一计算,方便后面的三角函数计算。
这里的思想是将单位圆被四条射线切割,同时利用中轴线和边界的距离作线性衰减,就可以做出羽化边界了,最后将遮罩与遮罩相乘、遮罩与贴图相乘,一个可以随着视角旋转的扇形光环就完成了。
到此为止,LensFlare的各个元素就制作完成了,但是为了能够在游戏里使用,还需要对它的可见性、整体效果进行一些处理。
整体效果主要包括距离显隐、距离缩放、可见性遮罩和可见性测试。
标记绿色的部分表示借鉴了其他大佬的做法,补充了在距离上的可见性、缩放变化
材质细节面板
此外还要记得将材质的混合模式以及着色模型改掉,由于我们自行进行了深度测试和消隐操作,就可以关掉自带的深度测试了,否则容易出现面片穿插的Bug。
效果参考:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

温馨提示:求助请到“Unity技术讨论”版块中发帖,便于集中解决!
您需要登录后才可以回帖 登录 | 立即注册

Unity游戏引擎开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2021-3-7 07:50 , Processed in 0.101168 second(s), 35 queries .