屏幕后处理-bloom效果, 使画面中较亮的区域“扩散”到周围的区域

效果

使画面中较亮的区域“扩散”到周围的区域,造成一种朦胧的效果。
bloom前
bloom后

思路

对原贴图大于某个阀值的区域进行提取,并缓存到渲染图。
再利用高斯模糊,对这张纹理进行模糊处理,模拟光线扩散的效果。
最后将其和原图进行混合。

实现

c#

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

public class BloomTest : PostEffectBaseTest {
    
    public Shader gaussianBlurShader;
    private Material gaussianBlurMatrial = null;
    
    public Material material
    {
        get
        {
            gaussianBlurMatrial = CheckShaderAndCreateMaterial(gaussianBlurShader, gaussianBlurMatrial);
            return gaussianBlurMatrial;
        }
    }
    [Range(0, 4)] public int iterations = 3;
    [Range(0.2f, 3f)] public float blurSpread = 0.6f;
    [Range(1, 8)] public int downSample = 2;
    [Range(0f, 4.0f)] public float luminanceThreshold = 0.6f;
    
    //使用迭代系数,渲染出更模糊的效果
    private void OnRenderImage(RenderTexture src, RenderTexture dest)
    {
        if (material)
        {
            material.SetFloat("luminanceThreshold",luminanceThreshold);
            //降采样
            int rtW = src.width / downSample;
            int rtH = src.height / downSample;
            RenderTexture buffer0 = RenderTexture.GetTemporary(rtW, rtH, 0);//得到与屏幕图像大小相同的缓存区
            buffer0.filterMode = FilterMode.Bilinear; //将渲染纹理的滤波模式设置为双线性
            
            //使用第一个pass(使用原图,计算明亮度,渲染成一张纹理记录到缓存。
            Graphics.Blit(src, buffer0, material, 0 ); 
            for (int i = 0; i < iterations; i++)//对画面进行多次模糊渲染
            {
                material.SetFloat("_BlurSize",1.0f+i*blurSpread);//调节模糊的范围大小
                RenderTexture buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);//获取屏幕图像缓存区
                //使用索引为1的pass,和模糊范围的参数,对纹理的竖直方向,进行模糊渲染
                Graphics.Blit(buffer0,buffer1,material,1);
                RenderTexture.ReleaseTemporary(buffer0);//释放缓冲区
                buffer0 = buffer1;//记录处理过竖直方向模糊的buffer1
                buffer1 = RenderTexture.GetTemporary(rtW, rtH, 0);//获取缓冲区
                //使用索引为2的pass,和模糊范围的参数,对纹理的水平方向,进行模糊渲染
                Graphics.Blit(buffer0,buffer1,material,2); 
                RenderTexture.ReleaseTemporary(buffer0);//释放屏幕缓冲区
                buffer0 = buffer1;
            }
            Graphics.Blit(buffer0,dest);//多重渲染后,再计算总结果,渲染出最后的图形
            material.SetTexture("_Bloom",buffer0);
            Graphics.Blit(src,dest,material,3);//多重渲染后,再在索引为3的pass中,进行bloom处理,渲染出最后的图形
            RenderTexture.ReleaseTemporary(buffer0);
        }
        else
        {
            Graphics.Blit(src,dest);
        }
    }
}

shader

Shader "Custom/BloomTest" {
	Properties {
        _MainTex("Base (RGB)",2D) = "white" {}
        _BlurSize("_BlurSize",Float) = 1.0
        _Bloom("Bloom (RGB)",2D) = "black" {}
        
	}
	SubShader {
	    CGINCLUDE
	    //引入文件
	    #include "UnityCG.cginc"
	    sampler2D _MainTex;
	    half4 _MainTex_TexelSize;
	    float _BlurSize;
	    sampler2D _Bloom;
	    float luminanceThreshold;
	    
	    struct v2f {
	        float4 pos : SV_POSITION;
	        half2 uv : TEXCOORD0;
	    };
	    
        fixed luminance(fixed4 color){
	        return 0.2125*color.r + 0.7154*color.g + 0.0721*color.b;
	    };
	    
        v2f vertExtractBright(appdata_img v){
	        v2f o;
	        o.pos = UnityObjectToClipPos(v.vertex);
	        o.uv = v.texcoord;
	        return o;
	    };
	    
        fixed4 fragExtractBright(v2f i):SV_Target{
	        fixed4 c = tex2D(_MainTex, i.uv);
	        fixed l = clamp(luminance(c) - luminanceThreshold, 0.0, 1.0); 
            return c*l;//返回主图的明亮度信息
	    };
	    
	    struct v2fBloom{
	        float4 pos : SV_POSITION;
	        half4 uv : TEXCOORD0;
	    };
	    
	    v2fBloom vertBloom(appdata_img v){
			v2fBloom o;
			o.pos = UnityObjectToClipPos (v.vertex);
			o.uv.xy = v.texcoord;		
			o.uv.zw = v.texcoord;
			
			#if UNITY_UV_STARTS_AT_TOP			
			if (_MainTex_TexelSize.y < 0.0)
				o.uv.w = 1.0 - o.uv.w;
			#endif
			return o; 
	    };
	    
	    fixed4 fragBloom(v2fBloom  i ) : SV_Target{
	        //对原图与
	        return tex2D(_MainTex,i.uv.xy ) + tex2D(_Bloom,i.uv.zw);
	    };
	    ENDCG
	    
	    ZTest Always Cull Off  ZWrite Off
	    Pass{
	        CGPROGRAM
	        #pragma vertex vertExtractBright
	        #pragma fragment fragExtractBright
	        ENDCG
	    }
	    
	    UsePass "Custom/GaussianBlurShader/GAUSSIAN_BLUR_VERTICAL"
    
        UsePass "Custom/GaussianBlurShader/GAUSSIAN_BLUR_HORIZONTAL"
	    
	    Pass{
	        CGPROGRAM
	        #pragma vertex vertBloom  
	        #pragma fragment fragBloom
	        ENDCG	    
	    }
	}
	FallBack Off
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值