본문 바로가기
3D-GS

[논문 리뷰] SVRaster (CVPR 2025) : Voxel기반 랜더링

by xoft 2025. 3. 16.

Sparse Voxels Rasterization: Real-time High-fidelity Radiance Field Rendering, Cheng Sun, Nvidia, CVPR 2025

 

Nvidia에서 발표한 연구로, voxel기반으로 scene을 구성한 novel-view synthesis 연구입니다. 전체적인 형태를 아래 그림을 통해 가늠해 볼 수 있습니다. scene이 서로 다른 크기의 voxel로 구성되어 있고, voxel rasterization을 통해 실제 이미지를 랜더링하게 됩니다.

 

Novel-view synthesis 분야의 대표적인 논문들로 NeRF(link)와 3DGS(link)가 있죠. 이 대표 논문들의 여러 세부 개념들을 차용해서 만들어진 연구입니다. 랜더링 속도, 퀄리티, 학습 속도 관점에서 높은 성능을 달성하게 됩니다.

왼쪽을 보면, 본 연구가 LPIPS↓(link) 관점에서 퀄리티가 가장 좋고, 랜더링 속도도 3DGS만큼 빠른 것을 볼 수 있습니다.
오른쪽 표에선, ours fast-train모델을 보면 LPIPS/PSNR/SSIM 퀄리티(link)를 높게 유지하면서도 학습속도가 INGP(link)만큼 빠른 것을 볼 수 있습니다.

 

어떻게 이런 지표들을 달성 할 수 있었는지 알고리즘을 살펴보도록 하겠습니다.

 

 

Overview

논문에 전체적인 아키텍처 그림 없이 알고리즘 설명이 길게 써진 논문이라서 별도로 목차를 만들어봤습니다.

 

Sparse Voxel Rasterization : Voxel을 어떻게 랜더링 하는가?

  • Scene Representation                  : Voxel 자료구조
  • Rasterization Algorithm                 : Voxel 랜더링 방법

Sparse Voxel Optimization : Voxel parameter 를 어떻게 결정하는가?

  • Voxel max sampling rate               : Voxel 샘플링 비율
  • Scene Initialization                        : Voxel parameter 초기값
  • Adaptive Pruning and Subdivision : Voxel 갯수 줄이거나 늘이는 방법
  • Optimization Objectives                 : 학습 Loss
  • Extract a mesh                               : (활용) 3D Object 추출

 

 

<Sparse Voxel Rasterization>

Scene Representation

Voxel Structure

알고리즘을 구성하는 scene을 표현하는 voxel 구조에 대해서 먼저 다룹니다. parent-child관계가 없는 Octree를 사용합니다. Octree는 3차원 육면체를 1/8등분해서 8개의 육면체를 만드는 tree입니다. 아래 왼쪽 그림은 Octree에 관한 기본적인 설명 이미지입니다. 여기서 parent-child 관계성만 없다고 보면 됩니다.


오른쪽 그림은 예시로 NeRF계열의 PlenOctree(link) 논문의 한 장면을 갖고 왔습니다. Scene을 구성 할 때, Octree로 구성하게 되면, 물체가 있는 곳에서 세밀하게 표현하고 없는 곳에선 sparse하게 표현함으로써, 속도와 퀄리티 모두에 이점을 가질 수 있습니다. 본 논문 SVRaster에서는 기본 Octree Level은 16으로 설정해두고 있습니다.

 

 

Density Parameter

각 voxel당 8개의 corner는 density parameter값을 갖게 됩니다. 인접한 voxel의 corner는 값을 공유합니다.

다른 novel-view synthesis와 동일하게 여러개의 이미지를 COLMAP(link)으로 카메라 포즈가 있다는 전제가 깔려있습니다.  카메라에서 ray를 그렸을 때 샘플링되는 point들은 density기준으로 유효한 voxel들에서만 계산하며, point가 속하는 voxel의 corner point의 density값으로 interpolation(=weighted-sum)해서 alpha값을 계산합니다.

