유니티에서 화면에 오브젝트를 그리기 위해 GPU에게 내리는 명령 하나하나를 Draw Call(드로우콜)이라고 부른다. GPU는 이 드로우콜을 받을 때마다 렌더링 작업을 수행하기 위해 준비 단계를 거치는데, 이 준비 단계가 바로 오버헤드를 만들어낸다.
즉, 드로우콜 수가 많을수록 렌더링 성능이 떨어진다.
유니티 엔진은 씬에 있는 모든 오브젝트를 각각 렌더링할 때마다 GPU에게 개별적인 드로우콜을 날리게 되는데, 이 과정은 크게 다음과 같은 과정을 거친다.
CPU가 GPU에게 렌더링 명령 전달
GPU가 렌더링 준비 및 상태 전환 (셰이더 교체, 텍스처 바인딩 등)
실제 렌더링 작업 수행
여기서 성능 병목(bottleneck)은 대부분 2단계에서 발생한다. GPU가 텍스처나 머티리얼, 셰이더를 바꿔가며 상태를 변경하는 작업이 생각보다 비용이 크기 때문이다.
정리하면 Draw Call 수가 늘어나면 CPU와 GPU가 상태 변경으로 시간을 많이 보내게 되어 FPS가 떨어진다.
1. 서로 다른 머티리얼 사용
오브젝트마다 개별적인 머티리얼을 사용하면 유니티는 각각 별도의 드로우콜을 발생시킨다.
같은 셰이더, 같은 텍스처라도 머티리얼 인스턴스가 다르면 드로우콜은 별개로 계산됨.
특히 실수로 같은 텍스처를 쓰는 머티리얼을 여러 개 만들면 쓸데없이 드로우콜이 폭발적으로 증가함.
2. 투명(Transparent) 오브젝트
투명한 오브젝트(알파 블렌딩 사용)는 유니티가 뒷면과 앞면 렌더링을 여러 번 진행하면서 드로우콜 수가 늘어난다.
3. 광원(Light) 및 그림자(Shadow)
라이트가 많아지면 라이트당 추가적인 드로우콜이 생긴다. 특히 실시간 그림자를 쓰면 그림자 패스가 별도의 렌더링 단계를 거치므로 드로우콜 수가 급격히 증가한다.
4. UI Canvas의 분할
Canvas를 여러 개로 나누거나, UI가 복잡할수록 드로우콜이 늘어난다.
드로우콜 최적화의 핵심은 상태 변화를 최소화하는 것이다.
1. 머티리얼 합치기 (Material Atlasing)
여러 오브젝트가 같은 머티리얼을 쓰면 한 번의 드로우콜로 묶어서 처리할 수 있다.
텍스처 아틀라싱(Texture Atlasing): 여러 텍스처를 하나의 큰 텍스처로 묶어서 사용한다.
머티리얼 공유(Material Sharing): 중복되는 머티리얼을 최대한 공유한다.
2. Static Batching
유니티가 정적인 오브젝트를 미리 한 덩어리로 합쳐서 렌더링.
씬에 배치된 뒤 이동하지 않는 정적인 오브젝트는 Inspector에서 Static 체크박스를 체크하면 유니티가 자동으로 Static Batching을 적용한다.
드로우콜 수를 획기적으로 낮추지만, 메모리 사용량은 증가할 수 있다.
3. Dynamic Batching
동적인 작은 오브젝트를 실시간으로 합쳐 렌더링.
유니티가 자동으로 동작하지만 제약 조건이 있음:
Vertex 수가 제한적임 (일반적으로 300 버텍스 이하)
같은 셰이더와 같은 머티리얼을 사용해야 함
성능 향상이 확실하지만, 동적으로 합치는데 CPU 오버헤드가 있으므로 잘 활용해야 함
4. GPU Instancing
동일한 메쉬와 머티리얼을 사용하는 많은 오브젝트를 한번의 명령으로 GPU에게 전달해 대량 렌더링 처리.
특히 잔디, 나무, 파티클 등 같은 오브젝트가 반복되는 환경에서 효과적이다.
유니티에서 머티리얼 설정에서 Enable GPU Instancing 옵션을 활성화하면 적용된다.
5. 라이트맵 사용 (Baked Lighting)
라이트맵을 구워서(베이크) 미리 계산된 빛 정보를 텍스처로 만들어 사용하면 실시간 조명이 줄어들어 드로우콜이 감소한다.
그림자, 광원의 동적 렌더링이 사라져 성능 향상이 크다.
6. UI 최적화
UI 캔버스를 합쳐서 렌더링하면 드로우콜 감소.
Canvas를 잘 그룹화하고 불필요한 Canvas 분리를 피해야 함.
텍스처 아틀라싱을 UI에서도 적극적으로 사용한다.
무조건 드로우콜을 낮추는 것이 정답은 아니다.
드로우콜을 너무 극단적으로 줄이면 메모리 사용량이 커지거나 GPU에 과부하가 걸릴 수도 있다.
프로젝트 특성에 맞게 적절한 균형을 잡아 최적화하는 것이 가장 중요하다.
프로파일러(Profiler)를 활용해 최적화 전후 성능을 분석하며 접근하는 것이 좋다.
드로우콜 최적화의 핵심은 결국 GPU에게 내리는 명령의 횟수를 최소화하는 것이다. 이를 위해 머티리얼 공유, 아틀라싱, Static/Dynamic Batching, GPU Instancing 등을 적극 활용하면 최적화를 효율적으로 수행할 수 있다.
프로젝트 규모가 커질수록 최적화는 필수이며, 드로우콜 관리는 그 첫 번째 단계라고 할 수 있다. 드로우콜을 잘 관리하면 성능과 품질을 동시에 챙길 수 있다.