유니티/공통

유니티 - Batching에 대해 알아보자.(feat. Draw call, Set Pass Call, 아틀라스)

근본넘치는개발자 2024. 10. 25. 23:54

오늘은 Batching에 대해 알아보고자 합니다.

요즘 계속 유니티 관련해서 찾아봐서 그런가

유튜브 알고리즘이 띄워주더군요. ㅋ

 

아틀라스를 사용하면서 몇 번 스치듯 들어보긴 했는데

정확하게 몰라 한번 정리해 봤습니다.

Batching?

Draw Call과 여러 그래픽 요소들을 하나로 묶어 GPU에 전달하는 최적화 기법

 

Draw Call ? 

CPU는 게임 오브젝트 데이터를 읽고 처리하는 역할,

GPU는 받은 데이터를 기반으로 실제 컨텐츠를 그리는 역할을 수행하는데,

 

이때  CPU가 GPU에게 3D 오브젝트를 그리라고 지시하는 명령을

Draw Call이라고 합니다.

 

Set Pass Call ? 

Draw Call을 통해 따라오는 데이터를 커멘드 버퍼라고 하는데, 

그 중 매테리얼, 쉐이더 등 그래픽 관련 데이터를 묶어놓은 버퍼가 Set Pass

전달하는 걸 SetPass Call이라고 합니다.

 

배치에 해당하는 컴포넌트들 

스프라이트 렌더러(Sprite Renderer)

메시 렌더러(Mesh Renderer)

라인 렌더러(Line Renderer)

트레일 렌더러(Trail Renderer)

파티클 시스템(Particle System)

 

배치를 확인 할 수 있는 방법

 

1. 게임 창의 우측 상단에 Stats를 누르면 정보들이 나옵니다.

 

2. Window - Analys - Frame Debugger를 통해서도 자세하게 확인이 가능합니다. 

 

 

다이나믹 배칭(Dynamic Batching)

동일한 재질을 사용하는 메시들을 자동으로 묶어서 렌더링하는 방법.

900개 이상의 정점 속성이나 225개 이상의 정점을 가진 메시는 적용 불가능하다고 합니다.

 

스프라이트 렌더러는 기본적으로 다이나믹 배칭 대상으로서

스프라이트 아틀라스 활용 시 효과적인 배칭이 가능합니다.

 

아틀라스?

여러 개의 작은 이미지들을 하나의 큰 이미지 파일로 합친 것.

말로는 이해가 안 갈 거 같아서 자료를 가져왔습니다. 

 

빙 이미지 크리에이터를 통해 만든 Sprite 아틀라스

이런 식으로 여러개의 이미지들을 하나로 묶어서 사용하는 걸 아틀라스라고 합니다.

 

개별 텍스처를 일일이 로딩하는 것 보다

하나의 큰 텍스처를 로딩하고 부분을 가져오는 게 아무래도 더 효율적이겠죠?

 

사용하는 법을 간단하게 설명하자면 

 

아틀라스를 클릭 후

Inspector 창에서 Sprite Mode - Multiple로 바꿔준 후 Sprite Editor로 들어갑니다.

 

좌측 상단에서 Slice라고 적힌 부분을 누르고

Type을 Automatic으로 변경, Slice를 눌러줍니다. 

 

다음처럼 네모난 상자모양으로 자동으로 나눠줍니다.

 

우측 상단에서 Apply를 누르면 

 

이렇게 분리가 되고,

하나의 이미지로부터 원하는 부분을 가져와 사용할 수 있게 되었습니다.

 

 

3D환경에서 다이나믹 배치 활성화 시키는 방법

 

Edit - preferences - Core Render Pipeline - visibility를 All Visible로 바꾸기

 

 

 

Edit - Project Settings - Quality에 들어가면

Rendering에 Render Pipeline Asset이 있습니다. 

 

 

일단 저는 비어 있는데,

들어가 있는 해당 Render PipeLine Asset을 클릭한 후 

Dynamic Batching을 설정하실 수 있습니다.

 

설명을 위해 Render PipeLine Asset을 가져와 봤습니다.

Inspector 창에 Dynamic Batching이 보이시나요.

그 위에는 SRP 배칭도 있습니다.

 

SRP 배칭은 이따가 소개하겠습니다.

 

스태틱 배칭(Static Batching)

정적 오브젝트들을 하나의 메시로 통합하여 처리하는 기법 

 

단점으로는 

 

정적이기에 transform 조절이 불가합니다.

 

또한 내부 상에서 하나의 매쉬로 통합이 돼서 배치가 올라가기에

메모리를 많이 차지한다고 합니다.

 

설정하는 방법은 아래와 같습니다. 

 

Edit - project Settings - Player - Other Settings에 Static Batching 활성화 확인

(기본으로 활성화되어 있는 듯합니다)

 

원하는 대상을 선택 후 Inspector 창에서 우측에 Static을 선택해 주면 됩니다.

 

Batching Static 옵션

 

 

강의에서 static으로 되어 있는 걸 봤었는데 이래서 설정한 거였군요. 

오...

 

 

연습 프로젝트에서 고정된 배경들에 적용해 본 결과 

 

 

적용 전 - Batches 가 320 ~ 330 왔다 갔다 하는 걸 확인

: 카메라 Occlusion으로 인해 마우스 움직임에 따라 약간씩 변하는 듯

: 이 부분에 대한 자세한 설명은 곧 따로 정리해 작성해 보겠습니다.

 

적용 후 - Batches가 183, Save Batches 가 158 / 대략 반 정도 세이브

 

간단한 방법으로 Batching을 대략 반 정도를 줄였네요 ㄷㄷ

 

SRP 배칭(SRP Batching)

 

설정하면 서로 다른 메터리얼을 하나로 처리해 줍니다.

단 동일한 쉐이더를 사용해야한다는 조건이 있습니다.

 

또 SRP배칭과 호환 안 되는 쉐이더들도 있어서 

직접 인스펙터 창에서 확인해 줘야 하는 번거로움이 있을 수 있답니다.

 

배치 수는 유지되나 Set Pass Call가 감소하는 걸

영상에서 확인 할 수 있었습니다.

 

GPU 인스턴싱(GPU Instancing)

CPU가 하나의 메쉬만을 읽고 GPU에 저장하면 

GPU에서 이 정보를 계속 활용하는 기법입니다.

 

단점으로는 

 

페이징 처리(수가 많으면 일정 단위로 나눠서 순차적으로 처리)로 인한

약간의 배치 수 발생 가능성과

 

GPU 인스턴싱을 사용하기 위해

SRP 배칭을 꺼야 한다는 번거로움이 있다고 합니다.

(원하는 쉐이더가 SRP 배칭을 호환하지 않으면 안 꺼도 상관없습니다.)

 

설명을 위해 Material을 생성했고, 아래 GPU instancing을 확인 할 수 있었습니다.

 

 

 

또 256개 미만의 버텍스를 가진 메시는 비효율적이라고 합니다.

 

마무리 

직접 눈으로 수치가 보이니까 신기하더군요.

아틀라스를 쓰면서도 최적화된다고만 들었지 직접보니까 확실히 체감이 되네요.

 

오늘은 이렇게 간단하게 Batching 최적화 기법에 대해 알아보았습니다.

 

참고한 자료

 

https://youtu.be/w14yjBlfNeQ?si=2S7_4jjTv4ax-T_J