alpha값은 density과 반비례 관계이기 때문에, 1-exp(x) 수식의 형태를 갖습니다.

interpolation 한 후에 activation 함수를 별도로 설계했습니다.

  • Softplus와 유사하나 계산량이 적고 빠르며, CUDA에서 더 효율적으로 동작합니다.
  • density 값이 0보다 작은 경우, 작은 값을 유지하여 더 디테일한 밀도 표현 가능합니다.
  • non-linear activation으로 Sharp density field를 만들어 경계를 명확하게 만들었습니다.

전체적으로 alpha 계산하는 부분은 NeRF계열의 Plenoxel (link)개념과 유사해보이네요. point를 샘플링하는 방법에 대해선 뒤에서 다루겠습니다.

 

 

Color Parameter

view dependent한 색상표현을 위해 Sperical Harmonic (link)를 사용했습니다. 여기선 corner point마다 색상값이 아닌 voxel마다 독립적으로 Sperical Harmonic (SH) 함수를 가집니다. SH degree인 $N_{shd}$는 3입니다. 

color 계산 수식입니다.

이렇게 SH로 color값과 density parameter로 alpha값이 계산된다면, alpha blending으로 pixel의 color를 표현 할 수 있습니다.

NeRF와 3DGS에서 사용한 수식입니다. 짧게 설명하자면, T는 Transmittance고 N은 이미지 pixel 1개에서 샘플링되는 point들의 갯수입니다. 샘플링된 포인트에 도달하기전까지의 누적 투명도 T와 샘플링된 포인트의 투명도로 color를 표현합니다.

 

NeRF의 경우 카메라에서 primitive(=3D point)에 관한 direction vector를 사용했지만, 여기선 3DGS처럼 primitive(=voxel)에서 카메라로의 direction vector를 사용해서 계산 효율성을 만들었다고 합니다. 또한 SH로 설계하면서 메모리는 많이 가져가지만 빠른 랜더링을 할 수 있다는 장점을 갖고 있습니다.

 

density와 color는 학습되는 parameter입니다. 이 값을 최적화하면 모델이 생성됩니다. 다음에 소개드릴 normal과 vector는 density값을 활용해서 만들 수 있습니다.

 

 

Normal

NeRF와 3DGS에선 volume density를 간접적으로 계산하지만, 여기선 직접적으로 계산합니다. normal도 voxel마다 독립적으로 값을 가지며, color와 차이는 view-independent한 점입니다.

이렇게 설계했을 때의 장점은, CUDA에서 closed-form으로 gradient를 빠르게 계산 할 수 있다라는 점과 물체의 표면 퀄리티를 높이고 부드러운 경계 생성이 가능하다는 점입니다. 일반적으로 normal map을 만들게 되면, mesh생성을 할 수 있고, 조명효과(shading, lighting)를 적용 할 수 있습니다.

 

 

Voxel Depth

NeRF와 3DGS에선 volume rendering으로 depth를 계산했었습니다. 여기선 voxel내부에서 K개의 포인트를 샘플링하고, (카메라 중심에서) 깊이 기반으로 가중 평균을 했습니다. voxel마다 depth값을 가지면서 view-depedent하게 설계했습니다.

특정 거리의 픽셀을 더 선명하게 렌더링 할 수 있다는 장점이 있습니다. 일반적으로 depth map을 만들게되면 깊이 정보로 3D mesh 변환을 할 수 있고, 거리 기반 효과(안계, 빛 감소) 등을 적용 할 수 있습니다.

 

 

 

Rasterization Algorithm

여기선 voxel 랜더링에 관한 방법을 소개합니다.

전체 Process입니다.

  • Projection to image space : 이미지를 16x16픽셀 단위의 Tile로 나누고, Tile에 속하는 voxel들을 projection합니다. 
  • Pre-processing voxels : point density / voxel color / voxel normal 계산합니다.
  • Sorting voxels : Morton 정렬을 사용해서, voxel을 정렬합니다.
  • Rendering pixel : alpha composition 을 사용해서 랜더링합니다.

