效果一览
实际生活中,空气热扰动是一种空气受热不均造成的一种物理现象,用在游戏中能充分增强画面质感,如用在火焰,炎热天气下的柏油马路上,突出炙热感
基本原理
生成当前背景纹理,利用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 "Custom/Distortion(GrabPass)"
{
Properties
{
_DistortStrength("热扰动强度",Range(0,1)) = 0.5
_DistortVelocity("热扰动速率",Range(0,1)) = 0.5
_XDensity("噪声密度(水平)",float) = 1
_YDensity("噪声密度(竖直)",float) = 1
_NoiseTex("噪声贴图",2D) = "white"{}
_Mask("噪声遮罩",2D) = "Black"{}
}
SubShader
{
Tags{
"RenderType" = "Transparent"
"Queue" = "Transparent+1"
"DisableBatching"="True"//批处理会合并模型,造成物体本地坐标丢失,公告牌效果失效,所以忽视批处理
}
Zwrite Off
GrabPass{
"_GrabTex"}//获取当前屏幕图像,并存入_GrabTex纹理
Cull Off
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
float4 pos : SV_POSITION;
float4 grabPos : TEXCOORD0;
float4 uv : TEXCOORD1;
};
sampler2D _GrabTex;
sampler2D _NoiseTex;
sampler2D _Mask;
float _XDensity;
float _YDensity;
float4 _NoiseTex_ST;
fixed _DistortStrength;
fixed _DistortVelocity;
v2f vert (appdata_base v)
{
v2f o;
//公告牌实现&#