// 후처리 후 RGB + 합성 알파를 출력하는 풀스크린 Blit 셰이더. // // 알파 = saturate(prepassAlpha + bloomAlpha) // prepassAlpha = NiloToon Prepass G 채널 (캐릭터 외곽, AA 포함) // bloomAlpha = saturate((postLum - preLum) * _BloomAlphaGain) — 후처리가 추가한 빛 // // _PreColorTex 가 비어있으면 bloomAlpha = 0 (Prepass 만 사용) // _NiloToonPrepassBufferTex 가 비어있으면 prepassAlpha = 0 (Bloom diff 만 사용) Shader "Hidden/Streamingle/AlphaCompose" { Properties { _SourceAlphaGain ("Source Alpha Gain (cameraColor.a)", Range(0, 4)) = 1.0 _BloomAlphaGain ("Bloom Alpha Gain", Range(0, 20)) = 5.0 _PrepassAlphaGain ("Prepass Alpha Gain", Range(0, 4)) = 1.0 _AlphaBlurRadius ("Alpha Blur Radius (texels)", Range(0, 5)) = 1.0 } SubShader { Tags { "RenderType"="Opaque" "RenderPipeline"="UniversalPipeline" } Pass { ZWrite Off ZTest Always Cull Off Blend Off HLSLPROGRAM #pragma vertex Vert #pragma fragment Frag #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl" #include "Packages/com.unity.render-pipelines.core/Runtime/Utilities/Blit.hlsl" // _BlitTexture 는 Blit.hlsl 가 이미 선언함 (후처리 후 cameraColor) TEXTURE2D(_PreColorTex); // 후처리 전 cameraColor SAMPLER(sampler_PreColorTex); TEXTURE2D(_NiloToonPrepassBufferTex); // NiloToon 글로벌 SAMPLER(sampler_NiloToonPrepassBufferTex); float _SourceAlphaGain; float _BloomAlphaGain; float _PrepassAlphaGain; float _AlphaBlurRadius; // 3x3 가우시안 가중치 (1/4 1/8 1/16) — Prepass G 외곽 부드럽게 half SamplePrepassAlpha(float2 uv) { if (_AlphaBlurRadius <= 0.001) return SAMPLE_TEXTURE2D(_NiloToonPrepassBufferTex, sampler_NiloToonPrepassBufferTex, uv).g; float2 t = (1.0 / _ScreenParams.xy) * _AlphaBlurRadius; half a = 0; a += SAMPLE_TEXTURE2D(_NiloToonPrepassBufferTex, sampler_NiloToonPrepassBufferTex, uv).g * 0.25; a += SAMPLE_TEXTURE2D(_NiloToonPrepassBufferTex, sampler_NiloToonPrepassBufferTex, uv + float2( 0, t.y)).g * 0.125; a += SAMPLE_TEXTURE2D(_NiloToonPrepassBufferTex, sampler_NiloToonPrepassBufferTex, uv + float2( 0, -t.y)).g * 0.125; a += SAMPLE_TEXTURE2D(_NiloToonPrepassBufferTex, sampler_NiloToonPrepassBufferTex, uv + float2( t.x, 0)).g * 0.125; a += SAMPLE_TEXTURE2D(_NiloToonPrepassBufferTex, sampler_NiloToonPrepassBufferTex, uv + float2(-t.x, 0)).g * 0.125; a += SAMPLE_TEXTURE2D(_NiloToonPrepassBufferTex, sampler_NiloToonPrepassBufferTex, uv + float2( t.x, t.y)).g * 0.0625; a += SAMPLE_TEXTURE2D(_NiloToonPrepassBufferTex, sampler_NiloToonPrepassBufferTex, uv + float2(-t.x, t.y)).g * 0.0625; a += SAMPLE_TEXTURE2D(_NiloToonPrepassBufferTex, sampler_NiloToonPrepassBufferTex, uv + float2( t.x, -t.y)).g * 0.0625; a += SAMPLE_TEXTURE2D(_NiloToonPrepassBufferTex, sampler_NiloToonPrepassBufferTex, uv + float2(-t.x, -t.y)).g * 0.0625; return a; } half4 Frag(Varyings input) : SV_Target { float2 uv = input.texcoord; half4 postSample = SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, uv); half3 postRgb = postSample.rgb; half sourceAlpha = postSample.a * _SourceAlphaGain; half3 preRgb = SAMPLE_TEXTURE2D(_PreColorTex, sampler_PreColorTex, uv).rgb; // 후처리가 추가한 luminance (블룸/글로우/플레어 등) half postLum = Luminance(postRgb); half preLum = Luminance(preRgb); half bloomAlpha = saturate((postLum - preLum) * _BloomAlphaGain); // NiloToon Prepass G 채널 알파 (캐릭터 외곽, 가우시안 블러로 AA) half prepassAlpha = SamplePrepassAlpha(uv) * _PrepassAlphaGain; half alpha = saturate(sourceAlpha + prepassAlpha + bloomAlpha); return half4(postRgb, alpha); } ENDHLSL } } Fallback Off }