Shaderlab Notizen 8 屏幕水幕特效

一、Shader實現部分

//-----------------------------------------------【Shader腳本說明】---------------------
//       屏幕水幕特效的實現代碼-Shader腳本部分  
//--------------------------------------------------------------------------------------------

Shader "Shader/ScreenWaterDropEffect"  
{  
    //------------------------------------【屬性值】------------------------------------  
    Properties  
    {  
        //主紋理  
        _MainTex ("Base (RGB)", 2D) = "white" {}  
        //屏幕水滴的素材圖  
        _ScreenWaterDropTex ("Base (RGB)", 2D) = "white" {}  
        //當前時間  
        _CurTime ("Time", Range(0.0, 1.0)) = 1.0  
        //X坐標上的水滴尺寸  
        _SizeX ("SizeX", Range(0.0, 1.0)) = 1.0  
        //Y坐標上的水滴尺寸  
        _SizeY ("SizeY", Range(0.0, 1.0)) = 1.0  
        //水滴的流動速度  
        _DropSpeed ("Speed", Range(0.0, 10.0)) = 1.0  
        //溶解度  
        _Distortion ("_Distortion", Range(0.0, 1.0)) = 0.87  
    }  

    //------------------------------------【唯一的子著色器】------------------------------
    SubShader  
    {  
        Pass  
        {  
            //設置深度測試模式:渲染所有像素.等同于關閉透明度測試(AlphaTest Off)  
            ZTest Always  

            //===========開啟CG著色器語言編寫模塊===========  
            CGPROGRAM  

            //編譯指令:告知編譯器頂點和片段著色函數的名稱  
            #pragma vertex vert  
            #pragma fragment frag  
            #pragma fragmentoption ARB_precision_hint_fastest  
            //編譯指令: 指定著色器編譯目標為Shader Model 3.0  
            #pragma target 3.0  

            //包含輔助CG頭文件  
            #include "UnityCG.cginc"  

            //外部變量的聲明  
            uniform sampler2D _MainTex;  
            uniform sampler2D _ScreenWaterDropTex;  
            uniform float _CurTime;  
            uniform float _DropSpeed;  
            uniform float _SizeX;  
            uniform float _SizeY;  
            uniform float _Distortion;  
            uniform float2 _MainTex_TexelSize;  

            //頂點輸入結構  
            struct vertexInput  
            {  
                float4 vertex : POSITION;//頂點位置  
                float4 color : COLOR;//顏色值  
                float2 texcoord : TEXCOORD0;//一級紋理坐標  
            };  

            //頂點輸出結構  
            struct vertexOutput  
            {  
                half2 texcoord : TEXCOORD0;//一級紋理坐標  
                float4 vertex : SV_POSITION;//像素位置  
                fixed4 color : COLOR;//顏色值  
            };  

            //--------------------------------【頂點著色函數】-----------------------------  
            // 輸入:頂點輸入結構體  
            // 輸出:頂點輸出結構體  
            //---------------------------------------------------------------------------------  
            vertexOutput vert(vertexInput Input)  
            {  
                //【1】聲明一個輸出結構對象  
                vertexOutput Output;  

                //【2】填充此輸出結構  
                //輸出的頂點位置為模型視圖投影矩陣乘以頂點位置,也就是將三維空間中的坐標投影到了二維窗口  
                Output.vertex = mul(UNITY_MATRIX_MVP, Input.vertex);  
                //輸出的紋理坐標也就是輸入的紋理坐標  
                Output.texcoord = Input.texcoord;  
                //輸出的顏色值也就是輸入的顏色值  
                Output.color = Input.color;  

                //【3】返回此輸出結構對象  
                return Output;  
            }  

            //--------------------------------【片段著色函數】-----------------------------  
            // 輸入:頂點輸出結構體  
            // 輸出:float4型的顏色值  
            //---------------------------------------------------------------------------------  
            fixed4 frag(vertexOutput Input) : COLOR  
            {  
                //【1】獲取頂點的坐標值  
                float2 uv = Input.texcoord.xy;  

                //【2】解決平臺差異的問題。校正方向,若和規定方向相反,則將速度反向并加1  
                #if UNITY_UV_STARTS_AT_TOP  
                if (_MainTex_TexelSize.y < 0)  
                    _DropSpeed = 1 - _DropSpeed;  
                #endif  

                //【3】設置三層水流效果,按照一定的規律在水滴紋理上分別進行取樣  
                float3 rainTex1 = tex2D(_ScreenWaterDropTex, float2(uv.x * 1.15* _SizeX, (uv.y* _SizeY *1.1) + _CurTime* _DropSpeed *0.15)).rgb / _Distortion;  
                float3 rainTex2 = tex2D(_ScreenWaterDropTex, float2(uv.x * 1.25* _SizeX - 0.1, (uv.y *_SizeY * 1.2) + _CurTime *_DropSpeed * 0.2)).rgb / _Distortion;  
                float3 rainTex3 = tex2D(_ScreenWaterDropTex, float2(uv.x* _SizeX *0.9, (uv.y *_SizeY * 1.25) + _CurTime * _DropSpeed* 0.032)).rgb / _Distortion;  

                //【4】整合三層水流效果的顏色信息,存于finalRainTex中  
                float2 finalRainTex = uv.xy - (rainTex1.xy - rainTex2.xy - rainTex3.xy) / 3;  

                //【5】按照finalRainTex的坐標信息,在主紋理上進行采樣  
                float3 finalColor = tex2D(_MainTex, float2(finalRainTex.x, finalRainTex.y)).rgb;  

                //【6】返回加上alpha分量的最終顏色值  
                return fixed4(finalColor, 1.0);  

            }  

            //===========結束CG著色器語言編寫模塊===========  
            ENDCG  
        }  
    }  
}

