3D Gaussian Splatting을 Unreal·Unity 실시간 배경 에셋으로 이식하는 방법
3D Gaussian Splatting 데이터를 Unreal Engine과 Unity 실시간 배경으로 가져오는 파이프라인을 정리한다. PLY 정리, 셰이더 렌더링, LOD·오버드로우·라이팅 한계와 최적화 기준까지 다룬다.

핵심 요약
3D Gaussian Splatting(3DGS)은 메시·텍스처 자산이 아니라 수많은 3D 가우시안 타원체를 알파 블렌딩으로 투영하는 장면 표현이다. 따라서 Unreal Engine과 Unity에 이식할 때는 PLY를 정점 데이터로 읽고 카메라 공간에서 화면 크기 타원으로 확장한 뒤 depth sorting 또는 근사 정렬로 합성하는 전용 렌더러가 필요하다. 정적인 원거리 배경에는 매우 효과적이지만 충돌·그림자·동적 조명까지 맡길 수 없으므로 게임플레이 영역은 기존 메시와 함께 구성하는 방식이 안전하다.
3D Gaussian Splatting은 왜 게임 엔진의 일반 에셋으로 바로 가져올 수 없을까?
일반적인 FBX 또는 glTF 에셋은 삼각형, UV, 머티리얼, 텍스처를 중심으로 구성된다. 반면 3DGS 학습 결과는 보통 PLY에 위치, 회전, 스케일, 불투명도, 색 또는 spherical harmonics(SH) 계수를 저장한다. 각 포인트는 점 하나가 아니라 방향과 크기를 가진 가우시안이다.
화면 좌표에서 가우시안의 가중치는 대략 다음과 같이 계산할 수 있다.
여기서 (\boldsymbol{\mu})는 중심 위치, (\Sigma)는 회전과 스케일로 만든 공분산 행렬, (\alpha)는 opacity다. 렌더러는 이 3D 타원체를 카메라에 투영해 화면 공간의 타원 쿼드로 그리고 뒤에서 앞으로 알파 합성한다.
| 구분 | 일반 메시 에셋 | 3D Gaussian Splatting |
|---|---|---|
| 기본 단위 | 삼각형 | 3D 가우시안 |
| 표면 정보 | 노멀, UV, 텍스처 | 위치, 회전, 스케일, opacity, SH |
| 깊이 처리 | Z-buffer 중심 | 정렬된 알파 합성 또는 근사 정렬 |
| 동적 조명 | PBR 파이프라인에 적합 | 캡처된 조명이 색에 포함되는 경우가 많음 |
| 게임플레이 | 충돌·내비게이션에 직접 활용 가능 | 별도 프록시 메시 필요 |
즉, PLY를 FBX로 단순 변환하면 3DGS의 시각적 특성이 사라진다. 렌더링 기술을 가져오는 일과 충돌용 자산을 만드는 일을 분리해야 한다.

