unity屏幕shader之水屏幕

本篇博客仅仅供本人参考学习,转载自浅墨shader。

首先创建一个顶点片段shader,将内容修改如下:

Shader "Custom/waterCamera" {
	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
			//添加选项到编译的OpenGL 片段程序。
			#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*0.9*_SizeX,(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
		}
	}
	FallBack "Diffuse"
}
接着创建一个脚本挂在摄像机上,如下:

using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class WaterScreen : 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("Custom/waterCamera");

        //判断是否支持屏幕特效
        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("Custom/waterCamera");
            ScreenWaterDropTex = Resources.Load("ScreenWaterDrop") as Texture2D;

        }
#endif
    }
    //-----------------------------------------【OnDisable()函数】---------------------------------------  
    // 说明:当对象变为不可用或非激活状态时此函数便被调用  
    //--------------------------------------------------------------------------------------------------------
    void OnDisable()
    {
        if (CurMaterial)
        {
            //立即销毁材质实例
            DestroyImmediate(CurMaterial);
        }

    }
}




  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值