Shader "Unlit/DualBlurBloom" { Properties { _MainTex ("Texture", 2D) = "white" {} _Bloom ("Bloom (RGB)", 2D) = "black" {} _Threshold("Threshold", float) = 0.5 _Intensity("Intensity", float) = 0.5 _Offset("BlurOffset", float) = 1 } SubShader { CGINCLUDE #include "UnityCG.cginc" sampler2D _MainTex; float4 _MainTex_ST; half _Offset, _Threshold, _Intensity; sampler2D _Bloom; float4 _MainTex_TexelSize; struct a2f_default { float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f_luminace { float4 pos : SV_POSITION; half2 uv : TEXCOORD0; }; // 降采样 顶-片结构体 struct v2f_downSample { float4 vertex : SV_POSITION; float2 texcoord: TEXCOORD0; float2 uv: TEXCOORD1; float4 uv01: TEXCOORD2; float4 uv23: TEXCOORD3; }; // 升采样 顶-片结构体 struct v2f_upSample { float4 vertex: SV_POSITION; float2 texcoord: TEXCOORD0; float4 uv01: TEXCOORD1; float4 uv23: TEXCOORD2; float4 uv45: TEXCOORD3; float4 uv67: TEXCOORD4; }; struct v2f_simple { float4 pos : SV_POSITION; half2 uv : TEXCOORD0; #if UNITY_UV_STARTS_AT_TOP half2 uv2 : TEXCOORD1; #endif }; v2f_simple vertBloom ( appdata_img v ) { v2f_simple o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = UnityStereoScreenSpaceUVAdjust(v.texcoord, _MainTex_ST); #if UNITY_UV_STARTS_AT_TOP o.uv2 = o.uv; if (_MainTex_TexelSize.y < 0.0) o.uv.y = 1.0 - o.uv.y; #endif return o; } fixed4 fragBloom ( v2f_simple i ) : SV_Target { #if UNITY_UV_STARTS_AT_TOP fixed4 color = tex2D(_MainTex, i.uv2); return color + tex2D(_Bloom, i.uv); #else fixed4 color = tex2D(_MainTex, i.uv); return color + tex2D(_Bloom, i.uv); #endif } v2f_luminace vertLuminace ( appdata_img v ) { v2f_luminace o; o.pos = UnityObjectToClipPos(v.vertex); o.uv = UnityStereoScreenSpaceUVAdjust(v.texcoord + _MainTex_TexelSize.xy, _MainTex_ST); return o; } fixed4 fragLuminace ( v2f_luminace i ) : SV_Target { fixed4 color = tex2D (_MainTex, i.uv); return max(color - _Threshold, 0) * _Intensity; } v2f_downSample VertDownSample(a2f_default v) { v2f_downSample o; o.vertex = UnityObjectToClipPos(v.vertex); o.texcoord = v.uv; #if UNITY_UV_STARTS_AT_TOP o.texcoord = o.texcoord * float2(1.0, -1.0) + float2(0.0, 1.0); #endif float2 uv = TRANSFORM_TEX(o.texcoord, _MainTex); _MainTex_TexelSize *= 0.5; o.uv = uv; o.uv01.xy = uv - _MainTex_TexelSize * float2(1 + _Offset, 1 + _Offset);//top right o.uv01.zw = uv + _MainTex_TexelSize * float2(1 + _Offset, 1 + _Offset);//bottom left o.uv23.xy = uv - float2(_MainTex_TexelSize.x, -_MainTex_TexelSize.y) * float2(1 + _Offset, 1 + _Offset);//top left o.uv23.zw = uv + float2(_MainTex_TexelSize.x, -_MainTex_TexelSize.y) * float2(1 + _Offset, 1 + _Offset);//bottom right return o; } half4 FragDownSample(v2f_downSample i): SV_Target { half4 sum = tex2D(_MainTex, i.uv) * 4; sum += tex2D(_MainTex, i.uv01.xy); sum += tex2D(_MainTex, i.uv01.zw); sum += tex2D(_MainTex, i.uv23.xy); sum += tex2D(_MainTex, i.uv23.zw); return half4(sum.rgb * 0.125, 1.0); } v2f_upSample VertUpSample(a2f_default v) { v2f_upSample o; o.vertex = UnityObjectToClipPos(v.vertex); o.texcoord = v.uv; #if UNITY_UV_STARTS_AT_TOP o.texcoord = o.texcoord * float2(1.0, -1.0) + float2(0.0, 1.0); #endif float2 uv = TRANSFORM_TEX(o.texcoord, _MainTex); _MainTex_TexelSize *= 0.5; _Offset = float2(1 + _Offset, 1 + _Offset); o.uv01.xy = uv + float2(-_MainTex_TexelSize.x * 2, 0) * _Offset; o.uv01.zw = uv + float2(-_MainTex_TexelSize.x, _MainTex_TexelSize.y) * _Offset; o.uv23.xy = uv + float2(0, _MainTex_TexelSize.y * 2) * _Offset; o.uv23.zw = uv + _MainTex_TexelSize * _Offset; o.uv45.xy = uv + float2(_MainTex_TexelSize.x * 2, 0) * _Offset; o.uv45.zw = uv + float2(_MainTex_TexelSize.x, -_MainTex_TexelSize.y) * _Offset; o.uv67.xy = uv + float2(0, -_MainTex_TexelSize.y * 2) * _Offset; o.uv67.zw = uv - _MainTex_TexelSize * _Offset; return o; } half4 FragUpSample(v2f_upSample i): SV_Target { half4 sum = 0; sum += tex2D(_MainTex, i.uv01.xy); sum += tex2D(_MainTex, i.uv01.zw) * 2; sum += tex2D(_MainTex, i.uv23.xy); sum += tex2D(_MainTex, i.uv23.zw) * 2; sum += tex2D(_MainTex, i.uv45.xy); sum += tex2D(_MainTex, i.uv45.zw) * 2; sum += tex2D(_MainTex, i.uv67.xy); sum += tex2D(_MainTex, i.uv67.zw) * 2; return half4(sum.rgb * 0.0833, 1.0); } ENDCG Cull Off ZWrite Off ZTest Always Pass { CGPROGRAM #pragma vertex vertBloom #pragma fragment fragBloom // #pragma enable_d3d11_debug_symbols ENDCG } Pass { CGPROGRAM #pragma vertex VertDownSample #pragma fragment FragDownSample // #pragma enable_d3d11_debug_symbols ENDCG } Pass { CGPROGRAM #pragma vertex VertUpSample #pragma fragment FragUpSample // #pragma enable_d3d11_debug_symbols ENDCG } // 根据阈值和强度获取需要进行模糊的RT Pass { CGPROGRAM #pragma vertex vertLuminace #pragma fragment fragLuminace // #pragma enable_d3d11_debug_symbols ENDCG } } }