(Forward Rendering / Deferred Rendering)
Rendering Pipeline
랜더링은 이런식으로 업데이트 후 컬링을 거쳐 콜을 받아서 버텍스 쉐이더를 지나 프래그먼트 쉐이더 부분을 지나 하나의 비행기(FrameBuffer)를 그리고 또 반복해서 다른 비행기(FrameBuffer)를 그리고 또 남은 비행기(FrameBuffer)를 마저 그리고 나서 포스트 프로세싱 구간을 지나 Back Buffer에 넣고 다시 Back Buffer에 있는 것을 Front Buffer에 넣어주는 것이다. 이걸 매 프레임 마다 하게 되는 거지요. 더블버퍼링이건 트리플 버퍼링이건 마찬가지 이다.
Forward Rendering
: 모바일 기기에서는 많이 사용하는 전통적인 오브젝트 렌더링 방식
- 수많은 동적 라이트를 다루는 데에는 한계가 존재
- 이렇게 동적라이트를 적용 하기 위해서는 멀티패스로 성능을 포기 하거나 (Built-in)
- 싱글패스로 라이트를 제한하거나(URP)
위 이미지에서 빛이 툭!하고 사라지는 부분은 포워드 렌더링에서는 버텍스나 픽셀이 라이트에 반응하는 리미트에 걸려 잘못된 모습을 보이고 있는 것이다.
좀더 설명하자면 버텍스타 픽셀이 받을수 있는 라이트의 수는 최대 8개 까지인데 현재 2~30개의 동적 라이트가 설치되어 있다. 그래서 버텍스나 픽셀이 강도가 높은 라이트에 반응 하다가 갑자기 바뀌거나 없어지는 것 처럼 보이는 것이다.
이래서 포워드 랜더링 방식이 동적라이트를 다루는데 한계가 있다고 하는 것이다.
Deferred Rendering
: 라이팅 연산을 포워드 처럼 바로 하는게 아니라 지연시켰다가 한꺼번에 랜더링 하는 방식이다.
수 많은 동적라이트를 비교적 좋은 성능으로 처리 할수 있으며 PC나 콘솔 게임에서 널리 사용
기기의 성능이 어느정도 받쳐주어야 한다.
지오메트리 버퍼
: 랜더링의 라이트연산에 필요한 속성(position/Normals/Albede/Specular등등)을 여러개의 지오메트리 버퍼에 저장하여 가지고 있다가 라이팅 연산을 나중에 한꺼번에 하게 된다
이 방법은 라이팅 연산을 나중에 한꺼번에 하기 때문에 오브젝트가 라이트에 종속되지 않고 라이팅과 오브젝트가 분리되어 처리되기 때문에 그 갯수에 큰영향을 받지 않는다.
랜더투 텍스쳐의 개념 처럼 카메라에서 읽은 데이타를 텍스쳐로 그려서 이것을 사용하게 되는데 이게 랜더 타겟(Render Target)이라는 개념이다.
위 그림 처럼 현재의 화면을 랜더링 하기 위해 여기서는 3개의 G Buffer를 사용하여 담고 있다가 라이팅 연산을 한꺼번에 해서 마지막 이미지 처럼 랜더링을 하게 되는 것이다. 이것을 멀티랜더타겟 / MRT (Multi Render Targets)라고 한다.
하지만 대역폭을 사용하는 GBuffer갯수 만큼 필요하므로 메모리 대역폭 문제가 생길수 있다.
디퍼드의 라이팅 연산 설명
그렇다면 위에서 처럼 MRT(멀티랜더타겟)을 이용해서 어떻게 랜더링 되는지를 알아보자.
: 최종이미지의 한 픽셀을 랜더링 하기 위해서 각 속성의 G Buffer 픽셀위치에 있는 정보를 가져와서 라이팅 연산을 하여 최종 이미지의 픽셀을 그리는 방식이다.
라이팅 연산 구간 비교
디퍼드렌더링의 다른 예
여기서는 4가지 속성의 G Buff를 사용하고 있다.
Depth / Normal / Specular / Albedo
이렇게 4가지 G Buffer를 참고하여 디퍼드 랜더링으로 라이팅 연산후 포스트프로세싱을 추가 하여 최종 이미지를 만든다.
그렇다면 맨처음 포워드에서 수 많은 동적라이트에 라이팅이 잘못 연산되었던 결과물과 디퍼드랜더링의 결과물과 비교 해보자.
짜잔..!! 잘나오는군!
하지만 메모리 대역폭을 많이 차지 하는게 가장 문제가 되고 있다.
그래서 G Buffer를 다운사이징 하여 조금이라도 줄여보려고 하고 있지만 이 부분은 퀄리티에 문제가 있어 사용하기 힘들다고 한다.
더군다나 모바일 디바이스에서는 쥐약이 된다. 왜? 메모리가 크지 않으니까.!!
또 다양한 메터리얼에 적용하기 힘들다. (Transparent 불가)
이런 상황을 극복하기 위해 TBR / TBDR 을 사용하지만 이 역시도 100% 사용하기는 힘들다.
더 다양한 시도들은 다음기회에..
Forward+ (2022.2 Beta)
: Tiled Forward Shading으로 수 많은 라이팅을 다루는 포워드 렌더링이다.
GPU를 사용하지 않고 소프트웨어적으로 Tile로 만들어서 라이팅을 제어하는 렌더링이다.
오브젝트별로 여러개 라이팅을 지원하는 방식
나타내보면 이런 형식이다.
기존 포워드랜더링 방식을 유지 하지만 라이팅연산을 할때 타일형태로 관리되는 데이타를 참고하여 연산하는 방식이다.
이 포워드+ 렌더링은 Light Culling이 중요해지는데.
만약에 이런 형태로 카메라와 라이팅 그리고 오브젝트가 씬에 있다면
라이팅 연산에 적용되어야 하는 라이트와 타일은 어떤 것일까?
정답은?
이유
- 1번 라이트는 카메라에서 이미 카메라 컬링이 이루어졌으니 연산에 참여하지 않고
- 2번 라이트는 카메라 안에는 있지만 그 라이팅 범위가 오브젝트에 영향을 미치지 않고
- 3번 라이트는 카메라 안에 들어와 있고 라이팅이 오브젝에 영향을 미치고 있으니 연산에 참여
- 4번 라이트는 카메라 안에는 있지만 오브젝트에 가려져 카메라가 볼수 없으므로 연산에 참여하지 않는다
- 그러므로 라이팅 연산에 참여해야 하는 타일은 4번과 5번이 되는 것이다.
이렇게 라이팅 연산에 꼭 필요한 부분만 걸러내는 부분이 아주 중요해진다.
URP의 Forward+는
- Tile 연산은 Compute Shader를 사용하지 않는다
- Job & Burst로 SIMD 와 Multi Core를 활용하여 활용
- 한 화면에 256(모바일 32)개의 라이트까지만 지원
- MSAA 사용가능
- VR 미지원 (오버헤드문제로 지원하지 않음)
- OpenGL ES2 미지원
Forward Rendering 인데도 마치 디퍼드 처럼 많은 라이팅 연산을 적은 비용으로 할수 있다.
정리
길었다..
'Optimize' 카테고리의 다른 글
[Unity Optimize] GI(Global Illumination)_01 (0) | 2023.07.27 |
---|---|
[Unity Optimize] 그림자 (Shadow) (0) | 2023.07.27 |
[Unity Optimize] 컬링(Culling) (0) | 2023.07.25 |
[Unity Optimize] 배칭(Batching) (0) | 2023.07.25 |
[Unity Optimize] 드로우콜 (DrawCall) (0) | 2023.07.25 |