CrossGaussian
원격 협업에서 360° 카메라는 현장 전체를 한 번에 보여 주지만, 깊이 정보가 없어 사용자가 카메라 위치를 벗어나 자유롭게 둘러보기는 어렵다. 반대로 3D 장면은 시점을 자유롭게 옮길 수 있지만, 현재 상황을 실시간으로 전달하지 못한다. CrossGaussian은 실시간 360° 영상과 사전에 재구성한 3D Gaussian Splatting 장면을 VR 환경에서 함께 보여 주며 두 방식의 빈틈을 보완한 연구 프로토타입이다.
ISMAR 2025 Research Demonstration 제출 영상.
내가 맡은 일
연구 방향과 논문 작업은 변재현과 지도교수가 주도했다. 나는 전달받은 연구 방향을 실제로 작동하는 시스템으로 옮기는 일을 주로 맡았다.
- Insta360 카메라 영상을 Unity 텍스처로 전달하는 스트리밍 경로
- Gaussian Splatting 장면에 포인트 라이트 그림자를 더하는 렌더링 확장
- 3DGS 장면과 360° 영상 레이어를 전환하고 혼합하는 로직
- Meta Quest 실행 환경 연동
- 각 구성요소를 하나의 데모로 통합하고 ISMAR 현장 시연을 준비하는 작업
Azure DevOps의 브랜치 중복을 제거해 집계한 결과, 내 커밋은 Insta360 저장소 77개 중 57개, CrossRealityParallax 저장소 42개 중 25개, UIST 제출 전 SharedReality 개발 구간 22개 중 14개였다. 커밋 수만으로 연구 기여 전체를 설명할 수는 없다. 다만 세 저장소 모두에서 과반을 차지한 이력은 내가 시스템 구현과 통합을 주도했다는 점을 뒷받침한다.
카메라 영상을 Unity로 가져오기
Insta360 카메라가 보내는 영상은 Unity에서 곧바로 쓸 수 있는 데이터가 아니었다. 카메라 스트림을 네이티브 코드에서 받고, 영상 프레임을 Unity 렌더링 경로에 맞는 텍스처로 전달해야 했다. 카메라 SDK의 콜백부터 네이티브 플러그인, C# 스크립트, Unity 렌더 스레드까지 실행 순서가 어긋나지 않도록 조정했다.
CrossGaussian에 들어간 후속 구현은 Direct3D 11 네이티브 텍스처를 사용해 NV12 프레임을 RGBA로 변환하는 경로를 중심으로 구성했다. 독립적으로 정리한 Direct3D 12 버전은 Insta360–Unity 스트리밍 플러그인에 공개했다. 이 버전은 FFmpeg와 CUDA로 H.264를 디코딩하고 NPP로 색 공간을 변환하지만, GPU 메모리에서 CPU를 거쳐 다시 Unity 텍스처로 올라가는 복사가 남아 있다. 두 구현은 시기와 구조가 달라 같은 파이프라인으로 묶지 않았다.
Gaussian splat에 그림자 만들기
기존 UnityGaussianSplatting 렌더러는 Gaussian splat을 실시간으로 그릴 수 있었지만, 포인트 라이트가 만드는 동적 그림자는 지원하지 않았다. 주변 환경과 splat 장면을 함께 보여 주려면 조명에 따른 깊이감이 필요했다.
포인트 라이트를 중심으로 여섯 방향의 깊이를 cubemap에 기록하고, 메인 렌더링에서 이 깊이와 현재 fragment를 비교하는 방식을 택했다. Compute Shader에서는 여섯 면에서 공통으로 쓰는 world position과 3D covariance를 먼저 한 번 계산했다. 이후 각 cubemap 면에 필요한 clip-space 위치와 화면상의 ellipse 축만 따로 구했다. 같은 계산을 여섯 번 반복하지 않도록 공통 단계와 면별 단계를 나눈 것이다.
가장 오래 붙잡고 있던 문제는 좌표계였다. C#에서 만든 view matrix와 projection matrix를 그대로 GPU에 넘기면 cubemap의 일부 면에서 그림자 방향이 뒤틀렸다. Unity의 CPU 좌표계와 GPU projection 규칙이 다르다는 점을 확인한 뒤, GPU가 기대하는 형태로 행렬을 다시 구성하고 GL.GetGPUProjectionMatrix()를 적용해 문제를 해결했다.
이 구현은 UnityGaussianSplatting-Shadow에 공개했다. 다만 3DGS 렌더러 전체를 새로 만든 것은 아니다. Aras Pranckevičius의 UnityGaussianSplatting을 바탕으로 포인트 라이트 그림자 생성과 적용 과정을 확장했다.
두 장면을 자연스럽게 오가기
CrossGaussian에서는 360° 영상이 현재 현장의 모습을 보여 주고, 3DGS 장면이 자유로운 시점 이동을 맡는다. 사용자는 상황에 따라 한쪽을 선택하거나 두 장면을 겹쳐 볼 수 있어야 했다. 이를 위해 색상과 투명도를 조절해 영상과 3DGS 레이어를 전환하고 혼합하는 로직을 구현했다. Meta Quest에서도 같은 흐름으로 탐색할 수 있도록 실행 환경과 입력을 연결했다.
각 기술을 따로 실행하는 것보다 하나의 시스템으로 묶는 과정이 더 어려웠다. 카메라 프레임이 들어오는 시점, Unity 렌더링 순서, 3DGS 계산량, VR 기기의 실행 조건을 한꺼번에 맞춰야 데모가 끊기지 않았다.
ISMAR 현장 데모
ISMAR 2025에서는 데모 부스를 직접 운영했다. 시연 전에는 Meta Quest에서 영상 스트리밍과 3DGS 렌더링, 입력이 함께 작동하는지 확인했다.

Meta Quest로 현장 데모를 확인하는 모습.
시연 중에는 방문객에게 시스템 구성을 설명하고 질문에 답했다.

ISMAR 2025 현장에서 방문객에게 데모를 설명하는 모습.
결과와 범위
CrossGaussian은 같은 시스템으로 두 개의 Adjunct 결과를 냈다.
- IEEE ISMAR Adjunct 2025 Research Demonstration: 공동 제1저자
- ACM UIST Adjunct 2025 Poster: 제2저자
ISMAR 논문과 UIST 논문은 제목과 저자진이 같은 연구다. 서로 독립된 두 프로젝트로 세지 않았다. 나는 핵심 시스템 구현과 ISMAR 현장 시연에는 참여했지만, 사용자 실험과 통계 분석, 논문 작성, UIST 포스터 발표는 맡지 않았다.
아직 공개된 자료에는 같은 조건에서 반복 측정한 end-to-end latency, dropped frame, CPU·GPU 사용률이 없다. 그림자 적용 전후의 성능 차이도 정량화하지 못했다. 다시 작업한다면 카메라 입력부터 HMD 표시까지 구간별 시간을 측정하고, 장시간 실행 안정성과 프레임 손실을 함께 기록할 것이다. 공개 Direct3D 12 플러그인에 남은 GPU–CPU 왕복 복사를 줄이는 작업도 다음 과제로 남아 있다.