[그래픽스 최적화] Forward/Deferred/Forward+ Rendering
카테고리: Unity
Main Reference:
- 유니티 그래픽스 최적화
- Unity Korea
- Arm Mali GPU Training Series
🐳 Forward Rendering
Forward Rendering | Lighting |
---|---|
Forward Rendering은 유니티가 전통적으로 사용해오던 렌더링 방식이다. Forward rendering을 사용하게 되면 각 오브젝트마다, 각 라이트마다 드로우콜을 날리게 된다. 사이즈가 큰 프레임 버퍼에 빛을 누적시키는 방식이기 때문에 메모리 대역폭 문제가 발생할 수 있고, 같은 픽셀을 다시 칠하는 오버드로우가 엄청나게 발생하게 된다. 또한 라이팅 연산을 오브젝트마다 수행하기 때문에 모든 lighting 연산이 끝나야만 depth test를 진행할 수 있다(낭비되는 계산 발생). 여기까지만 들으면 이런 걸 왜 쓰나 싶지만 GPU 메모리를 크게 사용하는 단계가 없기 때문에 하드웨어의 성능을 타지 않고, 모바일 게임에 적합한 방식이다. Universal Render Pipeline(URP)에 들어오면서는 각 light에 대해 multi-pass 방식이였던 lighting 연산이 single-pass로 개선되기도 했다(드로우콜 하나로 퉁).
Light Component
Mode | Render Mode |
---|---|
유니티 Light에 대해 조금 더 자세히 들어가보자. 우선 Light Component에서 Mode를 설정해줄 수 있다. Baked 모드의 경우 움직이지 않는 static한 litght들에게 적용할 수 있다. Baking이란 용어는 유니티를 하다보면 종종 마주치는데, 런타임에 연산하지 않고 미리 연산하여 저장하는 기법을 베이킹이라고 한다. 따라서 매 프레임 동적으로 움직이는 오브젝트들에는 적용할 수 없다. Realtime 모드의 경우 말 그대로 매 프레임 움직이는 라이트에 적용되는 모드이다. 런타임에 매 프레임 실시간으로 연산되어야 하므로 성능에 가장 큰 영향을 미친다. 따라서 오브젝트마다 영향을 받는 light 갯수의 한계를 두고, 빛의 세기에 따라 정렬한 뒤 나머지는 culling한다. 또한 오른쪽 그림의 Render Mode에서 해당 라이트가 Important인지, Not Important인지 설정할 수 있다. 간단히 이야기하자면 Important로 설정한 라이트의 경우 per pixel 연산이 이루어지고, Not Important의 경우 per vertex 연산이 이루어진다. 당연하게도 per vertex 연산을 하게 되면 퀄리티가 떨어지지만 연산 비용은 훨씬 저렴해진다. Auto의 경우 들어오는 빛의 양에 따라 자동으로 important/not important를 구분해준다.
🐳 Deferred Rendering
Deferred Rendering은 말 그대로 라이팅을 지연시킨 렌더링 방식이다. Forward Rendering처럼 오브젝트별로 라이팅을 계산하지 않고, 파이프라인의 맨 끝단에서 한 번에 처리한다. 따라서 라이팅 비용이 오브젝트에 비례하게 증가하지 않고(증가하기는 함), depth test를 라이팅 이전에 처리하기 때문에 화면에 출력되는 픽셀 연산만 하게된다. 결과적으로 매우 효율적인 연산이지만 GPU가 Multi Render Targets(MRT)기능을 지원해야 한다. Geometry Buffer(G-Buffer)라고도 불리는 MRT에는 씬에 등장하는 모든 오브젝트들의 geometry 정보들을 쑤셔 넣어야 한다. 따라서 굉장히 큰 메모리를 잡아먹으며 모바일 환경에서는 아직 적용하기 힘들다고 한다. 여담으로 모니터의 해상도가 올라가면서 PC환경 또한 라이팅 연산의 부담이 커졌다고 한다.
Geometry Buffer
Mode | Render Mode |
---|---|
Deferred Rendering은 G-Buffer의 데이터를 기반으로 라이팅 연산을 진행한다. 따라서 per pixel 연산만 지원되고, dynamic light도 효율적으로 처리할 수 있다. 하지만 depth test를 미리 진행하므로 불투명한 오브젝트나 스킨같은 경우는 forward rendering으로 다시 그려줘야 한다.
🐳 Tile Based Rendering (TBR)
Tile Based Rendering(TBR)은 말 그대로 전체 프레임 버퍼가 아닌 작은 타일 단위의 버퍼를 이용하여 렌더링하는 기법이다. 하드웨어(GPU)단에서 지원해야 사용할 수 있고, 성능의 제약이 큰 모바일 환경을 위해 고안되었다. TBR이 등장한 이유를 알기 위해 먼저 모바일 환경에서의 한계를 알아야 한다. 모바일에서는 전력이 지속적으로 공급되지 않기 때문에 전력 소모에 대한 이슈도 크지만, 쿨링 시스템이 없기 때문에 발열 문제도 매우 중요하다. 칩이 일정 온도 이상으로 올라가면 쓰로틀링을 통해 강제로 성능을 감소시키기 때문이다. 이때 발열의 가장 중요한 요인 중 하나가 바로 메모리 대역폭(band-width)이다.
Forward Rendering | Tile Based Rendering |
---|---|
먼저 일반적인 forward 렌더링 방식을 살펴보자. 드로우콜이 날라오면 gpu에서 오브젝트에 대한 정보들을 처리하고, 프레임 버퍼를 읽어와 렌더링 정보를 저장한다. 따라서 드로우콜이 날라올 때마다 크기가 매우 큰 프레임버퍼를 읽고,써야하고 메모리 대역폭 문제가 발생하게 된다(심지어 unified memory라 vram도 없음). 반면 TBR의 경우 드로우콜이 날라오면 vertex shader(transform)만 거친 이후 구조화된 타일 리스트에서 해당 타일만 가져와 fragment shading을 진행한다. 그 후 타일 단위로 프레임 버퍼에 flush하게 된다. 따라서 타일 단위의 버퍼들만 움직이기 때문에 메모리 대역폭 이슈를 피할 수 있다.
Tile Based Deferred Rendering(TBDR)
TBR에 deferred rendering 기술을 결합한 TBDR 렌더링도 존재한다. 타일 단위로 lighting 정보를 모아두었다가 한 번에 처리하는 방식이다. 이때 알파테스트를 사용하게 되면 타일 가속의 효과를 기대하기 어렵다고 한다. 타일 단위로 정보를 모아두는 버퍼를 parameter buffer라고 하는데 모든 geometry 정보가 들어있지는 않은가 보다(이해 못함). 또한 post processing 과정에서 타일 밖에 존재하는 픽셀에 대한 정보가 필요할 수 있다. 이런 경우 타일 가속이 깨진다고 표현하더라.
🐳 Forward+ Rendering (Tiled Forward Rendering)
Forward+ Rendering | Lighting Heat Map |
---|---|
Forward+ Rendering은 forward rendering에 타일 개념을 적용한 기법이다. 가장 큰 차이는 light culling을 오브젝트 단위가 아니라 타일 단위로 수행한다. 오른쪽 그림을 보면 같은 오브젝트임에도 타일마다 영향을 받는 라이트의 갯수가 다르다는 것을 알 수 있다(빨갈수록 많음). 예를 들어 사이즈가 아주 큰 바닥 오브젝트에 forward+ 렌더링 방식을 적용하면 많은 라이트들을 굉장히 효율적으로 처리할 수 있다. 다만 유니티에서는 아직 베타 버전만 지원한다고 한다.
댓글 남기기