效果一览
实际生活中,空气热扰动是一种空气受热不均造成的一种物理现象,用在游戏中能充分增强画面质感,如用在火焰,炎热天气下的柏油马路上,突出炙热感
基本原理
生成当前背景纹理,利用mask面片在相应位置采样该背景纹理,采样的uv利用噪声进行扰动,达到采样结果与原背景纹理相比呈现出不规则错位的效果,既热扰动效果
具体实现
我将在Unity中实现该效果,具体有两种思路
- 在mask面片的shader中用GrabPass抓取当前背景纹理,计算mask面片的屏幕坐 标,采样噪声去扰动该屏幕坐标,并用该屏幕坐标采样背景纹理。优点是操作简单,
缺点就是GrabPass在移动设备上性能较差
- 利用CommandBuffer绘制mask面片,利用_CameraDepthTexture对mask面片进行深度测试并将最后结果渲染到纹理,随后进行热扰动全屏后处理,在后处理shader中采样mask纹理实现指定区域的热扰动。后处理中使用的OnRenderImage()中的Graphic.Bilt()性能表现优于GrabPass,但对于移动设备来说仍是一笔不小的负担。
第一种实现(GrabPass)
空间布局如下:
Mask为Unity新建的quad,Mask的Shader为:
Shader
_Mask为我在ps里制作的黑白遮罩图
新建quad,重命名为Mask,将带有该shader的材质赋予该Mask,拖入噪声贴图,遮罩贴图,调整数值,即可看到效果
第二种实现(全屏后处理)
界面布局与之前相同,先编写一个后处理基类,用来处理各种后处理的基本生成
PostEffectBase.cs
using
再编写一个扰动后处理类,继承上基类,实现具体实现细节
DistortionEffect.cs
using
负责热扰动后处理的shader如下,基本原理和上文相同:
Shader
本文较为关键的点来了,利用CommandBuffer将Mask面片放在CameraEvent.AfterForwardOpaque之后,OnRenderImage之前渲染,渲染该面片时,利用_CameraDepthTexture为该面片进行自定义深度测试,为的是在后处理之前获得该mask面片的正确遮挡关系,利用该面片确定后处理范围。
CommandBufferForDistortMask.cs如下,该脚本挂载在mask面片上:
using
而mask面片的shader如下,实现了一个基本的公告牌以及自定义深度测试:
Shader
将DistortionEffect.cs挂载至相机,将负责热扰动后处理的Custom/Distortion(PostEffect)拖至其“后处理着色器”选项,将噪声纹理拖至其相应选项。
设置mask的shader为Custom/DistortionMask(BillBoard),并在检视面板更改其Layer属性,配合相机的CullingMask,使得相机在正常渲染时不会渲染mask面片,该面片将会通过commandbuffer自定义渲染。
效果完成,你可以加一个box去遮挡热扰动观察效果