본문 바로가기

레퍼런스/고도엔진

고도엔진 튜토리얼 #25 3D 성능과 제한(3D performance and limitations)

서론


고도는 균형잡힌 성능 철학을 따릅니다. 성능의 세계에서는 유용성과 유연성을 위한 거래 속도로 구성되는 trade-off입니다. 몇몇 실용적인 예가 있습니다 :


  • 많은 양의 오브젝트를 효과적으로 렌더링하는 것은 쉽지만 큰 씬을 렌더링 하는 경우 비효율적일 수 있습니다. 이를 해결하기 위해, 렌더링에 시각적 계산을 추가해 렌더링 효율성이 낮아지지만 동시에 렌더링되는 개체가 줄어들어 전반적인 효율성이 향상됩니다.
  • 렌더러가 필요한 모든 오브젝트를 위한 모든 자료(material)의 속성을 구성하는 것도 느립니다. 이를 해결하기 위해, 오브젝트는 자료의 값이 적은 순으로 정렬되어 있지만 이 정렬을 하느데도 값이 듭니다.
  • 3D 물리학에도 비슷한 상황이 생깁니다. 큰 값의 물리 물체를 다루는 데의 최고의 알고리즘은 (SAP와 같은) 물체의 삽입/삭제와 레이캐스팅(ray-cating_에서 굉장히 느립니다. 알고리즘은 더 빠른 삽입과 삭제를 허용하며, 레이캐스팅은 많은 활성 오브첵트를 처리할 수 없습니다.

이에 대한 예가 더욱 많습니다! 게임 엔진은 본질적으로 일반적인 목적을 위해 노력하므로 균형 잡힌 알고리즘은 일부 상황에서는 빠르지만 다른 상황에서는 느릴 수 있는 알고리즘보다 빠르며, 사용하기는 어렵지만 빠른 알고리즘은 항상 선호되는 편입니다.


고도도 예외가 아니며, 뒷단에서 다른 알고리즘이 스왑 가능하게 설계되어 있으며, 기본 설정으로 (또는 더 많은 것, 거기에 있는 유일한 것) 성능보다 균형과 유연성의 우선순위를 지정하십시오.


이를 명확하게 하려면, 이 튜토리얼은 어떻게 고도에서 최고의 성능을 얻는지를 모표로 한다는 것을 알려드립니다.



렌더링


3D 렌더링은 성능을 얻기 가장 어려운 영역이며 그래서 이 섹션은 팁의 목록을 보여드릴까합니다.



쉐이더와 자료의 재사용


고도의 렌더러는 시중의 것들과는 조금 다릅니다. GPU 상태 변경을 가능한 한 최소화하도록 설계되어 있습니다. FixedMaterial은 비슷한 쉐이더가 팔요한 자료의 재사용에는 좋은 성능을 보이지만, 만약 커스템 쉐이더가 사용중이면 가능한 한 그 들을 재사용하도록 해야합니다. 고도의 우선순위는 다음과 같습니다 :


  • 자료의 재사용 : 씬에서 적은 양의 다른 자료가 렌더링을 빠르게 해줍니다. 만약 씬이 거대한 양의 오브젝트(수백개 또는 수천개)를 가지고 자료를 재사용 하거나 최악의 경우에는 아틀라스를 사용합니다. (The less amount of different materials in the scene, the faster the rendering will be. If a scene has a huge amount of objects (in the hundreds or thousands) try reusing the materials or in the worst case use atlases.)
  • 쉐이더의 재사용 : 만약 자료가 재사용 될 수 없으면, 최소한 쉐이더를 재사용 할 수 있게 노력해보세요 (또는 다른 매개변수를 가지지만 같은 설정을 가진 FixedMaterials).

만약 씬이 예를 들어 2만개의 다른 자료를 각각 가지는 2만개의  오브젝트를 가진다면 렌더링은 정말 느릴 것입니다. 만약 같은 씬에 2만개의 오브젝트를 가지지만 100개의 자료만이 있다면 렌더링은 빛날 정도로 빠를 것입니다.


픽셀에 들어가는 값 vs 정점에 들어가는 값


모델의 다각형을 줄이면 빠르게 렌더링 된다는 것은 일반적인 생각입니다. 이건 정말로 여러 요인에 연관됩니다.


최근에 PC와 콘솔에서는 정점에 들어가는 값이 낮습니다. 매우 낮습니다. GPU는 원래 삼각형만 렌더링하며, 그러므로 모든 정점은 :


  1. CPU에 의해 변환되어야합니다 (오려내는 것을 포함해서)
  2. RAM에서 GPU 메모리로 전송되어야 합니다.

요즘은 이 모든게 GPU 내에서 다루어지기 때문에 성능이 매우 높습니다. 3D 아티스트는 보통 모델링에 들어가는 다각형의 개수와 성능에 대해서 잘못된 감정을 가지고 있습니다. 왜냐하면 3D DCC(Blender나 Max 등)는 CPU 메모리 안의 기하학을 가지고 있을 필요가 있으며 그것을 편집하기 위해, 실제 성능을 줄여야합니다. 진실은, 모델은 3D 엔진에 의해 렌더링되는 것이  3D DCC에 비해  더 긍정적입니다.


모바일 기기에서는, 얘기가 좀 달라집니다. PC와 콘솔 GPU는 전력망에서 필요한 전력을 마구 가져다가 쓰는 막무가내의 괴물입니다. 모바일 GPU는 작은 배터리에 의해 제한되어 있어서, 더 큰 파워 효율이 필요합니다.


더 효율적으로 하기 위해 모바일 GPU는 오버드로우를 피하려고 시도합니다. 이는 화면에 같은 픽셀이 한 번 이상 렌더링 (조명 계산 등 같이) 된다는 뜻입니다. 몇몇 빌딩이 있는 마을을 상상해 보세요, GPU는  그리기 전까지는 어떤 것이 보이고 어떤 것이 숨겨져 있는지 잘 알지 못합니다. 한 집이 아마 그려지고 다른 집이 그앞에 그려집니다 (같은 픽셀에 두 번에 렌더링이 됩니다!). PC GPU는 일반적으로 이에 대해서 크게 신경쓰지 않고 성능을 높이기 위해서 더 많은 픽셀 프로세서를 하드웨어에 던집니다 (하지만 파워 소모가 증가하겠죠).


모바일에서는, 파워를 더 끌어다 쓰는 것은 선택사항입니다. 그래서 화면을 격자로 나누는 "Tile Based Rendering"이라 불리는 기술이 사용됩니다 (거의 대부분의 모바일 하드웨어가 다른 형태로 사용합니다). 각 셀은 그려진 삼각형의 목록을 유지하고 오버드로우를 최소화하기 위해 깊이별로 정렬합니다. 이 기술은 성능을 높이고 전력 소모를 줄이지만, 정점 성능에 큰 타격을 줍니다. 결과적으로, 드로잉을 위해 정점과 삼각형을 덜 처리할 수 있습니다.


일반적으로, 이는 그렇게 나쁘지 않지만, 화면의 작은 부분에 많은 기하학이 있는 작은 물체가 모바일에서 코너 케이스가 되는 것을 피해야만 합니다.


※ 코너 케이스 : 여러가지 변수와 환경의 복합적인 상호작용으로 발생하는 문제


이는 모바일 GPU의 단일 스크린 셀에서 많은 긴장을 강제하고 고려할만큼 저하된 성능을 보입니다 (다른 모든 셀은 프레임 표시를 위해 완료될 때까지 기다려야하므로).


간단하게 말해서, 모바일에서 정점 개수에 대해서 크게 걱정하지 않아도 되지만, 화면의 작은 부분에 정점이 집중되는 것을 피하라는 것입니다. 만약 예를 들어, 캐릭터, NPC, 차량 등이 멀다면 (그래서 작아보인다면), 더 작은 디테일 레벨 모델(LOD)을 대신 사용하세요.


정점 비용을 고려해야하는 추가 상황은 다음과 같이 정점 당 추가 처리가 필요한 오브젝트입니다 :


  • 스키닝 (스켈레톤 애니메이션)
  • 모르프 (쉐이프 키)
  • 정점 조명 오브젝트 (모바일에서 일반적임)


텍스쳐 압축


고도는 임포트 되었을 때 3D 모델 텍스쳐 압축(VRAM 압축)을 제공합니다. 비디오 RAM 압축은 저장시 PNG 또는 JPG와 같이 크기면에서 효율적이지 않지만 그릴 때 성능을 크게 향상시킵니다.


이는 텍스쳐 압축의 주요 목표가 메모리와 GPU 간의 대역폭 감소이기 때문입니다.


3D에서는, 오브젝트의 모양이 텍스쳐보다 기하학에 의존하므로 압축은 일반적으로 알아차리기 어렵다. 2D에서는, 압축은 텍스쳐 안의 모양(shapes)에 의존하므로 압축으로부터 아티팩팅 결과가 더 눈에 띕니다.


경고하자면, 대부분의 안드로이드 장치는 투명한 (오직 불투명체만) 텍스쳐의 텍스쳐 압축을 지원하지 않습니다. 마음에 새겨두세요.



투명한 오브젝트


이전에 언급했듯이, 고도는 성능을 증가시키기 위해 오브젝트를 재료와 쉐이더에 의해 정렬합니다. 하지만, 이는 투명한 오브젝트에는 적용되지 않습니다. 투명 오브젝트가 뒤에서 앞으로 렌더링되어 작업 뒤에 있는 것과 블렌딩됩니다. 결과적으로, 투명 오브젝트는 최소화하려고 하세요! 만약 오브젝트가 투명성을 띈 작은 부위를 가진다면, 그 부분을 분리된 재료로 만드세요.



디테일의 레벨 (LOD)


이전에 언급했듯이, 적은 정점을 가진 오브젝트를 사용하는 것은 몇몇 경우에 성능을 증가시킬 수 있습니다. 고도는 디테일의 레벨에 대해 매우 간단한 시스템을 가지며, GeometryInatance 기반 오브젝트는 정의할 수 있는 가시 범위를 가지고 있습니다. 몇몇 다른 범위에서 GeometryInstance 오브젝트를 가지는 것은 LOD로서 작동합니다.


사용 인스턴스화 (멀티메시)


만약 몇몇 동일한 오브젝트가 같은 위치나 비슷한 곳에 그려져야 한다면, MultiMesh를 대신 사용해보세요. 멀티메시는 수천개의 오브젝트의 수십개의 그림을 그릴 때 정말 적은 성능 값으로 그리도록 허용해 줍니다. 같은 양떼, 풀, 파티클 등을 말이죠.



베이크 조명


작은 조명은 대부분 성능 문제가 되지 못한다. 그림자는 조금 더하다. 일반적으로 만약 몇몇 조명이 씬에 영향을 끼친다면 베이크 (doc_light_baking)하는 것이 이상적입니다. 베이킹은 간접 조명을 더함으로 씬의 질을 높이는 데 도움이 됩니다.


만약 모바일에서 작동한다면, 텍스쳐를 베이킹하는 것이 추천됩니다. 왜냐하면 이 방법은 빠르기까지 하기 때문입니다.