一、Shader實(shí)現(xiàn)部分
//-----------------------------------------------【Shader腳本說(shuō)明】---------------------
// 屏幕水幕特效的實(shí)現(xiàn)代碼-Shader腳本部分
//--------------------------------------------------------------------------------------------
Shader "Shader/ScreenWaterDropEffect"
{
//------------------------------------【屬性值】------------------------------------
Properties
{
//主紋理
_MainTex ("Base (RGB)", 2D) = "white" {}
//屏幕水滴的素材圖
_ScreenWaterDropTex ("Base (RGB)", 2D) = "white" {}
//當(dāng)前時(shí)間
_CurTime ("Time", Range(0.0, 1.0)) = 1.0
//X坐標(biāo)上的水滴尺寸
_SizeX ("SizeX", Range(0.0, 1.0)) = 1.0
//Y坐標(biāo)上的水滴尺寸
_SizeY ("SizeY", Range(0.0, 1.0)) = 1.0
//水滴的流動(dòng)速度
_DropSpeed ("Speed", Range(0.0, 10.0)) = 1.0
//溶解度
_Distortion ("_Distortion", Range(0.0, 1.0)) = 0.87
}
//------------------------------------【唯一的子著色器】------------------------------
SubShader
{
Pass
{
//設(shè)置深度測(cè)試模式:渲染所有像素.等同于關(guān)閉透明度測(cè)試(AlphaTest Off)
ZTest Always
//===========開(kāi)啟CG著色器語(yǔ)言編寫(xiě)模塊===========
CGPROGRAM
//編譯指令:告知編譯器頂點(diǎn)和片段著色函數(shù)的名稱
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
//編譯指令: 指定著色器編譯目標(biāo)為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;
//頂點(diǎn)輸入結(jié)構(gòu)
struct vertexInput
{
float4 vertex : POSITION;//頂點(diǎn)位置
float4 color : COLOR;//顏色值
float2 texcoord : TEXCOORD0;//一級(jí)紋理坐標(biāo)
};
//頂點(diǎn)輸出結(jié)構(gòu)
struct vertexOutput
{
half2 texcoord : TEXCOORD0;//一級(jí)紋理坐標(biāo)
float4 vertex : SV_POSITION;//像素位置
fixed4 color : COLOR;//顏色值
};
//--------------------------------【頂點(diǎn)著色函數(shù)】-----------------------------
// 輸入:頂點(diǎn)輸入結(jié)構(gòu)體
// 輸出:頂點(diǎn)輸出結(jié)構(gòu)體
//---------------------------------------------------------------------------------
vertexOutput vert(vertexInput Input)
{
//【1】聲明一個(gè)輸出結(jié)構(gòu)對(duì)象
vertexOutput Output;
//【2】填充此輸出結(jié)構(gòu)
//輸出的頂點(diǎn)位置為模型視圖投影矩陣乘以頂點(diǎn)位置撮珠,也就是將三維空間中的坐標(biāo)投影到了二維窗口
Output.vertex = mul(UNITY_MATRIX_MVP, Input.vertex);
//輸出的紋理坐標(biāo)也就是輸入的紋理坐標(biāo)
Output.texcoord = Input.texcoord;
//輸出的顏色值也就是輸入的顏色值
Output.color = Input.color;
//【3】返回此輸出結(jié)構(gòu)對(duì)象
return Output;
}
//--------------------------------【片段著色函數(shù)】-----------------------------
// 輸入:頂點(diǎn)輸出結(jié)構(gòu)體
// 輸出:float4型的顏色值
//---------------------------------------------------------------------------------
fixed4 frag(vertexOutput Input) : COLOR
{
//【1】獲取頂點(diǎn)的坐標(biāo)值
float2 uv = Input.texcoord.xy;
//【2】解決平臺(tái)差異的問(wèn)題伴逸。校正方向,若和規(guī)定方向相反狡耻,則將速度反向并加1
#if UNITY_UV_STARTS_AT_TOP
if (_MainTex_TexelSize.y < 0)
_DropSpeed = 1 - _DropSpeed;
#endif
//【3】設(shè)置三層水流效果陪踩,按照一定的規(guī)律在水滴紋理上分別進(jìn)行取樣
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】按照f(shuō)inalRainTex的坐標(biāo)信息荒吏,在主紋理上進(jìn)行采樣
float3 finalColor = tex2D(_MainTex, float2(finalRainTex.x, finalRainTex.y)).rgb;
//【6】返回加上alpha分量的最終顏色值
return fixed4(finalColor, 1.0);
}
//===========結(jié)束CG著色器語(yǔ)言編寫(xiě)模塊===========
ENDCG
}
}
}
二敛惊、腳本實(shí)現(xiàn)部分
最重要的:
//載入素材圖
ScreenWaterDropTex = Resources.Load("ScreenWaterDrop") asTexture2D;
源碼:
//-----------------------------------------------【C#腳本說(shuō)明】--------------------------
// 屏幕水幕特效的實(shí)現(xiàn)代碼-C#腳本部分
//--------------------------------------------------------------------------------------------
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
[AddComponentMenu("Shader/ScreenWaterDropEffect")]
public class ScreenWaterDropEffect : MonoBehaviour
{
//-------------------變量聲明部分-------------------
#region Variables
//著色器和材質(zhì)實(shí)例
public Shader CurShader;//著色器實(shí)例
private Material CurMaterial;//當(dāng)前的材質(zhì)
//時(shí)間變量和素材圖的定義
private float TimeX = 1.0f;//時(shí)間變量
private Texture2D ScreenWaterDropTex;//屏幕水滴的素材圖
//可以在編輯器中調(diào)整的參數(shù)值
[Range(5, 64), Tooltip("溶解度")]
public float Distortion = 8.0f;
[Range(0, 7), Tooltip("水滴在X坐標(biāo)上的尺寸")]
public float SizeX = 1f;
[Range(0, 7), Tooltip("水滴在Y坐標(biāo)上的尺寸")]
public float SizeY = 0.5f;
[Range(0, 10), Tooltip("水滴的流動(dòng)速度")]
public float DropSpeed = 3.6f;
//用于參數(shù)調(diào)節(jié)的中間變量
public static float ChangeDistortion;
public static float ChangeSizeX;
public static float ChangeSizeY;
public static float ChangeDropSpeed;
#endregion
//-------------------------材質(zhì)的get&set----------------------------
#region MaterialGetAndSet
Material material
{
get
{
if (CurMaterial == null)
{
CurMaterial = new Material(CurShader);
CurMaterial.hideFlags = HideFlags.HideAndDontSave;
}
return CurMaterial;
}
}
#endregion
//-----------------------------------------【Start()函數(shù)】-------------------------------
// 說(shuō)明:此函數(shù)僅在Update函數(shù)第一次被調(diào)用前被調(diào)用
//-----------------------------------------------------------------------------------------
void Start()
{
//依次賦值
ChangeDistortion = Distortion;
ChangeSizeX = SizeX;
ChangeSizeY = SizeY;
ChangeDropSpeed = DropSpeed;
//載入素材圖
ScreenWaterDropTex = Resources.Load("ScreenWaterDrop") as Texture2D;
//找到當(dāng)前的Shader文件
CurShader = Shader.Find("Shader/ScreenWaterDropEffect");
//判斷是否支持屏幕特效
if (!SystemInfo.supportsImageEffects)
{
enabled = false;
return;
}
}
//-------------------------------------【OnRenderImage()函數(shù)】---------------------
// 說(shuō)明:此函數(shù)在當(dāng)完成所有渲染圖片后被調(diào)用,用來(lái)渲染圖片后期效果
//-----------------------------------------------------------------------------------------
void OnRenderImage(RenderTexture sourceTexture, RenderTexture destTexture)
{
//著色器實(shí)例不為空绰更,就進(jìn)行參數(shù)設(shè)置
if (CurShader != null)
{
//時(shí)間的變化
TimeX += Time.deltaTime;
//時(shí)間大于100瞧挤,便置0,保證可以循環(huán)
if (TimeX > 100) TimeX = 0;
//設(shè)置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);
//拷貝源紋理到目標(biāo)渲染紋理儡湾,加上我們的材質(zhì)效果
Graphics.Blit(sourceTexture, destTexture, material);
}
//著色器實(shí)例為空特恬,直接拷貝屏幕上的效果。此情況下是沒(méi)有實(shí)現(xiàn)屏幕特效的
else
{
//直接拷貝源紋理到目標(biāo)渲染紋理
Graphics.Blit(sourceTexture, destTexture);
}
}
//-----------------------------------------【OnValidate()函數(shù)】-----------------------
// 說(shuō)明:此函數(shù)在編輯器中該腳本的某個(gè)值發(fā)生了改變后被調(diào)用
//-----------------------------------------------------------------------------------------
void OnValidate()
{
ChangeDistortion = Distortion;
ChangeSizeX = SizeX;
ChangeSizeY = SizeY;
ChangeDropSpeed = DropSpeed;
}
//-----------------------------------------【Update()函數(shù)】----------------------------
// 說(shuō)明:此函數(shù)在每一幀中都會(huì)被調(diào)用
//-----------------------------------------------------------------------------------------
void Update()
{
//若程序在運(yùn)行徐钠,進(jìn)行賦值
if (Application.isPlaying)
{
//賦值
Distortion = ChangeDistortion;
SizeX = ChangeSizeX;
SizeY = ChangeSizeY;
DropSpeed = ChangeDropSpeed;
}
//找到對(duì)應(yīng)的Shader文件豺型,和紋理素材
#if UNITY_EDITOR
if (Application.isPlaying != true)
{
CurShader = Shader.Find("Shader/ScreenWaterDropEffect");
ScreenWaterDropTex = Resources.Load("ScreenWaterDrop") as Texture2D;
}
#endif
}
//-----------------------------------------【OnDisable()函數(shù)】-------------------------
// 說(shuō)明:當(dāng)對(duì)象變?yōu)椴豢捎没蚍羌せ顮顟B(tài)時(shí)此函數(shù)便被調(diào)用
//-----------------------------------------------------------------------------------------
void OnDisable()
{
if (CurMaterial)
{
//立即銷毀材質(zhì)實(shí)例
DestroyImmediate(CurMaterial);
}
}
}