Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
최적화(Optimization)
소개
새로운 그래픽 기능과 발전에 대한 요구로 인해 그래픽 병목 현상이 발생할 가능성이 거의 높습니다. 이들 중 일부는 CPU 측에 있을 수 있습니다. 예를 들어 렌더링할 객체를 준비하기 위한 Godot 엔진 내부 계산에서 그렇습니다. GPU에 전달할 명령을 정렬하는 그래픽 드라이버의 CPU와 이러한 명령을 전송할 때 병목 현상이 발생할 수도 있습니다. 그리고 마지막으로 GPU 자체에서도 병목 현상이 발생합니다.
렌더링 시 병목 현상이 발생하는 위치는 하드웨어에 따라 다릅니다. 특히 모바일 GPU는 데스크탑에서 쉽게 실행되는 장면에서 어려움을 겪을 수 있습니다.
GPU 병목 현상을 이해하고 조사하는 것은 CPU의 상황과 약간 다릅니다. GPU에 제공하는 명령을 변경하여 간접적으로만 성능을 변경할 수 있는 경우가 많기 때문입니다. 또한 측정이 더 어려울 수도 있습니다. 대부분의 경우 성능을 측정하는 유일한 방법은 각 프레임을 렌더링하는 데 소요되는 시간의 변화를 조사하는 것입니다.
그리기 호출, 상태 변경 및 API
참고
다음 섹션은 최종 사용자와 관련이 없지만 이후 섹션과 관련된 배경 정보를 제공하는 데 유용합니다.
Godot는 그래픽 API(Vulkan, OpenGL, OpenGL ES 또는 WebGL)를 통해 GPU에 명령을 보냅니다. 관련된 통신 및 드라이버 활동은 특히 OpenGL, OpenGL ES 및 WebGL에서 비용이 많이 들 수 있습니다. 드라이버와 GPU가 선호하는 방식으로 이러한 지침을 제공할 수 있다면 성능을 크게 향상시킬 수 있습니다.
OpenGL의 거의 모든 API 명령에는 GPU가 올바른 상태인지 확인하기 위해 일정량의 검증이 필요합니다. 겉으로는 단순해 보이는 명령이라도 이면의 관리 작업으로 이어질 수 있습니다. 따라서 목표는 이러한 명령을 최소한으로 줄이고 유사한 개체를 가능한 한 많이 함께 그룹화하여 함께 렌더링하거나 비용이 많이 드는 상태 변경 횟수를 최소화하는 것입니다.
2D 배칭
2D에서는 각 항목을 개별적으로 처리하는 데 드는 비용이 엄청나게 높을 수 있습니다. 화면에 항목이 수천 개나 있을 수 있기 때문입니다. 이것이 2D *배칭*이 사용되는 이유입니다. 여러 유사한 항목은 각 항목에 대해 별도의 그리기 호출을 수행하는 대신 단일 그리기 호출을 통해 함께 그룹화되고 일괄적으로 렌더링됩니다. 또한 이는 상태 변경, 재료 및 질감 변경을 최소한으로 유지할 수 있음을 의미합니다.
3D 일괄 처리
3D에서는 여전히 드로우 콜과 상태 변경을 최소화하는 것을 목표로 하고 있습니다. 그러나 여러 개체를 단일 그리기 호출로 일괄 처리하는 것이 더 어려울 수 있습니다. 3D 메시는 수백 또는 수천 개의 삼각형으로 구성되는 경향이 있으며 대규모 메시를 실시간으로 결합하는 데는 엄청나게 많은 비용이 듭니다. 메시당 삼각형 수가 증가함에 따라 연결 비용이 모든 이점을 빠르게 초과합니다. 훨씬 더 나은 대안은 **미리 메시를 결합**하는 것입니다(서로 관련된 정적 메시). 이는 아티스트가 수행하거나 추가 기능을 사용하여 Godot 내에서 프로그래밍 방식으로 수행할 수 있습니다.
3D로 개체를 일괄 처리하는 데에도 비용이 듭니다. 하나로 렌더링된 여러 객체는 개별적으로 컬링될 수 없습니다. 화면 밖에 있는 도시 전체가 화면에 있는 풀잎 하나에 결합되면 여전히 렌더링됩니다. 따라서 3D 개체를 함께 일괄 처리하려고 시도할 때는 항상 개체의 위치와 컬링을 고려해야 합니다. 그럼에도 불구하고 정적 개체를 결합하면 다른 고려 사항보다 더 큰 이점이 있는 경우가 많습니다. 특히 멀리 떨어져 있거나 폴리곤이 낮은 개체가 많은 경우에는 더욱 그렇습니다.
3D 특정 최적화에 대한 자세한 정보는 성능를 참조하세요.
셰이더 및 재료 재사용
Godot 렌더러는 기존의 렌더러와 약간 다릅니다. GPU 상태 변경을 최대한 최소화하도록 설계되었습니다. :ref:`StandardMaterial3D <class_StandardMaterial3D>`은 유사한 셰이더가 필요한 재료를 재사용하는 데 능숙합니다. 맞춤형 셰이더를 사용하는 경우 최대한 재사용하도록 하세요. Godot의 우선순위는 다음과 같습니다:
재료 재사용: 씬의 다양한 재료가 적을수록 렌더링 속도가 빨라집니다. 씬에 엄청난 양의 개체(수백 또는 수천 개)가 있는 경우 해당 재료를 재사용해 보세요. 최악의 경우에는 아틀라스를 사용하여 텍스처 변경량을 줄이세요.
셰이더 재사용: 재료를 재사용할 수 없다면 최소한 셰이더를 재사용해 보세요. 참고: 셰이더는 매개변수가 다르더라도 동일한 구성(확인란을 통해 활성화 또는 비활성화되는 기능)을 공유하는 StandardMaterial3D 간에 자동으로 재사용됩니다.
예를 들어 씬에 각각 20,000개의 서로 다른 재질이 포함된 20,000개의 객체가 있는 경우 렌더링 속도가 느려집니다. 동일한 씬에 20,000개의 객체가 있지만 100개의 재질만 사용하는 경우 렌더링 속도가 훨씬 빨라집니다.
픽셀 비용과 정점 비용 비교
모델의 다각형 수가 적을수록 렌더링 속도가 빨라진다는 말을 들어보셨을 것입니다. 이는 실제로 상대적이며 여러 요인에 따라 달라집니다.
최신 PC와 콘솔에서는 정점 비용이 낮습니다. GPU는 원래 삼각형만 렌더링했습니다. 이는 모든 프레임이 다음을 의미합니다.
모든 정점은 CPU에 의해 변환되어야 했습니다(클리핑 포함).
모든 정점은 메인 RAM에서 GPU 메모리로 전송되어야 했습니다.
요즘에는 이 모든 것이 GPU 내부에서 처리되어 성능이 크게 향상됩니다. 3D 모델링 소프트웨어(예: Blender, 3ds Max 등)는 편집을 위해 CPU 메모리에 형상을 유지해야 하므로 실제 성능이 저하되기 때문에 3D 아티스트는 일반적으로 폴리카운트 성능에 대해 잘못된 인식을 갖고 있습니다. 게임 엔진은 GPU에 더 많이 의존하므로 많은 삼각형을 훨씬 더 효율적으로 렌더링할 수 있습니다.
모바일 기기에서는 이야기가 다릅니다. PC와 콘솔 GPU는 전력망에서 필요한 만큼의 전력을 끌어낼 수 있는 무차별적인 괴물입니다. 모바일 GPU는 작은 배터리로 제한되므로 전력 효율이 훨씬 높아야 합니다.
보다 효율적이기 위해 모바일 GPU는 *오버드로*를 방지하려고 시도합니다. 오버드로우는 화면의 동일한 픽셀이 두 번 이상 렌더링될 때 발생합니다. 여러 건물이 있는 마을을 상상해 보세요. GPU는 그릴 때까지 무엇이 보이고 무엇이 숨겨져 있는지 알지 못합니다. 예를 들어, 집이 그려지고 그 앞에 또 다른 집이 그려질 수 있습니다. 이는 동일한 픽셀에 대해 렌더링이 두 번 발생했음을 의미합니다. PC GPU는 일반적으로 이에 대해 크게 신경 쓰지 않고 성능을 높이기 위해 하드웨어에 더 많은 픽셀 프로세서를 추가합니다(이로 인해 전력 소비도 늘어납니다).
더 많은 전력을 사용하는 것은 모바일에서 옵션이 아니므로 모바일 장치는 화면을 그리드로 나누는 *타일 기반 렌더링*이라는 기술을 사용합니다. 각 셀은 그려진 삼각형 목록을 유지하고 깊이별로 정렬하여 *오버드로*를 최소화합니다. 이 기술은 성능을 향상시키고 전력 소비를 줄이지만 정점 성능에 큰 타격을 줍니다. 결과적으로 그리기 위해 처리할 수 있는 꼭지점과 삼각형의 수가 더 적습니다.
또한 타일 기반 렌더링은 화면의 작은 부분 내에 많은 기하학적 구조를 가진 작은 개체가 있는 경우 어려움을 겪습니다. 이로 인해 모바일 GPU는 단일 화면 타일에 많은 부담을 주게 되며, 다른 모든 셀은 프레임을 표시하기 전에 완료될 때까지 기다려야 하므로 성능이 상당히 저하됩니다.
요약하자면, 모바일의 정점 개수에 대해 걱정하지 마세요. 하지만 화면의 작은 부분에 정점이 집중되는 것을 피하세요. 캐릭터, NPC, 차량 등이 멀리 떨어져 있는 경우(작아 보인다는 의미) 더 작은 LOD(레벨 오브 디테일) 모델을 사용하세요. 데스크톱 GPU에서도 화면의 픽셀 크기보다 작은 삼각형을 사용하지 않는 것이 좋습니다.
다음을 사용할 때 필요한 추가 정점 처리에 주의하세요.
스키닝(골격 애니메이션)
Morph(모양 키)
정점 조명 개체(모바일에서 일반적임)
픽셀/조각 셰이더 및 채우기 속도
정점 처리와 대조적으로 프래그먼트(픽셀당) 셰이딩 비용은 수년에 걸쳐 극적으로 증가했습니다. 화면 해상도가 증가했습니다. 4K 화면의 영역은 8,294,400픽셀로 기존 640×480 VGA 화면의 영역은 307,200픽셀입니다. 그것은 면적의 27배입니다! 또한 셰이더 조각의 복잡성이 폭발했습니다. 물리적 기반 렌더링에는 각 조각에 대한 복잡한 계산이 필요합니다.
프로젝트의 채우기 비율이 제한되어 있는지 여부를 아주 쉽게 테스트할 수 있습니다. 초당 프레임 수 제한을 방지하려면 V-Sync를 끄고 큰 창으로 실행할 때와 매우 작은 창으로 실행할 때의 초당 프레임 수를 비교하세요. 그림자를 사용하는 경우 그림자 맵 크기를 비슷하게 줄이는 것도 이점이 있습니다. 일반적으로 작은 창을 사용하면 FPS가 상당히 증가하는 것을 볼 수 있는데, 이는 채우기 속도가 어느 정도 제한되어 있음을 나타냅니다. 반면, FPS가 거의 또는 전혀 증가하지 않으면 병목 현상은 다른 곳에 있는 것입니다.
You can increase performance in a fill rate-limited project by reducing the amount of work the GPU has to do. You can do this by simplifying the shader (perhaps turn off expensive options if you are using a StandardMaterial3D), or reducing the number and size of textures used. Also, when using shaded particles, consider forcing vertex shading in their material to decrease the shading cost.
더 보기
지원되는 하드웨어에서 :ref:`doc_variable_rate_shading`를 사용하면 최종 이미지의 가장자리 선명도에 영향을 주지 않고 음영 처리 비용을 줄일 수 있습니다.
모바일 장치를 대상으로 하는 경우 합리적으로 사용할 수 있는 가장 간단한 셰이더를 사용하는 것이 좋습니다.
텍스처 가져오기
조각 셰이더의 또 다른 요소는 텍스처를 읽는 비용입니다. 텍스처를 읽는 것은 비용이 많이 드는 작업입니다. 특히 단일 조각 셰이더의 여러 텍스처에서 읽을 때 더욱 그렇습니다. 또한 필터링으로 인해 속도가 더 느려질 수 있다는 점을 고려하세요(밉맵 간의 삼선형 필터링 및 평균화). 텍스처를 읽는 것도 전력 사용량 측면에서 비용이 많이 들며 이는 모바일에서 큰 문제입니다.
타사 셰이더를 사용하거나 자체 셰이더를 작성하는 경우 가능한 한 적은 수의 텍스처 읽기가 필요한 알고리즘을 사용해 보십시오.
텍스처 압축
기본적으로 Godot는 비디오 RAM(VRAM) 압축을 사용하여 가져올 때 3D 모델의 텍스처를 압축합니다. 비디오 RAM 압축은 저장할 때 크기가 PNG나 JPG만큼 효율적이지는 않지만, 충분히 큰 텍스처를 그릴 때 성능이 엄청나게 향상됩니다.
텍스처 압축의 주요 목표는 메모리와 GPU 간의 대역폭을 줄이는 것이기 때문입니다.
3D에서는 물체의 모양이 텍스처보다는 형상에 더 많이 의존하므로 일반적으로 압축이 눈에 띄지 않습니다. 2D에서는 압축이 텍스처 내부의 모양에 더 많이 의존하므로 2D 압축으로 인한 아티팩트가 더 눈에 띕니다.
경고하자면, 대부분의 Android 장치는 투명도(불투명만)가 있는 텍스처의 텍스처 압축을 지원하지 않으므로 이 점을 염두에 두십시오.
참고
3D에서도 "픽셀 아트" 텍스처는 낮은 해상도로 인해 성능이 크게 향상되지 않고 모양에 부정적인 영향을 미치기 때문에 VRAM 압축을 비활성화해야 합니다.
프로세싱(Processing)
후처리 효과와 그림자는 프래그먼트 셰이딩 활동 측면에서 비용이 많이 들 수도 있습니다. 항상 이러한 요소가 다른 하드웨어에 미치는 영향을 테스트하십시오.
섀도우맵의 크기를 줄이면 섀도우맵 쓰기 및 읽기 측면에서 성능이 향상될 수 있습니다. 또한 그림자 성능을 향상시키는 가장 좋은 방법은 가능한 한 많은 조명과 개체에 대해 그림자를 끄는 것입니다. 더 작거나 멀리 있는 OmniLights/SpotLights는 종종 약간의 시각적 영향만으로 그림자를 비활성화할 수 있습니다.
투명성과 블렌딩
투명한 객체는 렌더링 효율성에 있어 특별한 문제를 나타냅니다. 불투명한 개체(특히 3D)는 기본적으로 어떤 순서로든 렌더링될 수 있으며 Z 버퍼는 가장 앞쪽의 개체만 음영처리되도록 보장합니다. 투명하거나 혼합된 개체는 다릅니다. 대부분의 경우 Z 버퍼에 의존할 수 없으며 올바르게 보이려면 "페인터의 순서"(즉 뒤에서 앞으로)로 렌더링해야 합니다.
투명한 개체는 특히 채우기 속도에 좋지 않습니다. 나중에 다른 투명 개체를 맨 위에 그려도 모든 항목을 그려야 하기 때문입니다.
불투명한 객체는 이 작업을 수행할 필요가 없습니다. 일반적으로 먼저 Z 버퍼에 쓴 다음 특정 픽셀의 앞에 있는 객체인 "승리" 조각에 대해 조각 셰이더만 수행하여 Z 버퍼를 활용할 수 있습니다.
투명도는 여러 투명 객체가 겹치는 경우 특히 비용이 많이 듭니다. 일반적으로 채우기 속도 요구 사항을 최소화하려면 투명한 영역을 가능한 한 작게 사용하는 것이 좋습니다. 특히 채우기 속도가 매우 비싼 모바일에서는 더욱 그렇습니다. 실제로 많은 상황에서 더 복잡한 불투명 형상을 렌더링하는 것이 투명도를 사용하여 "속임수"하는 것보다 더 빠를 수 있습니다.
멀티 스레딩(Multi-threading)
여러 플랫폼에 출시하려는 경우 모든 플랫폼, 특히 모바일에서 초기 테스트하고 자주 테스트하세요. 데스크톱에서 게임을 개발했지만 마지막 순간에 모바일로 이식하려고 시도하는 것은 재앙을 불러오는 비결입니다.
일반적으로 가장 낮은 공통 분모로 게임을 디자인한 다음 보다 강력한 플랫폼을 위해 선택적 개선 사항을 추가해야 합니다. 예를 들어 데스크톱과 모바일 플랫폼을 모두 대상으로 하는 호환성 렌더링 방법을 사용할 수 있습니다.
모바일/타일식 렌더러
위에서 설명한 대로 모바일 장치의 GPU는 데스크톱의 GPU와 크게 다른 방식으로 작동합니다. 대부분의 모바일 장치는 타일 렌더러를 사용합니다. 타일 렌더러는 화면을 초고속 캐시 메모리에 맞는 일반 크기 타일로 분할하여 주 메모리에 대한 읽기/쓰기 작업 수를 줄입니다.
하지만 몇 가지 단점이 있습니다. 타일링된 렌더링은 특정 기술을 수행하는 데 훨씬 더 복잡하고 비용이 많이 들 수 있습니다. 다른 타일의 렌더링 결과나 보존되는 이전 작업의 결과에 의존하는 타일은 매우 느릴 수 있습니다. 셰이더, 뷰포트 텍스처 및 후처리의 성능을 테스트할 때는 매우 주의해야 합니다.