"눈이 나쁘면 안경을 쓴댔으니 모자란 너에겐 모자를 씌워주마" – 김케장 / 동전주머니엔 동전이 들었지

20140126
Draw call 일괄 처리

원문

http://docs.unity3d.com/Manual/DrawCallBatching.html

draw call하고 좀 싸울 일이 있어서 보다가 번역해서 적어놓습니다. 오역이 있을 수 있습니다. ;ㅁ;


Draw call 일괄 처리

화면에 물체를 그리기 위해서는 엔진이 그래픽 API(예로 OpenGL 이나 Direct3D)에 draw call을 보내야 합니다. 그래픽 API가 큰 작업을 모든 draw call마다 하게 되면 CPU 쪽에서 성능 부담(overhead)을 발생시킵니다.

유니티는 런타임 도중에 여러 물체를 합칠 수 있고, 모두 함께 draw call 한 번으로 그릴 수 있습니다. 이 작업을 “일괄 처리(batching)”라고 부릅니다. 유니티가 더 많은 물체를 일괄 처리할 수 있다면, 더 좋은 렌더링 성능(CPU 쪽)을 얻을 수 있습니다.

유니티에서 지원하는 내장 일괄 처리는 모델링 툴에서 지오메트리(폴리곤)를 단순히 합치는 것(이나 기본 에셋 묶음에 있는 CombineChildren 스크립트를 사용하는 것)보다 훨씬 큰 이득을 가져옵니다. 유니티의 일괄 처리는 보이는 물체 결정 단계(컬링) 이후에 처리됩니다. 엔진이 각각의 물체를 하나하나 추려(culling)내고 렌더링을 하므로 렌더링 된 지오메트리의 양은 일괄 처리를 하지 않았을 때와 같게 됩니다. 반면 모델링 툴에서 합친 지오메트리는 (이미 하나로 합쳐져서 일부만 보여도 합쳐진 전체가 렌더링 되어) 효율적인 추려내기를 못하기 때문에 더 많은 양의 지오메트리가 렌더링 됩니다.

재질

같은 재질을 공유(사용)하는 물체들끼리만 함께 일괄 처리할 수 있습니다. 그러므로 효과적인 일괄 처리를 원한다면 가능한 많은 물체가 같은 재질을 사용하게 해야 합니다.

각각 텍스처만 다른 재질 두 개가 있다면 그 두 텍스처를 흔히 텍스처 지도 만들기(texture atlasting)라고 부르는 과정을 통해 하나의 큰 텍스처로 합칠 수 있습니다. 한 번 텍스처가 하나의 지도(atlas)에 들어가게 되면 두 개 대신 하나의 재질을 사용할 수 있습니다.

스크립트에서 공유된 재질 속성값(properties)에 접근해야 할 일이 있는 경우 알아야 할 중요한 내용이 있습니다. Renderer.material을 수정하면 원본 대신 복사본이 생성됩니다. (실제 재질 파일의 변경을 막기 위해서 런타임용 복사본을 만들어 사용) 그러니 재질 공유를 유지하려면 Renderer.sharedMaterial을 사용해야 합니다.

동적 일괄 처리

유니티는 움직이는 물체들이 같은 재질을 사용하고 다른 몇몇 기준들을 지키고 있다면 자동으로 같은 draw call에 넣어 묶을 수 있습니다. 동적 일괄 처리는 자동으로 작동하며 작업자 쪽에서 추가로 작업할 필요가 없습니다. (라면서 밑에 해야할 거 막 적어 두고 있지)

몇가지 정보:

– 동적 물체 일괄 처리는 약간의 부담이 정점마다 발생합니다. 그러므로 일괄 처리는 전체 정점 속성이 900개보다 적은 메시에만 적용돼야 합니다.

– 사용 중인 셰이더가 정점 위치, 법선과 UV 하나를 사용하고 있다면 정점 300개(정점당 속성 3개x300==900)까지 적용할 수 있지만 셰이더가 정점 위치, 법선, UV0, UV1과 접선을 사용 중이라면 정점 180개(5×180==900)까지 적용할 수 있습니다.

– 속성 개수 제한은 앞으로 변경될 수 있음을 알립니다.

