Unity3D手游开发日记(4) - 适合移动平台的热浪扭曲

热浪扭曲效果的实现,分两部分,一是抓图,二是扭曲扰动.其中难点在于抓图的处理,网上的解决方案有两种,在移动平台都有很多问题,只好自己实现了一种新的方案,效果还不错.


网上方案1. 用GrabPass抓图

GrabPass在有的手机上是不支持的...效率也是问题,所以...

代码可以看看:

Shader "Luoyinan/Distortion/HeatDistortion" 
{
	Properties
	{
		_NoiseTex ("Noise Texture (RG)", 2D) = "white" {}
		_MainTex ("Alpha (A)", 2D) = "white" {}
		_HeatTime  ("Heat Time", range (0,1.5)) = 1
		_HeatForce  ("Heat Force", range (0,0.1)) = 0.1
	}

	Category 
	{
		Tags { "Queue"="Transparent+1" "RenderType"="Transparent" }

		Blend SrcAlpha OneMinusSrcAlpha
		AlphaTest Greater .01
		Cull Off 
		Lighting Off 
		ZWrite Off
	
		SubShader 
		{
			GrabPass 
			{							
				Name "BASE"
				Tags { "LightMode" = "Always" }
 			}

			Pass 
			{
				Name "BASE"
				Tags { "LightMode" = "Always" }
			
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#pragma fragmentoption ARB_precision_hint_fastest
				#include "UnityCG.cginc"

				struct appdata_t 
				{
					float4 vertex : POSITION;
					fixed4 color : COLOR;
					float2 texcoord: TEXCOORD0;
				};

				struct v2f 
				{
					float4 vertex : POSITION;
					float4 uvgrab : TEXCOORD0;
					float2 uvmain : TEXCOORD1;
				};

				float _HeatForce;
				float _HeatTime;
				float4 _MainTex_ST;
				float4 _NoiseTex_ST;
				sampler2D _NoiseTex;
				sampler2D _MainTex;

				v2f vert (appdata_t v)
				{
					v2f o;
					o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
					o.uvgrab = ComputeGrabScreenPos(o.vertex);
					o.uvmain = TRANSFORM_TEX( v.texcoord, _MainTex );
					return o;
				}

				sampler2D _GrabTexture;

				half4 frag( v2f i ) : COLOR
				{
					// noise effect
					half4 offsetColor1 = tex2D(_NoiseTex, i.uvmain + _Time.xz*_HeatTime);
					half4 offsetColor2 = tex2D(_NoiseTex, i.uvmain - _Time.yx*_HeatTime);
					i.uvgrab.x += ((offsetColor1.r + offsetColor2.r) - 1) * _HeatForce;
					i.uvgrab.y += ((offsetColor1.g + offsetColor2.g) - 1) * _HeatForce;
	
					half4 col = tex2Dproj(_GrabTexture, UNITY_PROJ_COORD(i.uvgrab));
					// Skybox's alpha is zero, don't know why.
					col.a = 1.0f;
					half4 tint = tex2D( _MainTex, i.uvmain);

					return col*tint;
				}

				ENDCG
			}
		}

		// ------------------------------------------------------------------
		// Fallback for older cards and Unity non-Pro
		SubShader 
		{
			Blend DstColor Zero
			Pass 
			{
				Name "BASE"
				SetTexture [_MainTex] {	combine texture }
			}
		}
	}
}

网上方案2:用RenderTexture来代替抓图

这种方法很坑爹,把场景再渲染一次?想想就很恐怖

我的方案: 后处理

换种思路,后处理其实就已经有了我们需要抓取的图,我们只需要渲染一个掩码图,就能实现局部的扭曲了,以前做次世代引擎的开发,很多特效都是后处理的实现的,比如人在水里面走水面泛起的涟漪,其实热浪扭曲也可以用类似的方法.


原理:

1.先用后处理实现全屏的扰动

Unity3D手游开发日记(4) - 适合移动平台的热浪扭曲_第1张图片

2.用RenderTexture做实时的掩码图.

Unity3D手游开发日记(4) - 适合移动平台的热浪扭曲_第2张图片

这样的话,效率开销只在两部分,一是后处理,二是把扭曲面片渲染到掩码图,

优化:

1.掩码图RenderTexture尽可能简单,关掉深度,抗锯齿等,用最简单的格式RenderTextureFormat.RGB565,黑白掩码图,不要alpha通道,掩码面片的shader可以用粒子的add shader

2.不需要扭曲的时候应该关闭掉扭曲用的后处理.不要一直开着.这个实现起来需要对掩码面片的存在有一个计数统计,才知道什么时候能关掉.

3.掩码图的比例一定要和屏幕保持一致,大小可设置为屏幕宽高的1/2或者1/4,


后处理的脚本:

Unity3D手游开发日记(4) - 适合移动平台的热浪扭曲_第3张图片

后处理shader:

Shader "Luoyinan/ImageEffect/HeatDistortion" 
{
	Properties 
	{
		_MainTex ("Base (RGB)", 2D) = "white" {}
		_NoiseTex ("Noise Texture (RG)", 2D) = "white" {}
		_MaskTex ("Mask Texture", 2D) = "white" {}
		_HeatTime  ("Heat Time", range (0,1.5)) = 1
		_HeatForce  ("Heat Force", range (0,0.1)) = 0.1
	}
	
	SubShader 
	{
		Pass
		{
			CGPROGRAM
			#pragma vertex vert_img
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			#include "UnityCG.cginc"
			
			float _HeatForce;
			float _HeatTime;

			uniform sampler2D _MainTex;
			uniform sampler2D _NoiseTex;
			uniform sampler2D _MaskTex;

			fixed4 frag(v2f_img i) : COLOR
			{
				// 为了效率,掩码图是黑白的,so...
				fixed mask = tex2D(_MaskTex, i.uv).r;

				// 扭曲效果
				half4 offsetColor1 = tex2D(_NoiseTex, i.uv + _Time.xz*_HeatTime);
				half4 offsetColor2 = tex2D(_NoiseTex, i.uv - _Time.yx*_HeatTime);
				i.uv.x += ((offsetColor1.r + offsetColor2.r) - 1) * _HeatForce * mask;
				i.uv.y += ((offsetColor1.g + offsetColor2.g) - 1) * _HeatForce * mask;

				fixed4 renderTex = tex2D(_MainTex, i.uv);
		
				return renderTex;
			}
	
			ENDCG
		}
	} 
	FallBack off
}



你可能感兴趣的:(unity3d,手游,移动平台,扭曲,热浪扭曲)