"자신이 원하지 않는 일을 남에게 시키지 마라." – 論語(논어)

2014/01/26

Draw call 일괄 처리

원문

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

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


Draw call 일괄 처리

화면에 게임오브젝트를 그리려면 그래픽 엔진은 (OpenGL이나 Direct3D같은) 그래픽 API에 draw call을 보내야 합니다. draw call은 자원을 많이 사용하는 경우가 많으며, 그래픽 API가 매 draw call마다 큰 작업을 하게되면 CPU쪽에 성능 오버헤드(부가 간접 계산)를 발생시킵니다. 이는 주로 draw call 사이에 (다른 머티리얼로 교체 같은) 상태 변경을 할 때 많이 발생하며, 자원을 많이 사용하는 유효 검사나 그래픽 드라이버의 변환 단계에서 발생합니다.

유니티는 이를 해결하기 위해 다음의 두 기술을 사용합니다.

  • 동적 일괄 처리 : 메시가 충분히 작은 경우, CPU상에서 정점을 변환하고 비슷한 많은 정점을 한데 모은 뒤에 모두 한 번에 그립니다.
  • 정적 일관 처리 : (움직이지 않는) 고정 게임오브젝트들을 큰 메시들로 합쳐 보다 더 빠르게 그립니다.

내장(자동) 일괄 처리는 게임오브젝트들을 직접 합치는 것보다 몇몇 이점이 있습니다. 특히 주목할 점은 여전히 게임오브젝트를 (일괄 처리중에도) 개별적으로 사용할 수 있다는 것입니다. 하지만 단점도 있습니다. 정적 일괄처리는 메모리와 저장공간 오버헤드를 발생시키며, 동적 일괄 처리는 약간의 CPU 오버헤드를 발생시킵니다.

일괄 처리용 머티리얼 설정

같은 머티리얼을 사용하는 오브젝트들만 함께 일괄적으로 처리 할 수 있습니다. 그러므로 좋은 효과를 보려면, 다른 종류의 게임오브젝트들이 가능한 많이 같은 머티리얼을 사용하게 해야 합니다.

텍스처만 다른 두 개의 개별 머티리얼이 있다면, 텍스처들을 하나의 큰 텍스처로 합칠 수 있습니다. 이런 작업을 텍스처 아틀라싱(texture atlasing, 더 자세한 내용은 위키피디아의 텍스처 아틀라스 페이지를 보세요.)이라고 부릅니다. 같은 큰 텍스처로 한 번만 합쳐지면 머티리얼을 여럿대신 하나로 사용할 수 있습니다.

스크립트에서 (오브젝트들이) 함께 사용하고 있는 머티리얼의 속성에 접근해야 한다면 Renderer.material을 수정할 경우 머티리얼 복사본이 생성된다는 것을 알고 있는 것이 중요합니다. 대신 Renderer.sharedMaterial으로 머티리얼을 계속해서 함께 사용하세요.

동적 일괄 처리(메시)

유니티는 움직이는 게임오브젝트들이 같은 머티리얼을 사용하고 다른 조건을 충족한다면, 동일한 draw call에 넣어 자동으로 일괄 처리할 수 있습니다. 동적 일괄 처리는 자동으로 수행되며 여러분이 따로 해야할 것은 없습니다.

  • 게임오브젝트를 동적으로 일괄 처리하는 것은 정점마다 약간의 오버헤드를 갖게되기 때문에 정점 300개, 정점 속성이 900개를 넘지 않는 메시들만 적용됩니다.

몇가지 정보:

  • 동적 물체 일괄 처리는 약간의 부담이 정점마다 발생합니다. 그러므로 일괄 처리는 전체 정점 속성이 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는 일괄 처리되지 않습니다.

댓글 남기기 | cat > 타닥타닥 | tag > ,

댓글 남기기

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