U3D Distortion

我们的美术希望游戏可以更炫一点,想在刀光特效上加上空气扭曲的效果,就是类似燃烧的火焰上方空气扰动的那种效果。这个效果其实很多游戏都有。网络上流传的有一个叫heat_distortion的shader,这个shader使用grabTexture实现的,实现方法很多人都讲过,这里就不细说了。grabTexture比较坑爹,在移动设备上效率很成问题,而且有些机型也不支持,所以我们需要用其他办法实现。
我们用的是后处理的办法.

1. 我们在特效上挂一个片A,给A单独设一个layer L1,然后在Main  Camera上挂一个带摄像机的子节点Sub(back ground清成黑色),MainCamera的mask剔除掉L1 ,让Sub只渲染L1。
2. A的材质shader使用heat_distortion,这个shader通过一张噪声图计算出一个UV值,从mainTex中取颜色给后面后处理的时候当UV用。
3. main camera挂载脚步DistortImageEffect。在OnRenderImage中获取Sub的RenderTexture,将这个RT给shader:IE_heat_distortion使用并生成最终结果。


代码:

using UnityEngine;
using System.Collections;


public class DistortImageEffect : MonoBehaviour
{
	// 记录参数的rt
	RenderTexture rt;


	public Material IEHeatMaterial = null;
	public Camera sub = null;
	// Use this for initialization
	void Start()
	{
		Camera cam = GetComponent<Camera>();


		sub.fieldOfView = cam.fieldOfView;
		sub.nearClipPlane = cam.nearClipPlane;
		sub.farClipPlane = cam.farClipPlane;
		sub.aspect = cam.aspect;
		int w = Screen.width / 2;
		int h = Screen.height / 2;
		if (w > SystemInfo.maxTextureSize)
		{
			h = h * SystemInfo.maxTextureSize / w;
			w = SystemInfo.maxTextureSize;
		}
		if (h > SystemInfo.maxTextureSize)
		{
			w = w * SystemInfo.maxTextureSize / h;
			h = SystemInfo.maxTextureSize;
		}


		rt = RenderTexture.GetTemporary(Screen.width / 2, Screen.height / 2);
		sub.targetTexture = rt;
	}


	void OnDestroy()
	{
		RenderTexture.ReleaseTemporary(rt);
	}


	void OnRenderImage(RenderTexture source, RenderTexture destination)
	{
		if (sub == null)
		{
			Graphics.Blit(source, destination);
			return;
		}


		IEHeatMaterial.SetTexture("_NormalTex", rt);
 		Graphics.Blit(source, destination, IEHeatMaterial, 0);
	}	
}



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

Category {
	Tags { "RenderType"="Opaque" }
	Cull Off Lighting Off ZWrite Off Blend Off Fog {Mode Off}
	LOD 100
	

	SubShader {

		Pass {			
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			#pragma fragmentoption ARB_precision_hint_fastest
			#include "UnityCG.cginc"

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

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

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

			v2f vert (appdata_t v)
			{
				v2f o;
				o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
				#if UNITY_UV_STARTS_AT_TOP
				float scale = -1.0;
				#else
				float scale = 1.0;
				#endif
				o.uvgrab.xy = (float2(o.vertex.x, o.vertex.y*scale) + o.vertex.w) * 0.5;
				o.uvgrab.zw = o.vertex.zw; 
				o.uvmain = TRANSFORM_TEX( v.texcoord, _MainTex );
				o.uv = v.texcoord;

				return o;
			}

			half4 frag( v2f i ) : COLOR
			{
				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;

				return tex2D(_MainTex, i.uvgrab);
			}
			ENDCG
		}
	}
}

Fallback off
}


Shader "IEHeatDistortion" {
Properties {
	_MainTex ("Base (RGB)", 2D) = "white" {}
	_NormalTex ("Noise Texture (RGB)", 2D) = "white" {}
}

Category {	
	ZTest Off Cull Off ZWrite Off Blend Off

	SubShader {
		Pass {
			Fog { Mode off }
			
				CGPROGRAM
				#pragma vertex vert
				#pragma fragment frag
				#include "UnityCG.cginc"

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

				struct v2f {
					float4 vertex : POSITION;
					float2 uv : TEXCOORD0;
				};

				float4 _MainTex_ST;
				float4 _NormalTex_ST;
				sampler2D _NormalTex;
				sampler2D _MainTex;

				v2f vert (appdata_t v)
				{
					v2f o;

					v.vertex.z = 0.1;
					o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
					o.uv = v.texcoord;
					
					return o;
				}

				half4 frag( v2f i ) : COLOR
				{
					half4 col = tex2D( _NormalTex, i.uv);
					half4 tint = tex2D( _MainTex, i.uv + col);
					return tint;
				}
				ENDCG
		}
	}
}
}

猜你喜欢

转载自blog.csdn.net/songchao_xx/article/details/51541863