Unreal Engine과 Unity 중 어떤 엔진 이식 경로를 선택할까?
가장 작은 구현은 이미 검증된 3DGS 플러그인 또는 렌더러를 사용하고 그 위에 배치·컬링·품질 설정만 추가하는 것이다. 직접 구현은 렌더링 제어가 필요한 경우에만 선택한다.
| 목표 | Unreal Engine | Unity |
|---|---|---|
| 빠른 배경 배치 | 플러그인 기반 Actor와 컴포넌트 | 패키지 기반 Component 또는 Renderer Feature |
| 커스텀 렌더링 | C++ FPrimitiveSceneProxy, RDG, HLSL | C# GraphicsBuffer, Compute Shader, HLSL |
| 카메라별 렌더 제어 | Scene View Extension 또는 렌더 패스 | URP Renderer Feature, HDRP Custom Pass |
| GPU 컬링 | RDG Compute Pass | Compute Shader와 DrawProceduralIndirect |
| 권장 용도 | 시네마틱·고사양 PC/콘솔 배경 | 모바일 제외 실시간 전시·PC/XR 배경 |
엔진 선택보다 중요한 것은 목표 플랫폼이다. 수백만 개 가우시안은 대역폭, 알파 블렌딩, 정렬 비용에 민감하다. 모바일에서 원본 품질을 그대로 재생하려 하기보다 고정 시점 배경은 영상 또는 임포스터로 대체하는 편이 더 낫다.
3DGS PLY를 실시간 배경 에셋으로 이식하는 3단계
1. 학습 결과를 게임용 데이터로 정리한다
먼저 PLY의 property 이름과 데이터 타입을 확인한다. 학습 도구마다 f_dc_0, f_rest_*, scale_0, rot_0, opacity 같은 필드 구성이 다르다. 엔진용 로더는 원본 순서를 가정하지 말고 property 이름으로 매핑해야 한다.
정적 배경이라면 다음 정리가 비용 대비 효과가 크다.
- 카메라에 거의 보이지 않는 가우시안을 제거한다.
- opacity가 낮고 기여도가 작은 가우시안을 임계값으로 제거한다.
- 멀리 있는 영역은 voxel grid 또는 중요도 기반 샘플링으로 밀도를 낮춘다.
- SH 차수를 낮춘다. 방향성 색 변화가 중요하지 않다면 DC 색상만 남기는 선택도 가능하다.
opacity를 sigmoid로 복원해야 하는 데이터 형식도 있다. 학습 결과가 logits를 저장한다면 렌더링 전에 다음 변환이 필요하다.
o가 이미 0부터 1 사이의 opacity라면 다시 sigmoid를 적용하면 안 된다. PLY exporter의 스키마와 학습 코드의 저장 방식을 함께 확인해야 하는 이유다.
2. GPU 버퍼와 셰이더 입력을 만든다
가우시안 하나당 최소 입력은 위치, quaternion 회전, 3축 scale, opacity, 색상이다. Unity에서는 GraphicsBuffer, Unreal에서는 Structured Buffer 또는 vertex buffer에 패킹한다. 대역폭을 줄이려면 색상은 UNorm8, opacity는 UNorm8 또는 float16, scale은 float16으로 양자화할 수 있다. 다만 quaternion 양자화는 회전 오차가 화면 타원 왜곡으로 보이므로 비교 렌더링으로 확인한다.
다음은 엔진과 무관한 HLSL 개념 예시다. 실제 구현에서는 화면 공간 공분산 계산과 컬링 결과를 함께 사용한다.
struct GaussianData
{
float3 position;
float4 rotation;
float3 scale;
float opacity;
float3 color;
};
float4 GaussianFragment(float2 localPos, float opacity, float3 color)
{
float weight = exp(-0.5 * dot(localPos, localPos));
float alpha = saturate(opacity * weight);
clip(alpha - 0.003);
return float4(color * alpha, alpha);
}
블렌딩은 premultiplied alpha를 기준으로 맞춘다. 예를 들어 색을 이미 alpha와 곱해 출력한다면 blend state는 One, OneMinusSrcAlpha 계열이어야 한다. straight alpha 출력과 premultiplied alpha blend를 섞으면 가장자리가 검거나 밝게 뜬다.
3. 정렬·컬링·LOD를 적용한다
정확한 알파 합성은 카메라 기준 뒤에서 앞으로 그리는 것이다. 그러나 매 프레임 수백만 가우시안을 완전 정렬하는 것은 비싸다. 실시간 배경에서는 다음 순서로 비용을 줄인다.
- 프러스텀 밖 가우시안과 너무 작은 화면 크기의 가우시안을 Compute Shader에서 제외한다.
- 깊이를 일정 개수의 bin으로 나누어 bucket sort 또는 radix sort를 적용한다.
- 먼 거리에는 더 적은 가우시안을 쓰는 LOD를 적용한다.
flowchart LR
A[PLY 로드] --> B[속성 검증·양자화]
B --> C[GPU Structured Buffer]
C --> D[Compute 컬링·LOD]
D --> E[깊이 bin 정렬]
E --> F[화면 공간 타원 스플랫]
F --> G[프리멀티플라이드 알파 합성]
완전한 per-pixel 정렬이 아니라 depth bin을 쓰면 일부 반투명 경계에서 순서 오류가 날 수 있다. 배경처럼 카메라가 장면을 크게 가로지르지 않는 용도에서는 이 타협이 보통 합리적이다. 빠른 이동과 가까운 전경 오브젝트가 많은 씬이라면 가우시안을 줄이거나 메시 기반 표현을 선택한다.

