Streamingle_URP/Assets/Scripts/SpoutOutputScript/Shaders/StreamingleAlphaCompose.shader
user 9ea5f2af2b Refactor : Spout/NDI 출력 파이프라인 통합 + 알파 합성 + Normalizer 통합
- RenderStreamOutput 을 URP 17 RenderGraph API 로 마이그레이션
  (옛 Execute() 도 Compatibility Mode 호환용으로 유지)
- 알파 합성 셰이더 신규: Pre/Post 비교(블룸/글로우) + NiloToon Prepass G + 가우시안 블러
- 알파 채널 별도 Spout 송신 추가 ("Streamingle Spout Alpha Output")
  - 그레이스케일 RGB 마스크, A=1
- spout_ndi_normalizer.exe 외부 프로세스 자동 실행/종료 (SpoutNdiLauncher 병합)
  - Display 드롭다운 / Vsync / AlwaysOnTop / HideCursor / Realtime / NoActivate 옵션
  - exe 가 있으면 강제 종료 후 단일 인스턴스 보장
  - 내부 옵션(exe 경로, window size 등)은 [HideInInspector]
- ScreenshotManager 가 RenderStreamOutput 의 합성 결과를 그대로 PNG 저장
  - 자체 카메라 렌더/셰이더 관리 제거 → 알파 품질 라이브 출력과 동일
  - captureWidth/Height 지정 시 한 프레임 임시 고해상도 렌더 후 원복
- spout_ndi_normalizer.exe 위치: Resources → StreamingAssets/SpoutNdiNormalizer
- URP Asset: Allow Post Process Alpha Output 활성화

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 04:35:14 +09:00

97 lines
4.5 KiB
Plaintext

// 후처리 후 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
}