그래픽스 퍼포먼스 최적화(Optimizing graphics performance)
최적의 퍼포먼스를 위한 캐릭터 모델링(Modeling characters for optimal performance)

드로우 콜 배칭(Draw Call Batching)

화면에 게임 오브젝트를 그리려면 엔진이 그래픽스 API(OpenGL, Direct3D 등)에 드로우 콜을 보내야 합니다. 드로우 콜에는 종종 리소스가 많이 사용되고, 그래픽스 API 가 모든 드로우 콜에 중요 작업을 수행함으로 인해 CPU 성능이 많이 사용될 수 있습니다. 이 이유는 주로 드로우 콜 간에 수행되는 (다른 머티리얼로 전환하는 등의) 스테이트 변경으로 인해 그래픽 드라이버에서 리소스가 많이 사용되는 확인 및 이동 단계를 수행해야 하기 때문입니다.

Unity 는 두 가지 기법을 사용하여 이 문제를 해결합니다:

  • 동적 배칭: 메시가 충분히 작은 경우 이 기법을 사용하면 메시의 버텍스가 CPU 에서 트랜스폼되고, 여러 유사한 메시가 그룹화되고, 모든 것이 한꺼번에 드로우됩니다.
  • 정적 배칭: 정적인(움직이지 않는) 게임 오브젝트를 큰 메시로 합치고 더 빠른 방법으로 렌더링합니다.

빌트인 배칭은 수동으로 게임 오브젝트를 병합하는 방법에 비해 몇 가지 이점이 있습니다. 가장 두드러진 이점은 게임 오브젝트를 계속 개별적으로 컬링할 수 있다는 것입니다. 하지만 몇 가지 단점도 있습니다. 정적 배칭에는 메모리와 스토리지가 많이 사용되고, 동적 배칭에는 CPU 리소스가 좀 많이 사용됩니다.

배칭할 머티리얼 설정

같은 머티리얼을 공유하는 게임 오브젝트만 함께 배칭할 수 있습니다. 따라서 효과적으로 배칭하려면 가능한 한 많은 게임 오브젝트 간에 머티리얼을 공유하려고 해야 합니다.

텍스처만 다른 동일한 머티리얼 2 개가 있는 경우, 이 텍스처를 큰 텍스처 하나로 합칠 수 있습니다. 이 프로세스를 종종 텍스처 아틀라싱이라고 합니다. 자세한 내용은 텍스처 아틀라싱에 대한 Wikipedia 페이지를 참조하십시오. 텍스처가 같은 아틀라스 안에 있으면 머티리얼 하나를 대신 사용할 수 있습니다.

스크립트에서 공유된 Material 프로퍼티에 액세스해야 하는 경우 Renderer material을 수정하면 머티리얼의 복사본이 생성된다는 것을 기억하는 것이 중요합니다. 그 대신 Renderer.sharedMaterial을 사용하여 Materials 를 공유된 상태로 유지해야 합니다.

섀도우 캐스터는 머티리얼이 다른 경우에도 종종 렌더링 중에 배칭할 수 있습니다. Unity 의 섀도우 캐스터는 섀도우 패스에 필요한 머티리얼의 값이 동일한 경우 다른 머티리얼에도 동적 배칭을 사용할 수 있습니다. 예를 들어 많은 크레이트에 텍스처가 다양한 머티리얼을 사용할 수 있지만, 섀도우 캐스터에는 텍스처 렌더링이 중요하지 않으므로 이 경우에는 함께 배칭할 수 있습니다.

동적(Dynamic) 배칭

Unity 는 같은 머티리얼을 공유하고 다른 조건을 충족하는 움직이는 게임 오브젝트를 동일 드로우 콜 안에 자동으로 배칭할 수 있습니다. 동적 배칭은 추가적인 작업 없이 자동으로 수행됩니다.

  • 동적 게임 오브젝트 배칭은 리소스 사용량이 버텍스마다 일정하므로, 총 900 개 미만의 버텍스가 포함된 메시에만 적용됩니다.
  • 쉐이더가 버텍스 포지션, 노멀 및 싱글 UV 를 사용하는 경우 버텍스를 300 개까지 배칭할 수 있는 한편, 셰이더가 버텍스 포지션, 노멀, UV0, UV1 및 탄젠트를 사용하는 경우 180 까지만 배칭할 수 있습니다.
  • 참고: 속성 카운트 제한은 향후 변경될 수 있습니다.
  • 트랜스폼에 미러링이 포함된 게임 오브젝트는 배칭되지 않습니다. 예를 들어 스케일이 +1 인 게임 오브젝트 A 와 스케일이 –1 인 게임 오브젝트 B 를 함께 배칭할 수 없습니다.
  • 다른 머티리얼을 사용하면 본질적으로 같은 게임 오브젝트도 함께 배칭되지 않습니다. 단, 섀도우 캐스터 렌더링은 예외입니다.
  • 라이트맵이 있는 게임 오브젝트에는 라이트맵 인덱스와 라이트맵으로 오프셋/스케일이라는 추가 렌더러 파라미터가 있습니다. 일반적으로 동적 라이트맵이 적용된 게임 오브젝트는 배칭할 라이트맵 위치와 정확히 똑같은 위치를 가리켜야 합니다.
  • 멀티 패스 Shaders 는 배칭을 중단합니다.
  • 거의 모든 Unity 셰이더는 포워드 렌더링 시에 몇 가지 광원을 지원하여 사실상 추가 패스를 대신 수행합니다. “픽셀당 추가 라이트”에 대한 드로우 콜은 배칭되지 않습니다.
  • Legacy Deferred(광원 프리패스) 렌더링 경로는 게임 오브젝트를 두 번 드로우해야 하기 때문에 동적 배칭이 불가능합니다.

