화면에 오브젝트를 렌더링 하려면 CPU가 많은 작업을 처리해야 합니다.
CPU가 하는 작업
- 광원 계산
- 셰이더, 셰이더 파라미터 설정
- 드로잉 커맨드를 그래픽 드라이브에 전송
- 커맨드가 그래픽 카드에 전송되도록 준비
- 등등...
오브젝트 별 CPU 사용은 리소스를 많이 사용하는데 보이는 오브젝트가 많다면 CPU에 무리가 갈 수 있습니다.
예시)
1000개의 삼각형을 그릴때, 하나의 삼각형을 하나의 메시에 넣는 것(메시 1000개를 그림)보다
모든 삼각형을 하나의 메시(메시를 결합하여 1개만 그림)에 넣는 것이 CPU를 효율적으로 사용할 수 있습니다.
두 경우 GPU 코스트는 비슷함
CPU 작업량을 줄이는 방법
1. 가까이 있는 오브젝트를 수동이나 Unity의 드로우 콜 배칭을 활용해 결합
2. 큰 텍스처 아틀라스에 개별텍스처를 넣어 오브젝트의 메터리얼 수를 줄임
3. 오브젝트가 여러 번 렌더링 되는 요소(반사, 그림자, 픽셀 별 광원)를 덜 사용함
1번부터 하나씩 살펴봅시다.
드로우 콜 배칭
드로우 콜(Draw call)
- CPU가 OpenGL이나 DirectX의 함수를 호출하여 GPU에게 그리기(Draw call)을 요청하는 것
그래픽 API의 모든 드로우 콜은 중요 작업을 수행함으로 CPU 코스트가 크다.
Why?
드로우 콜 간에 수행되는 스테이트 변경으로 인해 그래픽 드라이버에서 리소스가 많이 사용되는 확인 및 이동 단계를 수행하기 때문
드로우 콜 발생조건
1. 메쉬가 여러개일때
2. 머터리얼이 여러 개일 때(얼굴, 눈)
3. 셰이더에 의한 경우(2-Pass, 외곽선을 그리고 본체 그리기)
드로우 콜을 줄이기 위해 게임 엔진은 배치(Batches)를 제공한다.
배치(Batches)
- 드로우 콜과 많이 혼용돼서 사용하지만 드로우 콜을 포함하는 상위 개념(넓은 의미의 드로우 콜)
- Draw Call + Set VB/IB + Set Transform + Set Pass Call (Set Shader + Set Texture 0~7 + Set Blending + Set Z enable..)
Set pass call
- 머터리얼과 셰이더에 관련된 것에 대한 Batch
예시1: 머터리얼을 공유하는 오브젝트 5개
- Batch는 5개, Set Pass Call 1개 , 총 Batch 6개
예시2: 머터리얼을 공유하지 않는 오브젝트 5개
- Batch는 5개, Set Pass Call 5개 , 총 Batch 10개
따라서, 큰 텍스처 아틀라스에 개별텍스처를 넣어 오브젝트의 메터리얼 수를 줄이는 것이 중요하다.
배칭(Batching)
- 여러 개의 드로우 콜을 하나의 드로우 콜로 묶어서 처리하는 작업
- 동적 배칭: 메시가 충분히 작은 경우 메시의 버텍스가 CPU에서 트랜스폼되고, 유사한 메시가 그룹화되어 한꺼번에 드로우 됨
- 정적 배칭: 움직이지 않는 게임 오브젝트를 큰 메시로 합쳐서 빠른 방법으로 렌더링함
동적 배칭(Dynamic Batching)
- 동일한 머터리얼을 공유하고, 특정 조건을 만족하면, 유니티에서 자동적으로 일어나는 배칭
- 정적 배칭에비해 조건이 까다롭고 눈에 띄는 효율은 아님
- 동일한 모델일 필요X, 작은 것들을 한번에 렌더링한다고 보면 된다.
- 가장 많은 효과를 보는 곳은 파티클 메쉬
- 오브젝트 버텍스를 CPU에서 월드 공간으로 변환하는 방법으로 작동하기 때문에, 이 작업이 드로우 콜을 수행하는 것보다 더 작은 경우에만 유리함
동적 배칭 조건 정리
1. 리소스 사용량이 버텍스마다 일정하므로, 900미만의 버텍스 속성/300개 미만의 버텍스가 포함된 메시에만 적용
- 셰이더가 버텍스 포지션, 노멀 및 싱글 UV를 사용하면 버텍스를 300개까지 배칭 가능
- 셰이더가 버텍스 포지션, 노멀, UV0, UV1 및 탄젠트를 사용하는 경우 180개까지 배칭 가능
2. 트랜스폼에 미러링이 포함된 게임 오브젝트는 배칭되지 않습니다.
- 스케일 +1인 오브젝트A와 -1인 오브젝트B를 함께 배칭할 수 없음
3. 다른 머터리얼을 사용하면 같은 오브젝트도 함께 배칭되지 않습니다.
- 섀도우 캐스터 렌더링 예외
4. 라이트맵이 있는 오브젝트에는 라이트맵 인덱스와 라이트맵 오프셋/스케일이라는 추가 렌더러 파라미터가 있는데, 동적 라이트맵이 적용된 오브젝트는 배칭할 라이트맵위치와 정확히 똑같은 위치를 가리켜야합니다.
5. 멀티 패스 셰이더는 배칭을 중단합니다.
- 거의 모든 Unity 셰이더는 포워드 렌더링 시에 몇가지 광원을 지원하여 추가 패스를 대신 수행함
- 픽셀당 추가 라이트에 대한 드로우 콜은 배칭 되지 않습니다.
- 광원 프리패스(Legacy Deferred) 렌더링 경로는 오브젝트를 두번 드로우 해야하기 때문에 동적 배칭이 불가능함
정적 배칭(Static Batching)
- 동일한 머터리얼을 공유하고, 움직이지 않는 오브젝트 모든 크기의 지오메트리에 대해 드로우 콜을 줄일 수 있다.
- 일반적으로 동적 배칭 보다 효율적이지만 메모리를 더 많이 사용함
- 눈에 띄는 성능 차이를 보이기 때문에, CPU 오버헤드가 크다면 사용하면 좋다.
- 사용하려면 특정 오브젝트가 움직이지 않음(정적/ 이동,회전,스케일하지 않음)을 명시적으로 지정해야함
- 모든 배경을 하나로 합쳐서 내보내는 경우, 화면에 일부분이 보이더라도 전체를 무조건 그리기 때문에 시야각에 들어오는 구역별로 적절히 나누는 작업이 필요하다.
조명(Lighting) 최적화
라이트맵(Light map)
- 고정된 조명과 오브젝트의 경우에 라이트 맵을 최대한 활용한다. (ex. 실내 형광등)
- 픽셀당 계산하는 것보다 실행속도가 빠릅니다 / 다만 라이트맵을 bake하는 과정이 필요함
라이트 렌더 모드 설정
- important / Not Important 설정
- 동적 라이팅만 Important 설정 (ex. 손전등)
'유니티(Unity) > 최적화' 카테고리의 다른 글
그래픽스 퍼포먼스 최적화(3) GPU 최적화 (0) | 2021.08.09 |
---|---|
그래픽스 퍼포먼스 최적화(1) 개요 (0) | 2021.07.11 |
오브젝트 풀링(Object Pooling)이란? (1) | 2021.07.02 |