Shader学习:全屏流动的雾特效

效果如下:

实现思路:
其实雾的流动就是一个简单的UV动画,而雾效果是用噪点贴图的灰度值作为控制屏幕颜色和雾颜色插值的系数。
我这里对噪点贴图的灰度值进行了进一步的计算以方便使用参数来控制雾的浓度效果。

步骤:
1.新建一个场景,将下面提供的脚本文件添加到摄像机上

2.将噪点贴图拖至脚本上的FogNoiseTexture

3.将下面提供的shader文件拖至脚本上的FogShader
4.FogDensity,NoiseAmount和Speed都是用来控制雾的显示效果

脚本文件:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class FullSreenFog : MonoBehaviour 
{
    public Shader fogShader;

    public Texture fogNoiseTexture;

    public Color fogColor = Color.white;

    [Range(0, 1f)]
    public float fogDensity = 0.5f;

    [Range(0, 10f)]
    public float noiseAmount = 1f;

    [Range(0, 0.1f)]
    public float speed = 0.02f;

    private Material m_Material;
    public Material material
    {
        get
        {
            if (m_Material == null) m_Material = new Material(fogShader);
            return m_Material;
        }
    }

    void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        material.SetTexture("_FogNoiseTex", fogNoiseTexture);
        material.SetColor("_FogColor", fogColor);
        material.SetFloat("_FogDensity", fogDensity);
        material.SetFloat("_NoiseAmount", noiseAmount);
        material.SetFloat("_Speed", speed);
        Graphics.Blit(src, dest, material);
    }
}

Shader文件:

// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'

Shader "Custom/FullScreenFog" {
	Properties {
		_MainTex ("Albedo (RGB)", 2D) = "white" {}
		_FogNoiseTex ("Fog Noise Texture", 2D) = "white" {}
		_FogColor ("Fog Color", Color) = (1,1,1,1)
		_FogDensity ("Fog Density", Range(0, 1)) = 0.5
		_NoiseAmount ("Noise Amount", Range(0, 10)) = 1
		_Speed ("Speed", Range(0, 0.1)) = 0.02
	}
	SubShader {
		LOD 500
		
		Pass {
			ZWrite Off

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			sampler2D _MainTex;
			sampler2D _FogNoiseTex;
			fixed4 _FogColor;
			fixed _FogDensity;
			half _NoiseAmount;
			fixed _Speed;

			struct v2f {
				float4 pos : SV_POSITION;
				half2 uv : TEXCOORD0;
			};

			v2f vert(appdata_img v) {
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.uv = v.texcoord.xy;
				return o;
			}

			fixed4 frag(v2f i) : SV_TARGET {
				half2 uv = i.uv;
				uv.x += _Time.y * _Speed;
				fixed noise = (tex2D(_FogNoiseTex, uv).r - 0.5) * _NoiseAmount;

				fixed fogDensity = saturate(_FogDensity * (1 + noise));

				fixed4 finalColor = tex2D(_MainTex, i.uv);
				finalColor.rgb = lerp(finalColor.rgb, _FogColor.rgb, fogDensity);

				return finalColor;
			}
			ENDCG
		}
	}
}