二、腳本實現部分

最重要的:

//載入素材圖  
 ScreenWaterDropTex = Resources.Load("ScreenWaterDrop") asTexture2D;  

源碼:

//-----------------------------------------------【C#腳本說明】--------------------------
//  屏幕水幕特效的實現代碼-C#腳本部分  
//--------------------------------------------------------------------------------------------

using UnityEngine;  
using System.Collections;  

[ExecuteInEditMode]  
[AddComponentMenu("Shader/ScreenWaterDropEffect")]  
public class ScreenWaterDropEffect : MonoBehaviour  
{  
    //-------------------變量聲明部分-------------------  
    #region Variables  

    //著色器和材質實例  
    public Shader CurShader;//著色器實例  
    private Material CurMaterial;//當前的材質  

    //時間變量和素材圖的定義  
    private float TimeX = 1.0f;//時間變量  
    private Texture2D ScreenWaterDropTex;//屏幕水滴的素材圖  

    //可以在編輯器中調整的參數值  
    [Range(5, 64), Tooltip("溶解度")]  
    public float Distortion = 8.0f;  
    [Range(0, 7), Tooltip("水滴在X坐標上的尺寸")]  
    public float SizeX = 1f;  
    [Range(0, 7), Tooltip("水滴在Y坐標上的尺寸")]  
    public float SizeY = 0.5f;  
    [Range(0, 10), Tooltip("水滴的流動速度")]  
    public float DropSpeed = 3.6f;  

    //用于參數調節的中間變量  
    public static float ChangeDistortion;  
    public static float ChangeSizeX;  
    public static float ChangeSizeY;  
    public static float ChangeDropSpeed;  
    #endregion  

    //-------------------------材質的get&set----------------------------  
    #region MaterialGetAndSet  
    Material material  
    {  
        get  
        {  
            if (CurMaterial == null)  
            {  
                CurMaterial = new Material(CurShader);  
                CurMaterial.hideFlags = HideFlags.HideAndDontSave;  
            }  
            return CurMaterial;  
        }  
    }  
    #endregion  

