반응형
개요
- 전통적인 Forward Rendering의 확장!
- 최종 Shading 전에 Light Culling 하나만 추가되었다.
- 많은 수의 Light를 Culling하고 Pixel에 영향을 주는 것만 저장한다.
- Light List를 구축하고 이를 Shader에서 사용하지만 메모리는 적게 쓴다.
Standard Forward, Standard Deferred
식상한 얘기들
- Forward
- Deferred에 비해서 Material 수는 큰 문제가 되지 않는다.
- 다만 Light 개수가 많아지면 성능에 문제가 된다.
- 또 Shader 조합이 폭발적으로 늘어날 수 있고 Light와 Geometry의 CPU 관리가 필요하다.
- Deferred
- Geometry 복잡도와 Light 복잡도를 분리하여 많은 Light를 그릴 수 있다.
- Shader 조합이 비교적 관리할만한 수준이다.
- 많은 수의 Material을 사용하기 힘들다.
- 많은 Memory Bandwidth가 필요하다.
- 투명한 물체 처리가 힘들고, HW MSAA가 어렵다.
하지만 이제 시대가 바뀌었다. ALU 성능이 늘어나고 GPU는 범용적인 용도로도 사용할 수 있도록 많이 유연해졌다. 조금만 고치면 Forward Rendering도 가능한 것이다!
구현
- Depth Pre-pass (Optional)
- 옵션이지만 상대적으로 무거운 Final Shading의 부하를 줄이기 위해서 수행하는 것을 추천
- Light Culling
- Final Shading
Light Culling
- Deferred Lighting의 Light Accumulation과 유사함
- Pixel에 영향을 주는 Light Index를 List로 만든다.
- 하지만 모든 Pixel에 대해 계산하는 것은 성능상 좋지 않기 때문에 화면을 Tile로 분할하여 Per-Tile 기준으로 수행한다.
- 해당 Tile에 영향을 주는 Light를 선별하기 위해 Grid Frustum을 생성
- Grid Frustum은 해상도가 변경될 때 1번만 계산하면 됨
- Modern GPU에서는 모든 구현을 GPU 상에서 가능하다.
Shading
- Light Culling 단계에서 Light List가 전달되었다.
- Material 정보는 Linear Structured Buffer를 통해서 전달 가능하다.
- 완벽한 Light, Material 정보를 하나의 단계에서 처리하기 때문에 Pixel Quality에 영향을 주는 문제가 모두 해결된다.
Light Culling
기존에 Forward Rendering을 사용하는 곳에서는 모두 사용이 가능하다.
- Gather approach
- 화면 해상도와 Depth의 min~max 범위에 따라 Tile을 나눈다.
- Tile 당 GPU Thread Group을 만들어서 병렬적으로 겹치는 Light에 대해서 체크한다.
- Light가 겹치면 TLS의 Local Register에 저장한다.
- 모든 Thread 작업이 끝나면 이를 Global Memory에 모은다.
- Light 개수가 적을 때 사용하면 좋다.
- Scatter approach
- 어떤 Tile이 Light에 영향을 받는지 Light와, Tile Index를 Buffer에 기록한다.
- Thread / Light
- Light Index 순서로 정렬
- 1의 Data를 Radix Sort를 이용해 Tile Index로 정렬한다. (Tile 당 Light가 필요하기 때문에)
- Light 개수가 많을 때 사용하면 좋다.
Thread Number in Thread Group
DirectX의 Compute Shader에서 사용되는 Thread 개수는 다음과 같은 제약이 있다.
- 64의 배수여야 한다. (=8x8)
- 1024개를 넘을 수 없다. (=32x32)
따라서 Thread Group의 Dimension은 8x8 ~ 32x32 사이로 결정하고 한 Thread가 NxN Pixel을 커버한다.
예를들어...
- 해상도 : 1280x720 Pixel
- Light Tile : 16x16 Pixel
- 80x45개의 Tile이 생성됨
- Thread Dimension : 16x16
- 5x2.8개의 Group이 필요
- 하지만 2.8개는 불가능하기 때문에 5x3개의 Group으로 계산
성능 비교 (vs Deferred)
- Prepass, Lighting, Final Shading 3개의 파트로 나누어서 측정하였다.
- Prepass, Lighting에서는 Forward+가 좋았고, Final Shading에서는 Deferred가 좋았다.
- Forward+ : Shading 단계에서 Light Index를 모두 읽어야 함
- Deferred : Shading 단계에서 Light Accumulation Buffer의 float4만 읽으면 됨
- 결론적으로는 Forward+가 메모리를 더 적게 쓰고 빠르다.
- 추후 GPU도 Memory Bandwidth를 늘리는 방향보다는 ALU 개수를 늘리는 방향으로 발전할 가능성이 많기 때문에 많은 메모리를 사용하는 Deferred 보다 Forward+가 더 적합할 것이다.
H는 고사양, L은 저사양을 나타내며 저사양 GPU에서 차이가 더 많이 난다.
모든 Rendering Technique이 Light 개수가 많아질수록 급격하게 느려진다.
Forward+는 큰 범위의 Light 보다는 작은 범위의 Light가 여러개 있을 때 좋다.
참고
https://takahiroharada.files.wordpress.com/2015/04/forward_plus.pdf
http://www.3dgep.com/forward-plus/
반응형
'Game Dev > Article' 카테고리의 다른 글
Tiled Rendering (0) | 2016.10.21 |
---|---|
Premultiplied alpha (0) | 2016.10.14 |
Inferred Lighting (0) | 2016.10.13 |
Light Pre-Pass Renderering (=Deferred Lighting) (0) | 2016.10.09 |