DrawCall을 줄이는 가장 확실한 방법은 여러 오브젝트를 포함한 통메시를 만들어 한번에 그리는 것이다. 하지만, 조금만 생각해보면 이는 좋은 방법이 아니라는 것을 알 수 있다. Mesh가 엄청나게 큰 경우, 메시의 일부분만 화면에 나오더라도 그 Mesh의 전체 폴리곤을 처리해야 한다. 카메라 뷰 밖에 존재하는 많은 Vertex 연산들이 낭비 되므로, DrawCall이 주는 CPU에서 이득일지 몰라도, GPU 입장에서는 엄청난 손해이다.

Modular Asset

Untitled

따라서 가장 좋은 방법은 중복되는 Mesh, 중복되는 Material이 최대한 많아지도록 모듈 형태로 에셋을 만드는 것이다. 실내 맵 같은 경우 모듈 방식을 이용하면 Batch수를 크게 감소 시킬수 있다.

Texture Atlas

Untitled

SetPassCall을 줄이는 또 다른 대표적인 방법은 Texture Atlas 기법이 있다. 여러 Mesh의 Texture를 하나로 묶으면, SetPassCall없이 많은 Mesh들을 렌더링 할 수 있다. (Texture의 UV 좌표를 조정)

다만 Texture를 조금만 모아도 굉장히 큰 해상도의 Texture가 될 수 있는데 이 경우 메모리 대역폭 이슈가 발생할 수 있으므로 이를 고려 해야한다. 그리고 Texture의 압축방식도 고려해서 해상도를 정해야한다.

Static Batching

Untitled

Static Batching 기법은 Material을 공유하는 Mesh들을 묶어서 DrawCall하는 방법이다. 예를 들어 Material을 공유하는 3개의 Mesh들을 각각 따로 DrawCall하면 3번의 Batch가 발생하지만, Mesh들을 하나로 묶어서 DrawCall하면 한번의 Batch로 렌더할 수 있다. 위에서 언급한 Module방식에 적용하기 좋은 최적화 기법이다. 다만 각 Mesh들과 별개로 Mesh들을 합친 새로운 형태의 메모리 공간이 추가적으로 필요하다, 즉 메모리를 추가적으로 소모하여 최적화하는 방식이기 때문에 메모리 이슈가 존재하는 경우 (특히 모바일기기에서의 램부족) Static Batching을 해제 해야할 수도 있다.

Unity에서 GetComponent 메서드를 이용해 Meterial을 가져온다면 복사본이 생겨 서로 다른 객체 취급을 받고 배칭되지 않는다.

Dynamic Batching

Dynamic Batching 기법은 런타임에 움직이는 오브젝트들을 묶어서 DrawCall하는 방법이다.

매 프레임마다 Mesh들을 수집&재생성을 하기 때문에 추가적인 메모리 소모와 오버헤드가 발생