그래픽스 퍼포먼스 최적화
최적의 퍼포먼스를 위한 캐릭터 모델링

드로우 콜 배칭

드로우 콜 배칭

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

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

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

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

배칭할 머티리얼 설정

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

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

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

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

동적 배칭(메시)

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

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

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

동적 배칭(파티클 시스템, 라인 렌더러, 트레일 렌더러)

Unity가 동적으로 생성하는 지오메트리가 포함된 컴포넌트의 경우 동적 배칭은 메시에 대한 동적 배칭과 다르게 동작합니다.

  • 호환 가능한 렌더러 타입 각각에 대해 Unity는 모든 배칭 가능한 콘텐츠를 하나의 커다란 버텍스 버퍼로 빌드합니다.
  • 렌더러는 배치에 대한 머티리얼 상태를 설정합니다.
  • Unity는 버텍스 버퍼를 그래픽스 기기에 바인드합니다.
  • 배치의 렌더러 각각에 대해 Unity는 오프셋을 버텍스 버퍼로 업데이트한 다음 새로운 드로우 콜을 제출합니다.

그래픽스 기기 호출의 성능 부하를 측정하는 경우 컴포넌트 렌더링의 가장 느린 부분이 머티리얼 상태로 설정됩니다. 다양한 오프셋의 드로우 콜을 공유 버텍스 버퍼로 제출하면 비교적 속도가 매우 빠릅니다.

이러한 방식은 정적 배칭을 사용할 때 Unity가 드로우 콜을 제출하는 방법과 매우 유사합니다.

정적(Static) 배칭

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

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

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

내부적으로 정적 배칭은 정적 게임 오브젝트를 월드 공간으로 변환하고 하나의 공통 버텍스 및 인덱스 버퍼를 빌드하여 작동합니다. Player Settings 에서 Optimized Mesh Data 를 활성화하면 Unity는 버텍스 버퍼를 빌드할 때 셰이더 배리언트에서 사용하지 않는 모든 버텍스 요소를 제거합니다. 이 작업을 수행하기 위해 특별한 키워드 검사를 수행할 수도 있습니다. 예를 들어, Unity가 LIGHTMAP_ON 키워드를 감지하지 못하면 배치에서 라이트맵 UV를 제거합니다. 그런 다음 동일한 배치에 표시되는 게임 오브젝트의 경우 Unity는 일련의 간단한 드로우 콜을 수행합니다. 이때 각 드로우 콜 간에는 상태 변화가 거의 없습니다. 기술적으로 Unity는 API 드로우 콜을 저장하는 대신 드로우 콜 간의 상태 변화를 저장(리소스 소모가 심함)합니다. 배치 한도는 대부분의 플랫폼에서 64,000개 버텍스와 64,000개 인덱스입니다(OpenGLES는 48,000개 인덱스, macOS는 32,000개 인덱스).

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

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

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

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


  • 2017–10–26 일부 편집 리뷰를 거쳐 페이지 수정됨

  • 2017.2에 동적 배칭이 그래픽스 작업과 호환되지 않는다는 내용의 참고 사항 추가됨

그래픽스 퍼포먼스 최적화
최적의 퍼포먼스를 위한 캐릭터 모델링