projection to image space는 3DGS개념을 차용한 듯 합니다. CUDA병렬처리에 용이한 구조입니다. pre-processing voxels와 Rendering pixel은 앞절에서 설명드린 내용이라 sorting voxels에 대해서만 소개하겠습니다.

 

 

Sorting Voxels

3DGS에선 3D gaussian을 image plane으로 projection하기에 sparse 한 영역에서는 깊이를 제대로 획득하지 못하면서 artifact가 발생합니다. 본 논문에서는 Morton Sorting을 이용해 랜더링 할 voxel 순서를 정렬해서, 깊이의 정확도를 향상합니다.

 

일반적인 Morton sorting은 공간적으로 가까운 값들을 메모리에 연속적으로 배치하는 기법입니다. 예를들어 1920x1440이미지에서 (0,0)과 (1,1)이 공간적 연관성이 높은데, 메모리상에는 1*1440+1 거리 차이가 나게됩니다. 이를 개선하여 z형태로 메모리를 참조하게 만들어, z의 가로길이가 30이라면, 1*30+1 거리로 줄어들게됩니다. 일반적으로 CUDA low-level 코드에서 사용되고 있다고 합니다. 

논문으로 다시 돌아와서,

카메라에서 ray를 그려 voxel의 순서를 정할 때, 카메라와의 거리 z기반으로 정렬하게 될 경우, voxel의 중심을 기준(a상단)으로 하든 corner을 기준(a하단)으로 하든 정렬 순서가 올바르게 만들어지지 않습니다.

 

논문에서는 Tile(16x16)별로 Tile에 속하는 voxel들을 선별하고, 그림c에서 보는 것처럼 해당 voxel들의 메모리 순서에 따라 sorting하게 됩니다. 그림d에선 메모리 할당 순서를 보여줍니다. (z길이가 궁금한데 못 찾겠네요.). 그림b에서는 x,y,z가 음수인지 양수인지에 따라 해당 분면에는 동일한 순서를 보여준다는 것을 보여줍니다.

 

이렇게 설계할 경우, voxel 크기에 상관없이 랜더링 순서를 보장 할 수 있었고 artifact를 줄일 수 있다고 합니다.

 

 

Anti-aliasing

추가적으로 aliasing artifact를 줄이기 위한 방법이 짧게 소개되고 있습니다. $h_{ss}=1.5$배 높은 해상도로 랜더링 한후, 원본 해상도로 바꾸는 방법으로 anti-aliasing 구현했다고 합니다.

 

 

 

<Sparse Voxel Optimization>

Sparse Voxel Optimization : Voxel parameter 를 어떻게 결정하는가?

  • Voxel max sampling rate               : Voxel 샘플링 비율
  • Scene Initialization                        : Voxel parameter 초기값
  • Adaptive Pruning and Subdivision : Voxel 갯수 줄이거나 늘이는 방법
  • Optimization Objectives                 : 학습 Loss
  • Extract a mesh                               : (활용) 3D Object 추출

글 앞부분에서 정리한 목차입니다. 이제 voxel을 학습하는 방법에 관해 다뤄보겠습니다.

 

Voxel Max Sampling Rate

Voxel별 샘플링 비율 설계에 관한 내용입니다. voxel과 가장 가까운 카메라 거리와 voxel크기에 따라 voxel별로 다른 갯수로 point를 샘플링합니다.

