Unity3D Shader 空气扭动效果
//预览图
//原理
一个摄像机CullingMask设置只可见"Distortion"的Layer(需要自己手动加),输入到一张RenderTexture,其实就是用于确定哪里要扭曲。
另外一个摄像机CullingMask设置成对除了"Distortion"的Layer可见,并挂上后期效果脚本。
//Shader代码
Shader "Hidden/Distortion" { Properties { _MainTex ("Texture", 2D) = "white" {} _Noise ("Noise", 2D) = "black" {} _DistortionMask ("Distortion Mask", 2D) = "black" {} _DistortionStrength ("Distortion Strength", Float) = 0.1 _DistortTimeFactor ("_Distort Time Factor", Float) = 0.1 } SubShader { // No culling or depth Cull Off ZWrite Off ZTest Always Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; v2f vert (appdata v) { v2f o; o.vertex = mul(UNITY_MATRIX_MVP, v.vertex); o.uv = v.uv; return o; } sampler2D _MainTex; sampler2D _DistortionMask; sampler2D _Noise; float _DistortionStrength; float _DistortTimeFactor; fixed4 frag (v2f i) : SV_Target { //wave strength fixed strength = tex2D(_DistortionMask, i.uv).r; //noise fixed2 noi = tex2D(_Noise, i.uv-fixed2(0,_Time.y * _DistortTimeFactor)); //uv offset fixed2 uvOffset = strength*noi.xy*_DistortionStrength; fixed4 col = tex2D(_MainTex, i.uv.xy+uvOffset.xy); return col; } ENDCG } } }
//C#代码
using UnityEngine; using System.Collections; [ExecuteInEditMode] public class DistortionPostEffect : MonoBehaviour { private Camera distortionCam; public Material DistortionMat; private RenderTexture rt; void Awake() { Transform go = transform.Find("Distortion"); if (null == go) { go = (new GameObject ("Distortion")).transform; } go.transform.parent = transform; go.transform.localPosition = Vector3.zero; go.transform.rotation = Quaternion.identity; distortionCam = go.GetComponent<Camera> (); if (null == distortionCam) { distortionCam = go.gameObject.AddComponent<Camera> (); } distortionCam.clearFlags = CameraClearFlags.Color; distortionCam.backgroundColor = Color.black; //rt = RenderTexture.GetTemporary (Screen.width / 2, Screen.height / 2); rt = RenderTexture.GetTemporary (200 , 100); rt.wrapMode = TextureWrapMode.Repeat; distortionCam.targetTexture = rt; distortionCam.cullingMask = LayerMask.GetMask ("Distortion"); gameObject.GetComponent<Camera> ().cullingMask &= (~distortionCam.cullingMask); } // Use this for initialization void Start () { } // Update is called once per frame void Update () { } void OnRenderImage(RenderTexture src,RenderTexture dest) { DistortionMat.SetTexture ("_DistortionMask", rt); Graphics.Blit (src, dest, DistortionMat); } }