– 일반적으로, 물체는 같은 크기여야 합니다.

– 예외로 비 균일하게 크기 조절된(non-uniform scaled, 글 하단에 설명) 물체가 있습니다. 각각의 물체가 모두 비 균일하게 크기가 다르다면 일괄로 처리할 수 있습니다. (그래도 안 되던데 뭘 잘못 했나 ;ㅁ; 근데 같은 크기 쓰라고 해서 크기 맞추고 실제 메시의 정점 위치를 바꿔서 크기 변경 효과 적용)

– 다른 재질 인스턴스(실제 근본적으로 같더라도)를 사용한 물체는 함께 일괄 처리되지 않습니다.

– 라이트맵이 적용된 물체는 lightmap index와 offset/scale과 같은 추가 렌더링 매개 변수를 가집니다. 그러므로 일반적으로 동적 라이트맵 처리된 물체는 일괄 처리될 정확히 같은 라이트맵 위치를 가리켜야 합니다.

– 다중 패스 셰이더는 일괄 처리를 깨트립니다. 거의 모든 유니티 셰이더가 전방 렌더링(forward rendering)에서 다중 조명을 지원하며 추가 패스를 효과적으로 적용합니다. “추가적 픽셀 당 조명”으로 인한 draw call은 일괄 처리되지 않습니다.

– 실시간 그림자가 드리워진 물체는 일괄 처리되지 않습니다.

정적 일괄 처리

다른 것으로 정적 일괄 처리가 있습니다. 이는 엔진이 어떤 크기(움직이지 않고 같은 재질을 공유하는 경우)의 지오메트리든지 draw call을 줄일 수 있게 합니다. 정적 일괄 처리는 동적 일괄 처리보다 크게 효율적입니다. CPU의 성능을 더 적게 사용해야 한다면 정적 일괄 처리를 선택해야 합니다.

정적 일괄 처리 효과를 얻으려면 어떤 물체가 정적이고 이후에도 움직이고, 회전하고 크기가 변하지 않을지를 확실히 표시해야 합니다. 이렇게 하려면 inspector의 정적이라고 적힌 확인 상자를 활성화해서 물체가 정적이라고 표시하면 됩니다.

위에 저거

정적 일괄 처리를 사용하면 합쳐진 지오메트리를 저장하기 위해 추가로 메모리가 필요합니다. 여러 물체가 정적 일괄 처리 전에 같은 지오메트리를 공유하고 있다면 편집 상태건 런타임 중이건 지오메트리의 복사본이 각각의 물체마다 생성됩니다. 이는 항상 좋은 선택이 아닙니다. 가끔은 렌더링 성능을 희생하더라도 몇몇 물체의 메모리 사용량을 더 작게 유지하기 위해 적용하는 정적 일괄 처리를 피해야 할 경우가 있습니다. 예로 빽빽한 숲의 나무들을 정적으로 지정하는 것은 메모리에 심각한 부담을 줄 수 있습니다.

정적 일괄 처리는 draw call을 대신해 일괄 처리 수를 줄여주지는 않습니다. 하지만 처리 수는 같더라도 정적 일괄 처리가 훨씬 더 빠릅니다.

다른 일괄 처리 정보

현재는 Mesh RendererParticle System만 일괄 처리됩니다. 다시 말해 골격(skinned) 메시, 피복, 자취(trail) 렌더러와 다른 렌더링 component들은 일괄 처리를 지원하지 않습니다.

반투명 셰이더는 투명도를 적용하기 위해 뒤에서 앞 순서로 렌더될 물체(목록)를 가장 자주 필요로 합니다. 유니티는 먼저 이 순서대로 물체를 정리합니다. 그러고 나서 일괄 처리를 시도합니다. 하지만 순서가 정확히 만족해야 하므로 이는 종종 불투명 물체일 때 보다 일괄 처리된 수가 적을 수 있음을 의미합니다.

유니티 렌더링의 다른 부분은 일괄 처리가 아직 구현되어 있지 않습니다. 예로 그림자 발생기, 카메라 깊이 텍스처와 GUI는 일괄 처리되지 않습니다.

댓글 남기기 | 타닥타닥

댓글 남기기

* 표시된 곳은 반드시 입력해주세요