결론적으로 voxel과 가장 가까이에 있는 카메라 pixel크기만큼 voxel별 point를 샘플링합니다. 수식을 풀어서 설명하자면, image plane에서 1개 pixel을 voxel 중심으로 projection했을 때 pixel의 크기($v_{interval}$)를 계산하고 voxel 크기/pixel크기 비율을 계산합니다. 특정 voxel을 포함하는 모든 카메라에 대해서 이 비율을 계산한 후, 가장 높은 비율값을 voxel의 샘플링 개수로 지정합니다. $v_{interval}$ 수식이 복잡해 보이는데, 거리와 카메라fov 각도를 삼각함수로 계산한 수식입니다. fov를 0.5만큼 쓰면, 직각이 만들어지고, tan를 써서 v_interval의 0.5크기만큼을 계산하는 방식으로 풀어 볼 수 있습니다.

 

 

 

Scene Initialization 

학습 전 density와 color 초기값, voxel 배치 초기값에 대해 다룹니다.

density는 학습되면서 0~1사이의 값이 되므로, 0에 가깝게 음수로 설정합니다. color의 경우 coefficient를 0으로 설정합니다. voxel의 크기는 한정된 scene크기를 가진 bound scene과 크기가 제한없는 unbound scene에 따라 다르게 설계합니다.

 

bound scene경우에는 균등한 크기로 dense한 voxel을 생성합니다. octree level인 $h_lv$ 를 6으로 설정합니다. 그 후에 학습 이미지에 관측되지 않는 영역에 대해 voxel을 제거한다고 합니다. 제거 방법에 대해 나와있지 않아서 segmentation mask에 포함된 영역을 포함하지 않을 경우 제거하지 않을까 추측해봅니다.

 

unbound scene경우엔 main영역과 background 영역으로 나눕니다.

main영역은 bound scene과 같이 $h_lv = 6$로 voxel을 샘플링하였고, background 영역의 세부수치는 $h_out = 5$, $h_ratio = 2$ 입니다.

 

 

 

Adaptive Pruning and Subdivision

3DGS에선 primitive인 gaussain을 pruning, subdivision 했었다면, 본 논문에선 primitive인 voxel을 pruning, subdivision 했습니다.

 

Pruning

불필요한 voxel을 제거해서 계산량을 줄이고 학습 속도를 높이는 기법입니다. voxel마다 아래수식 Maximum Blending Weight를 계산하고 특정 임계값($h_{prune})보다 적을 경우 제거합니다.

$T_i$는 복셀의 누적투과율인 transmittance이고, α는 voxel의 투명도입니다. 위에 color parameter 파트에서 언급한 alpha blending에서 color c를 뺀 수식입니다. 다른 점은 모든 카메라에서 가장 높은 값을 계산한다는 점입니다. $h_{prune}$는 0.0001 에서 0.05 으로 증가시키면서 학습을 했습니다. fast randering 버전에선 $h_{prune}$가 0.15까지 설정해서 빠른 랜더링이 가능하게 했습니다.

 

pruning시, color값 경우 단순히 해당 voxel의 SH값을 제거하였고, density의 경우 8개 corner값 중복을 제거한 후 평균값 계산해서 주변 voxel의 corner값을 업데이트 했습니다.

 

 

Subdivision

voxel을 세분화하여 더 정밀하게 scene을 표현하기 위한 기법입니다. 아래 두가지 기준에 만족하면, subdivision을 하게됩니다.

1) training loss의 gradient가 큰 voxel

2) view-dependent한 alpha 변화량이 큰 voxel

구체적으로 아래 수식을 통해  priority를 계산하고 상위 $h_{percent}=5$만 subdivision을 합니다. 학습하면서 $h_{percent}$를 7배까지 증가시킵니다.

몇개의 pixel에 overfitting을 방지하기 위해서, voxel별 sampling rate인 $v_{rate}$가 2미만인 경우 priority를 없애고, 학습을 진행하면서 $v_{rate}$가 4미만인 경우 priority를 없애는 방식으로 진행했다고 합니다.

 

subdivision시, color값의 경우 단순히 해당 voxel의 SH coefficient를 자식 voxel로 복사하였고, density의 경우 8개의 corner 값을 interpolation했습니다.

 

 

Optimization objectives

