天天看点

Unity 热扭曲Shader

Unity 热浪扭曲Shader的实现,参考http://blog.csdn.net/qq18052887/article/details/50457680这位博主大大的实现方式。

首先介绍网上常见的使用GrabPass的实现方式来实现,主要思路是通过将GrabPass截取的图片根据噪声图片来偏移截图的uv,从而实现图片的扭曲。

下面贴出代码:

Shader "Hidden/ImageGlass"
{
    Properties
    {
        _MainTex ("Texture", D) = "white" {}
        _NoiseTex("Noise Texture",D) = "white"{}
        _MaskTex("Mask Texture",D) = "white"{}
        _HeatTime ("Heat Time",range(,)) = 
        _HeatForce ("Heat Force",range(,)) = 
    }
    SubShader
    {
        Tags {"Queue" = "Transparent"}

        Blend SrcAlpha OneMinusSrcAlpha
        AlphaTest Greater 
        Cull Off
        ZWrite Off
        Lighting Off

       GrabPass{"_RefractionTex"}    

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

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


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

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 uvgrab : TEXCOORD1;
                float4 vertex : SV_POSITION;
            };

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


            fixed4 frag (v2f i) : SV_Target
            {

                /*===============================================================
                                    将uv坐标偏移
                ================================================================*/
                half4 offestcol1 = tex2D(_NoiseTex,i.uv + _Time.xz * _HeatTime);
                half4 offestcol2 = tex2D(_NoiseTex,i.uv - _Time.yx * _HeatTime);
                i.uvgrab.x += ((offestcol1.r + offestcol2.r) - ) * _HeatForce;
                i.uvgrab.y += ((offestcol1.g + offestcol2.g) - ) * _HeatForce;

                /*===========================================================*/
                half4 col = tex2Dproj(_RefractionTex,UNITY_PROJ_COORD(i.uvgrab));

                half4 maskcol = tex2D(_MaskTex, i.uv);

                col.a = maskcol.a;

                half4 tint = tex2D(_MainTex,i.uv);

                return col * tint;
            }
            ENDCG
        }
    }
}
           

第二种方法

因为GrabPass在移动平台上消耗很大,所以参考博主的文章,其实是可以在渲染后直接对相机图片进行扭曲的,效率就上来了。

Shader "Hidden/ImageGlass"
{
     Properties   
    {  
        _MainTex ("Base (RGB)", D) = "white" {}  
        _NoiseTex ("Noise Texture (RG)", D) = "white" {}  
        _MaskTex ("Mask Texture", D) = "white" {}  
        _HeatTime  ("Heat Time", range (,)) =   
        _HeatForce  ("Heat Force", range (,)) =   
    }  

    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  
            {  
                fixed mask = tex2D(_MaskTex, i.uv).a;  

                // 扭曲效果  
                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) - ) * _HeatForce * mask;  
                i.uv.y += ((offsetColor1.g + offsetColor2.g) - ) * _HeatForce * mask;  

                fixed4 renderTex = tex2D(_MainTex, i.uv);  

                return renderTex;  
            }  

            ENDCG  
        }  
    }   
    FallBack off  
}
           

这个还要配合屏幕后处理脚本使用。