이 경로는 모든 게임 오브젝트 버텍스를 CPU 에서 월드 공간로 변환하는 방법으로 작동하므로, 이 작업이 드로우 콜을 수행하는 것보다 더 작은 경우에만 더 유리합니다. 드로우 콜의 리소스 요구사항은 주로 사용되는 그래픽스 API 를 비롯한 여러 요인에 따라 달라집니다. 예를 들어 콘솔이나 애플 메탈 같은 최신 API 에서는 드로우 콜에 사용되는 리소스가 일반적으로 훨씬 더 적고, 종종 동적 배칭이 전혀 유리하지 않을 수 있습니다.

정적(Static) 배칭

정적 배칭을 사용하면 엔진이 움직이지 않고 동일 머티리얼을 공유하는 모든 크기의 지오메트리에 대해 드로우 콜을 줄일 수 있습니다. (CPU 에서 버텍스를 변환하지 않으므로)종종 동적 배칭보다 더 효율적이지만, 메모리를 더 많이 사용합니다.

정적 배칭을 이용하여 이득을 얻기 위해서는 특정 게임 오브젝트가 정적이고 게임에서 움직이거나 회전하거나 스케일하지 않음을 명시적으로 지정해야 합니다. 이렇게 하려면 인스펙터에서 Static 체크박스를 사용하여 게임 오브젝트가 정적임을 표시해야 합니다.

정적 배칭을 사용하면 결합된 지오메트리를 저장할 메모리가 더 필요합니다. 정적 배칭 전에 몇몇 게임 오브젝트가 동일한 지오메트리를 공유한 경우, 각 게임 오브젝트에 대해 지오메트리의 복사본이 에디터에서, 또는 런타임 시점에 생성됩니다. 이렇게 하는 것이 항상 바람직하지는 않을 수 있습니다. 때로는 일부 게임 오브젝트의 메모리 사용량을 적게 유지하기 위해 정적 배칭을 방지하여 렌더링 성능 저하를 감수해야 합니다. 예를 들어 밀집한 숲 레벨에서 나무를 정적으로 표시하면 메모리에 중대한 영향을 미칠 수 있습니다.

정적 배칭은 내부적으로 정적 게임 오브젝트를 월드 공간로 변환하고 해당 오브젝트를 위해 큰 버텍스와 인덱스 버퍼를 빌드하는 방법으로 작동합니다. 다음, 동일 배치의 가시 게임 오브젝트에 대해 일련의 단순 드로우 콜이 수행되고 그 사이에 스테이트가 거의 변경되지 않습니다. 엄밀히 말해 3D API 드로우 콜은 저장되지 않지만, 리소스가 많이 사용되는 부분인 상호 간 스테이트 변경이 감소합니다. 배치는 대부분의 플랫폼에서 64k 버텍스와 64k 인덱스로 제한됩니다. 단 OpenGLES 에서는 48k 인덱스, macOS 에서는 32k 인덱스로 제한됩니다.

현재는 메시 렌더러, 트레일 렌더러, 라인 렌더러, 파티클 시스템스프라이트 렌더러만 배칭됩니다. 따라서 스킨드 메시, 천 및 기타 렌더링 컴포넌트 타입은 배칭되지 않습니다.

렌더러는 동일한 타입의 다른 렌더러와만 배칭됩니다.

반투명 셰이더에서 투명 효과가 작동하려면 일반적으로 뒤에서 앞으로 진행하는 순서로 게임 오브젝트를 렌더링해야 합니다. Unity 는 처음에 이 순서로 게임 오브젝트를 정렬한 다음, 배칭하려고 하지만, 순서를 철저하게 준수해야 하기 때문에 종종 불투명 게임 오브젝트를 사용하는 경우보다 배칭을 줄일 수 있습니다.

가까이 있는 게임 오브젝트에 대한 수동 결합은 드로우 콜 배칭에 매우 좋은 대안이 될 수 있습니다. 예를 들어, 서랍이 많은 고정 찬장은 종종 3D 모델링 애플리케이션이나 메시 컴바인 메시를 사용해 싱글 Mesh 로 결합하는 것이 적합합니다.


  • 2017–07–27 일부 편집 리뷰를 거쳐 페이지 수정됨
그래픽스 퍼포먼스 최적화(Optimizing graphics performance)
최적의 퍼포먼스를 위한 캐릭터 모델링(Modeling characters for optimal performance)