λ는 ssim=0.02, T=0.01, dist=0.1, R=0.01, tv=1e-10입니다. pixel loss인 MSE(mean squared error)를 높은 비율로 쓰는 것을 볼 수 있습니다.dist의 경우 10K iteration후부터 적용했다고 합니다.

 

 

 

Extract a mesh

grid기반 mesh extraction 기법들을 적용 할 수 있습니다. 그중에 하나인 Marching Cube(link)알고리즘을 사용해서, grid내 voxel의 8개 corner에 따라 density값에 따라 사전 정의된 triangles를 사용하는 방식으로 mesh를 추출합니다. octree level이 다를 경우엔 triange이 연결되지 않을 수가 있는데, 이 경우엔 단순히 큰 level의 voxel을 subdivision하여 fine하게 만드는 방식을 쓸 수 있습니다.

 

이 경우 surface가 매끄럽지 못하게 때문에, TSDF-Fusion을 추가로 적용했습니다. TSDF(Truncated Signed Distance Function)은 표면까지의 거리와 부호를 저장하는 함수입니다. TSDF-fusion에 대한 설명이 명확히 되어있진 않은데, ray를 따라 voxel의 밀도 값이 변경되는 지점을 찾아(=TSDF가 0인 영역으로 보고) surface를 추출하는 형태로 생각됩니다. 그 후에 marching cube를 적용해서 mesh로 변환합니다.

 

알고리즘은 여기까지입니다. 마지막으로 실험과 ablation study를 소개하겠습니다.

 

 

 

 

Experiments

본 블로그 글의 inroduction부분에서 언급했던 표입니다. Mip-NeRF360데이터셋에 대해서 평가했습니다. fast-rend와 fast-train의 차이만 언급하자면, fast-rend는 pruning시 제거 할 density의 thresould 기준값인 $h_{prune}$을 0.15로 3배 올려서 FPS를 2배 올렸고, fast-train에선 모든 iteration에서 0.3배 올리는 방식을 사용해서 학습 속도를 3배 향상시켰다고 합니다. 이 경우 둘 다 속도는 대폭 향상시키면서 성능은 약간 감소하는 것을 볼 수 있습니다. 그래도 다른 기법보다 높은 LPIPS수치를 달성하는 것을 볼 수 있습니다.

 

 

 

Ablation Studies

voxel 개수는 퀄리티와 속도를 결정하는 중요한 요소입니다. Mip-NeRF360데이터셋에 대해 subdivision을 하지 않고 균일한 voxel 개수를 사용했을 때, 퀄리티와 속도에 관한 내용입니다. voxel 개수를 증가시키면 퀄리티가 좋아지지만 랜더링 속도는 떨어지고, 1024^3까진 했을 땐, 24GB GPU에서 Out of Memory가 발생하는 것을 볼 수 있습니다. 

본몬 내용 외 appendix에 많은(10개가 넘는) ablation studies가 있지만 생략하겠습니다.

 

 

 

Mesh Reconstruction

TSDF-Fusion과 Marching Cube를 사용한 본 논문의 방식이, 기존 mesh extraction방법보다 더 빠른 속도와 높은 퀄리티를 보임을 보여주고 있습니다. Tanks&Temples는 large-scale의 데이터셋이고, DTU는 object-scale의 데이터셋(link)입니다.

 

 

 

Closing..

SVRaster가 novel-view synthesis 분야에서 유명한 NeRF와 3DGS 논문들의 성능들을 모두 능가한 연구라 생각됩니다. 이 논문 기반으로 개선된 연구가 많이 나올 것 같다는 생각이 드네요. 3DGS가 나올 당시 dynamic연구가 바로 후속으로 나왔는데, voxel형태를 dynamic하게 만드는 게 어려워보이는데, 적용 될 수 있을지 모르겠네요. large scale연구가 될지 경량화 연구가 될지 다음에 나올 응용 연구들이 기대되는 논문이었습니다.

댓글