Unreal Engine에서 3DGS 배경을 구현할 때 확인할 점은?
Unreal Engine에서는 3DGS를 일반 Static Mesh로 취급하지 않는 편이 낫다. 전용 Actor 또는 Component가 PLY 데이터를 로드하고 렌더 스레드에서 가우시안 버퍼와 드로우 패스를 관리하도록 구성한다.
권장 배치 방식
- 3DGS Actor는 시각 전용으로 둔다.
- 바닥, 벽, 계단, 엄폐물은 단순 collision mesh를 별도로 둔다.
- 조명 반응이 필요한 소품과 캐릭터는 일반 Nanite 또는 Static Mesh로 둔다.
- 가우시안 배경은 고정된 노출값과 색보정 기준으로 검수한다.
특히 Lumen, Virtual Shadow Maps, Reflection Capture는 3DGS를 일반 불투명 표면처럼 해석하지 못할 수 있다. 배경이 이미 캡처 당시의 광원을 포함한다면 엔진 조명을 억지로 적용하는 것보다 skylight 강도를 낮추고 캐릭터만 별도 라이팅하는 편이 이질감을 줄인다.
Unity URP/HDRP에서 3DGS를 구현할 때 확인할 점은?
Unity에서는 렌더 파이프라인에 맞는 삽입 지점이 중요하다. URP는 ScriptableRendererFeature, HDRP는 Custom Pass를 통해 카메라 컬링 이후 또는 투명 오브젝트 전후에 패스를 넣을 수 있다.
배경 스플랫은 보통 투명 오브젝트와의 합성 순서가 문제다. 캐릭터가 3DGS 배경보다 앞에 있어야 한다면 캐릭터의 깊이 버퍼를 활용해 가우시안 프래그먼트에서 깊이를 비교해야 한다. 단, 반투명 스플랫은 깊이 쓰기를 켜면 스플랫끼리 끊겨 보일 수 있으므로 ZWrite를 무조건 켜는 해결책은 피한다.
| 상황 | 우선 적용할 해결책 |
|---|---|
| 캐릭터가 배경 뒤로 잘못 섞임 | 카메라 depth texture와 비교해 가우시안 프래그먼트 discard |
| 프레임이 급격히 하락함 | 화면 크기 임계값 컬링, 가우시안 수 감소, SH 차수 축소 |
| 가장자리가 검게 보임 | alpha 출력 방식과 blend state를 premultiplied alpha 기준으로 통일 |
| 카메라 이동 시 레이어가 뒤집힘 | 깊이 bin 수 증가 또는 정렬 품질 상향 |
실시간 3DGS 최적화에서 가장 먼저 측정할 항목은 무엇인가?
가우시안 수만 보면 원인을 놓치기 쉽다. GPU 프로파일러에서 다음 네 가지를 함께 본다.
- Visible splat count: 실제 드로우된 가우시안 수다. 총 개수보다 중요하다.
- Fragment overdraw: 큰 타원 스플랫이 겹칠수록 픽셀 셰이더 비용이 급증한다.
- Sorting 또는 binning 시간: 카메라 이동에 따라 CPU 또는 Compute 비용이 증가할 수 있다.
- GPU memory bandwidth: SH 계수와 큰 구조체는 버퍼 읽기 비용을 키운다.
실무적인 시작 기준으로는 목표 해상도에서 visible splat count, 평균 화면 반경, GPU 프레임 시간을 같은 캡처에서 기록한다. 한 가지 숫자만 줄이기보다 화면에 거의 기여하지 않는 큰 오버드로우를 제거하는 것이 더 큰 개선으로 이어지는 경우가 많다.
자주 묻는 질문 (FAQ)
3D Gaussian Splatting을 충돌 가능한 레벨로 바로 쓸 수 있나?
아니다. 3DGS는 시각 표현 데이터이므로 물리 충돌, 내비게이션, 레이캐스트를 위해 저해상도 collision mesh 또는 프록시 메시를 따로 만들어야 한다.
3DGS에 실시간 그림자를 받을 수 있나?
전용 셰이더와 깊이 표현을 추가하면 제한적인 통합은 가능하지만 일반 PBR 메시처럼 안정적인 그림자 수신체가 되지는 않는다. 정적 배경은 베이크된 외관으로 두고 동적 오브젝트의 그림자만 별도 바닥 프록시에 받는 구성이 단순하다.
PLY가 너무 커서 로딩 시간이 길면 어떻게 해야 하나?
원본 ASCII PLY를 런타임에 파싱하지 말고 빌드 단계에서 엔진 전용 바이너리 포맷으로 변환한다. 영역별 청크와 LOD를 만들면 카메라 주변 데이터만 스트리밍할 수 있다.
정리
3DGS를 Unreal Engine 또는 Unity의 실시간 배경으로 이식하는 핵심은 PLY를 메시로 바꾸는 일이 아니라 가우시안 데이터를 GPU에서 정렬·컬링·알파 합성하는 렌더링 경로를 마련하는 것이다. 배경의 시각 품질은 3DGS에 맡기고 충돌·내비게이션·동적 그림자·상호작용은 단순한 프록시 메시와 기존 게임 에셋에 맡기면 품질과 성능을 함께 관리하기 쉬워진다.



