송출용 프로그램의 파티클 미출력 문제 관련 기록
Unity 파티클이 송출 화면에서 사라지는 문제 정리 (OBS / Spout2 / 크로마키)
Built-in / URP 로 제작판 파티클이 트래킹 프로그램 내에서는 제대로 출력되지만,
송출 프로그램으로 넘어가는 순간부터 비정상 출력되는 현상들이 종종 일어난다.
(예시 : https://x.com/chzzk_hoorogi/status/1910240771015573916/video/1)
이전에 발매했던 감정표현 VFX도 비슷한 현상이 있어서 standard unlit이 아닌 커스텀 쉐이더를 썼었는데
도대체가 원인이 뭔지는 모르겠었던 상황...
Meligo 캐릭터 SDK 디스코드에서 해당 현상 관련 문의가 들어온 겸
파티클 관련 질문을 드렸더니 실마리를 좀 찾은 것 같다.
뭔가 내가 멜리고에서 준 대답이랑 정 반대의 답안을 찾은거긴 하지만...
어쨌든 해결이 되면 럭키비키아닐까...
1. 현상
- Unity, Vseeface, Meligo 에서는 파티클이 정상적으로 보임
- OBS, Spout, NDI, VMix 등으로 송출 시
- 파티클의 가장자리가 찢어지거나 잘림
- 흐린 파티클이 아예 사라짐
- 투명하게 처리돼 출력되지 않음
- 몸 위의 파티클은 보임
- 캐릭터 외곽을 벗어난 파티클은 아예 사라지거나 흐릿해짐
- 특히 파티클 외곽의 soft edge, glow, light bloom 등은 아예 출력되지 않음
2. 원인 분석
2-1. Unity 기본 알파 블렌드 구조
Unity 기본 파티클 셰이더(URP/Legacy Unlit 포함)나 lilToon 등은
대부분 다음과 같은 Blend 방식 사용:
- 알파값에 따라 색이 섞이는 방식
- 알파가 0에 가까운 픽셀은 시각적으로 흐림 → 파티클 외곽에 주로 사용됨
이 설정은 픽셀의 알파값을 기준으로 전경/배경 색을 섞는 전통적인 알파 블렌딩 방식이다.
파티클 외곽은 자연스러운 fade-out 효과를 위해 알파값이 0.0 ~ 0.2 수준으로 낮게 설정되어 있다.
즉, 색은 존재하지만 알파는 거의 0에 가까운 픽셀들이 다수 존재함.
2-2. 송출 프로그램의 알파 해석
- OBS, Spout2, RenderTexture 기반 송출 구조는 알파값이 0인 픽셀을 '존재하지 않는 픽셀'로 간주
- 알파 기반 크로마키 합성에서도 같은 현상 발생
- 이 구조가 Unity의 부드러운 파티클 외곽 처리와 충돌함
OBS, Spout2, NDI 같은 송출 파이프라인은 보통 다음 두 가지 방식 중 하나로 알파를 해석한다:
- 알파 채널을 곧 투명도 마스크로 해석
→ 알파값이 0에 가까우면 해당 픽셀은 렌더링하지 않음 - Premultiplied Alpha 방식으로 해석
→ 색 정보가 알파와 함께 곱해졌다고 가정하고 해석
이러한 처리 방식은 Unity의 기본 파티클 Blend 구조와 상충된다.
결과적으로, 알파가 낮은 픽셀 = 없는 픽셀로 인식되어 잘려나간다.
2-3. 캐릭터 안팎에 따른 시각 차이
이 부분이 가장 중요함.
- 파티클이 캐릭터 바디 위에 존재할 경우:
- 뒷배경(캐릭터 바디)은 불투명 객체 → 알파가 낮아도 시각적으로 색이 섞이므로 보임
- 파티클이 캐릭터 밖으로 벗어날 경우:
- 뒷배경은 투명한 Skybox나 BG → 알파가 낮으면 색 자체가 송출되지 않음
즉, 뒤에 뭐가 있느냐에 따라 색이 보이거나 안 보이는 차이가 발생함.
OBS나 Spout 환경에서는 배경이 ‘없음(투명)’으로 처리되기 때문에,
파티클이 캐릭터를 벗어나는 순간 색이 0으로 남는 픽셀은 그대로 잘려버린다.
3. 해결 방법
3-1. Blend 모드 변경
쉐이더 수정 가능할 경우, 아래 설정으로 대체
- 알파가 0이라도 색 정보는 유지됨
- 송출 파이프라인에서도 픽셀이 보존됨 = “이 픽셀은 존재한다”는 사실을 송출 프로그램에 명시함
- 특히 첫 번째 방식은 알파=0이라도 색은 출력되도록 강제
왜 One을 앞에 넣는가?
Blend 문법:
- SrcFactor는 픽셀 자체의 색상에 곱해지는 값
- DstFactor는 이미 렌더 타겟에 있던 색에 곱해지는 값
기본은:
Blend SrcAlpha OneMinusSrcAlpha
// 결과: (Source * SrcAlpha) + (Dest * (1 - SrcAlpha))
Blend One OneMinusSrcAlpha
// 결과: (Source * 1) + (Dest * (1 - SrcAlpha)) → Source 색은 무조건 보장됨
이 구조가 OBS나 Spout 같은 알파 민감한 송출 파이프라인에서도 파티클이 사라지지 않게 해주는 핵심이다.
3-2. ZWrite / ZTest 옵션 조정
- ZWrite Off
- ZTest Always (필요 시)
깊이 버퍼와의 충돌로 인해 출력되지 않는 현상 완화
일부 셰이더나 URP 환경에서는 이 설정 없이 파티클이 뒤에 묻히는 현상 있음
4. lilToon 사용 시 조정 방법
- Render Mode: Transparent
- Blend Mode: One / OneMinusSrcAlpha 수동 지정
- ZWrite: Off
- Ignore Projector: On
- Outline: Off
이 설정으로 대부분의 송출 문제는 해결 가능
단, lilToon 내부 처리 구조에 따라 일부 효과는 여전히 영향 받을 수 있음
5. 대체 방법
5-1. 색상 기반 크로마키 우회
- 배경색을 고정 색상(녹색 등)으로 설정
- Blend Off + Unlit 처리
- OBS에서 크로마키 필터로 제거
5-2. RGB/Alpha 패스 분리
- Shader에서 RGB / Alpha Pass를 따로 구성
- RenderTexture 또는 후처리에서 별도 합성
복잡하긴 하지만, 방송 품질을 높일 수 있음
6. 테스트 환경
- Unity 2019.4.31f1 / 2021.3 LTS
- URP 7.x, 12.x
- lilToon 1.3.7
- OBS Studio 30.x
- Spout2 Unity Plugin
- RenderTexture (ARGB32 / RFloat Alpha Mask)
7. 결론 정리
기본 상태 | 수정 후 | |
Blend | SrcAlpha OneMinusSrcAlpha | One OneMinusSrcAlpha |
ZWrite | On | Off |
알파가 낮은 픽셀 | 송출 시 잘림 | 색상 유지됨 |
캐릭터 밖 파티클 | 사라짐 | 정상 출력 |