    //-----------------------------------------【Start()函數】-------------------------------
    // 說明:此函數僅在Update函數第一次被調用前被調用  
    //-----------------------------------------------------------------------------------------
    void Start()  
    {  
        //依次賦值  
        ChangeDistortion = Distortion;  
        ChangeSizeX = SizeX;  
        ChangeSizeY = SizeY;  
        ChangeDropSpeed = DropSpeed;  

        //載入素材圖  
        ScreenWaterDropTex = Resources.Load("ScreenWaterDrop") as Texture2D;  

        //找到當前的Shader文件  
        CurShader = Shader.Find("Shader/ScreenWaterDropEffect");  

        //判斷是否支持屏幕特效  
        if (!SystemInfo.supportsImageEffects)  
        {  
            enabled = false;  
            return;  
        }  
    }  

    //-------------------------------------【OnRenderImage()函數】--------------------- 
    // 說明:此函數在當完成所有渲染圖片后被調用,用來渲染圖片后期效果  
    //----------------------------------------------------------------------------------------- 
    void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)  
    {  
        //著色器實例不為空,就進行參數設置  
        if (CurShader != null)  
        {  
            //時間的變化  
            TimeX += Time.deltaTime;  
            //時間大于100,便置0,保證可以循環  
            if (TimeX > 100) TimeX = 0;  

            //設置Shader中其他的外部變量  
            material.SetFloat("_CurTime", TimeX);  
            material.SetFloat("_Distortion", Distortion);  
            material.SetFloat("_SizeX", SizeX);  
            material.SetFloat("_SizeY", SizeY);  
            material.SetFloat("_DropSpeed", DropSpeed);  
            material.SetTexture("_ScreenWaterDropTex", ScreenWaterDropTex);  

            //拷貝源紋理到目標渲染紋理,加上我們的材質效果  
            Graphics.Blit(sourceTexture, destTexture, material);  
        }  
        //著色器實例為空,直接拷貝屏幕上的效果。此情況下是沒有實現屏幕特效的  
        else  
        {  
            //直接拷貝源紋理到目標渲染紋理  
            Graphics.Blit(sourceTexture, destTexture);  
        }  

    }  

    //-----------------------------------------【OnValidate()函數】----------------------- 
    // 說明:此函數在編輯器中該腳本的某個值發生了改變后被調用  
    //-----------------------------------------------------------------------------------------
    void OnValidate()  
    {  
        ChangeDistortion = Distortion;  
        ChangeSizeX = SizeX;  
        ChangeSizeY = SizeY;  
        ChangeDropSpeed = DropSpeed;  
    }  

    //-----------------------------------------【Update()函數】----------------------------
    // 說明:此函數在每一幀中都會被調用  
    //-----------------------------------------------------------------------------------------
    void Update()  
    {  
        //若程序在運行,進行賦值  
        if (Application.isPlaying)  
        {  
            //賦值  
            Distortion = ChangeDistortion;  
            SizeX = ChangeSizeX;  
            SizeY = ChangeSizeY;  
            DropSpeed = ChangeDropSpeed;  
        }  
        //找到對應的Shader文件,和紋理素材  
#if UNITY_EDITOR  
        if (Application.isPlaying != true)  
        {  
            CurShader = Shader.Find("Shader/ScreenWaterDropEffect");  
            ScreenWaterDropTex = Resources.Load("ScreenWaterDrop") as Texture2D;  

        }  
#endif  

    }  

    //-----------------------------------------【OnDisable()函數】-------------------------
    // 說明:當對象變為不可用或非激活狀態時此函數便被調用    
    //-----------------------------------------------------------------------------------------
    void OnDisable()  
    {  
        if (CurMaterial)  
        {  
            //立即銷毀材質實例  
            DestroyImmediate(CurMaterial);  
        }  

    }  
}   
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容