U3D Distortion

来源:互联网 发布:网管软件限速 编辑:程序博客网 时间:2024/06/02 13:13

我们的美术希望游戏可以更炫一点,想在刀光特效上加上空气扭曲的效果,就是类似燃烧的火焰上方空气扰动的那种效果。这个效果其实很多游戏都有。网络上流传的有一个叫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{// 记录参数的rtRenderTexture rt;public Material IEHeatMaterial = null;public Camera sub = null;// Use this for initializationvoid 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 100SubShader {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_TOPfloat scale = -1.0;#elsefloat scale = 1.0;#endifo.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 OffSubShader {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}}}}
0 0