后处理 - 泛光Bloom

原理

泛光其实就是让图片变亮,看着有种自身在发光的感觉。

那怎么做呢?简单点,就是图片模糊处理后,再与原来的颜色值相加,就能使整体颜色变亮,但直接这样做可能会让颜色太亮而过曝,所以可以在图片模糊前做下颜色值的控制,防止相加后直接成为白色。

 

效果

 

c#代码

using UnityEngine;

public class BloomEff : MonoBehaviour
{
    public Shader m_BlurShader;
    public Material m_BlurMat;

    [Range(-3, 3)]
    public float m_BlurOffset = 1;

    public bool m_DoubleBlur; //是否启用双重模糊

    private int m_SrcRTWidth;
    private int m_SrcRTHeight;

    private RenderTexture m_RTHalfSize; //一半大小
    private RenderTexture m_RTQuarterSize; //1/4大小

    public Shader m_BloomBrightShader;
    public Material m_BloomBrightMat;
    [Range(0, 1)]
    public float m_BrightCut = 0.5f;

    public Shader m_BloomShader;
    public Material m_BloomMat;

    private RenderTexture m_TempRT1;
    private RenderTexture m_BlurRT;

    void Start()
    {
        if (false == SystemInfo.supportsImageEffects)
        {
            Debug.LogWarning("This platform does not support image effects or render textures.");
            this.enabled = false;
            return;
        }
        InitMaterial(ref m_BlurShader, ref m_BlurMat);
        if (null != m_BlurMat)
            m_BlurMat.SetFloat("_BlurOffset", m_BlurOffset);
        InitMaterial(ref m_BloomBrightShader, ref m_BloomBrightMat);
        InitMaterial(ref m_BloomShader, ref m_BloomMat);
    }

    private static void InitMaterial(ref Shader s, ref Material mat)
    {
        if (null == mat)
        {
            if (null != s && s.isSupported)
            {
                mat = new Material(s);
                mat.hideFlags = HideFlags.DontSave;
            }
        }
        else if (null != s && mat.shader != s)
        {
            if (s.isSupported) //优先shader
            {
                mat = new Material(s);
                mat.hideFlags = HideFlags.DontSave;
            }
            else
            {
                mat = null;
            }
        }
    }

    private void OnRenderImage(RenderTexture source, RenderTexture destination)
    {
        if (null == m_BlurMat)
        {
            Graphics.Blit(source, destination);
        }
        else
        {
            if (null == m_TempRT1 || m_TempRT1.width != source.width || m_TempRT1.height != source.height)
            {
                m_TempRT1 = RenderTexture.GetTemporary(source.width, source.height);
                m_BlurRT = RenderTexture.GetTemporary(source.width, source.height);
            }
#if UNITY_EDITOR
            m_BlurMat.SetFloat("_BlurOffset", m_BlurOffset);
            m_BloomBrightMat.SetFloat("_BrightCut", m_BrightCut);
#endif
            Graphics.Blit(source, m_TempRT1, m_BloomBrightMat); //图片模糊前控制下颜色值
            if (m_DoubleBlur)
                DoubleBlur(m_TempRT1, m_BlurRT);
            else
                Graphics.Blit(m_TempRT1, m_BlurRT, m_BlurMat, 0); //图片模糊

            m_BloomMat.SetTexture("_brightTex", m_BlurRT);

            Graphics.Blit(source, destination, m_BloomMat);
        }

    }

    private void DoubleBlur(RenderTexture source, RenderTexture destination)
    {
        if (m_SrcRTWidth != source.width || m_SrcRTHeight != source.height)
        {
            m_SrcRTWidth = source.width;
            m_SrcRTHeight = source.height;
            m_RTHalfSize = RenderTexture.GetTemporary((int)(m_SrcRTWidth * 0.5f), (int)(m_SrcRTHeight * 0.5f));
            m_RTQuarterSize = RenderTexture.GetTemporary((int)(m_SrcRTWidth * 0.25f), (int)(m_SrcRTHeight * 0.25f));
        }

        //降采样
        Graphics.Blit(source, m_RTHalfSize, m_BlurMat, 0);
        Graphics.Blit(m_RTHalfSize, m_RTQuarterSize, m_BlurMat, 1);

        //升采样
        Graphics.Blit(m_RTQuarterSize, m_RTHalfSize, m_BlurMat, 0);
        Graphics.Blit(m_RTHalfSize, destination, m_BlurMat, 1);
    }

    void OnDestroy()
    {
        if (null != m_TempRT1)
        {
            RenderTexture.ReleaseTemporary(m_TempRT1);
            m_TempRT1 = null;
        }
    }

}

 

BloomBright.shader

Shader "My/PostEff/BloomBright" //控制要叠加图片的像素值, 防止过量
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {} //主贴图
		_BrightCut("LightVal", Range(0, 1)) = 0.5 //降低要叠加图片的颜色值, 防止相加后过亮
	}

	SubShader
	{
		Cull Off //剔除: 关
		ZWrite Off //深度缓冲buff写入: 关
		ZTest Always //深度测试: 开

		Pass
		{
			CGPROGRAM
			#pragma vertex vert_img
			#pragma fragment frag

			#include "UnityCG.cginc"

			sampler2D _MainTex;
			float _BrightCut;

			fixed4 frag(v2f_img i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.uv);
				float br = max(max(col.r, col.g), col.b); //取rgb中颜色值最大的
				br = max(0, (br - _BrightCut)) / max(br, 0.00001);
				col.rgb *= br;
				return col;
			}
			ENDCG
		}
	}
}

 

Bloom.shader

Shader "My/PossEff/Bloom"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {} //主贴图
		_brightTex("BrightTex",2D) = "black" //要叠加的贴图
	}
	
	SubShader
	{
		Cull Off //剔除: 关
		ZWrite Off //深度缓冲buff写入: 关
		ZTest Always //深度测试: 开

		Pass
		{
			CGPROGRAM
			#pragma vertex vert_img
			#pragma fragment frag

			#include "UnityCG.cginc"

			sampler2D _MainTex;
			sampler2D _brightTex;

			half4 frag(v2f_img i) : SV_Target //片元着色器
			{
				half4 col = tex2D(_MainTex, i.uv);
				half4 brightCol = tex2D(_brightTex, i.uv);
				col.rgb += brightCol.rgb; //颜色相加就能让颜色更亮了
				return col;
			}
			ENDCG
		}
	}

}

 

参考

Unity自定义后处理——Bloom效果_unity 3d bloom效果-CSDN博客

 

posted @ 2024-03-29 22:36  yanghui01  阅读(10)  评论(0编辑  收藏  举报