Up to date

This page is up to date for Godot 4.2. If you still find outdated information, please open an issue.

Оптимізація Графічного Процесора

Вступ

Попит на нові графічні можливості та прогрес майже гарантує, що ви зіткнетеся з вузькими місцями в графіці. Деякі з них можуть бути на стороні центрального процесора, наприклад, під час обчислень всередині рушія Godot для підготовки об'єктів до рендерингу. Вузькі місця також можуть виникати на центральному процесорі в графічному драйвері, який сортує інструкції для передачі на графічний процесор, і в процесі передачі цих інструкцій. І, нарешті, вузькі місця виникають і на самому графічному процесорі.

Вузькі місця в рендерингу залежать від апаратного забезпечення. Зокрема, мобільні графічні процесори можуть не справлятися зі сценами, які легко відтворюються на настільних.

Розуміння та дослідження вузьких місць графічного процесора дещо відрізняється від ситуації на центральному процесорі. Це пов'язано з тим, що часто ви можете змінити продуктивність лише опосередковано, змінюючи інструкції, які ви даєте графічному процесору. Крім того, може бути складніше провести вимірювання. У багатьох випадках єдиний спосіб виміряти продуктивність - це дослідити зміни у часі, витраченому на малювання кожного кадру.

Виклики малювання, зміни стану та API

Примітка

Наступний розділ не стосується кінцевих користувачів, але корисний для надання довідкової інформації, яка буде використана в наступних розділах.

Godot sends instructions to the GPU via a graphics API (Vulkan, OpenGL, OpenGL ES or WebGL). The communication and driver activity involved can be quite costly, especially in OpenGL, OpenGL ES and WebGL. If we can provide these instructions in a way that is preferred by the driver and GPU, we can greatly increase performance.

Майже кожна команда API в OpenGL вимагає певної перевірки, щоб переконатися, що графічний процесор знаходиться в правильному стані. Навіть, здавалося б, прості команди можуть призвести до шквалу закулісної роботи. Тому мета полягає в тому, щоб звести ці команди до мінімуму і згрупувати схожі об'єкти якомога більше, щоб їх можна було вимальовувати разом або з мінімальною кількістю змін стану.

2D пакетування

In 2D, the costs of treating each item individually can be prohibitively high - there can easily be thousands of them on the screen. This is why 2D batching is used with OpenGL-based rendering methods. Multiple similar items are grouped together and rendered in a batch, via a single draw call, rather than making a separate draw call for each item. In addition, this means state changes, material and texture changes can be kept to a minimum.

Vulkan-based rendering methods do not use 2D batching yet. Since draw calls are much cheaper with Vulkan compared to OpenGL, there is less of a need to have 2D batching (although it can still be beneficial in some cases).

3D пакетування

In 3D, we still aim to minimize draw calls and state changes. However, it can be more difficult to batch together several objects into a single draw call. 3D meshes tend to comprise hundreds or thousands of triangles, and combining large meshes in real-time is prohibitively expensive. The costs of joining them quickly exceeds any benefits as the number of triangles grows per mesh. A much better alternative is to join meshes ahead of time (static meshes in relation to each other). This can be done by artists, or programmatically within Godot using an add-on.

Пакетне об'єднання об'єктів у 3D також має певні витрати. Кілька об'єктів, зображених як один, не можуть бути вибраковані окремо. Ціле місто, яке знаходиться за межами екрану, все одно буде зображене, якщо його приєднати до однієї травинки, яка знаходиться на екрані. Таким чином, при спробі об'єднати 3D-об'єкти слід завжди враховувати розташування об'єктів та можливість їхнього відсіювання. Незважаючи на це, переваги об'єднання статичних об'єктів часто переважають інші міркування, особливо для великої кількості віддалених або низькополігональних об'єктів.

Для отримання додаткової інформації про специфічні 3D-оптимізації див. Optimizing 3D performance.

Reuse shaders and materials

The Godot renderer is a little different to what is out there. It's designed to minimize GPU state changes as much as possible. StandardMaterial3D does a good job at reusing materials that need similar shaders. If custom shaders are used, make sure to reuse them as much as possible. Godot's priorities are:

  • Повторне використання матеріалів: Чим менше різних матеріалів у сцені, тим швидшим буде рендеринг. Якщо у сцені велика кількість об'єктів (сотні або тисячі), спробуйте використовувати матеріали повторно. У гіршому випадку, використовуйте атласи, щоб зменшити кількість текстурних змін.

  • Reusing Shaders: If materials can't be reused, at least try to reuse shaders. Note: shaders are automatically reused between StandardMaterial3Ds that share the same configuration (features that are enabled or disabled with a check box) even if they have different parameters.

If a scene has, for example, 20,000 objects with 20,000 different materials each, rendering will be slow. If the same scene has 20,000 objects, but only uses 100 materials, rendering will be much faster.

Вартість пікселя в порівнянні з вартістю вершини

Можливо, ви чули, що чим менша кількість полігонів у моделі, тим швидше вона рендериться. Це насправді відносно і залежить від багатьох факторів.

На сучасному ПК та консолі вартість вершини є низькою. Спочатку графічні процесори рендерили лише трикутники. Це означало, що кожен кадр:

  1. Всі вершини повинні були бути перетворені процесором (включаючи відсікання).

  2. Всі вершини потрібно було відправити в пам'ять графічного процесора з основної оперативної пам'яті.

Nowadays, all this is handled inside the GPU, greatly increasing performance. 3D artists usually have the wrong feeling about polycount performance because 3D modeling software (such as Blender, 3ds Max, etc.) need to keep geometry in CPU memory for it to be edited, reducing actual performance. Game engines rely on the GPU more, so they can render many triangles much more efficiently.

На мобільних пристроях все інакше. Графічні процесори для ПК та консолей - це монстри грубої сили, які можуть тягнути з електромережі стільки електроенергії, скільки їм потрібно. Мобільні графічні процесори обмежені крихітним акумулятором, тому вони повинні бути набагато енергоефективнішими.

Щоб бути більш ефективними, мобільні графічні процесори намагаються уникати перемальовування. Перемальовування виникає, коли один і той самий піксель на екрані рендериться більше одного разу. Уявіть собі місто з кількома будівлями. Графічні процесори не знають, які є видимі, а які приховані, доки не намалюють їх. Наприклад, може бути намальований будинок, а потім інший будинок перед ним (це означає, що рендеринг відбувся двічі для одного і того ж пікселя). Графічні процесори ПК зазвичай не дуже переймаються цим і просто додають більше піксельних процесорів до апаратного забезпечення, щоб збільшити продуктивність (що також збільшує енергоспоживання).

На мобільних пристроях не можна використовувати більше енергії, тому вони використовують техніку, яка називається плитковий рендеринг, який ділить екран на сітку. Кожна комірка зберігає список намальованих до неї трикутників і сортує їх за глибиною, щоб мінімізувати перемальовування. Ця техніка покращує продуктивність і зменшує енергоспоживання, але негативно впливає на продуктивність вершин. Як наслідок, для малювання обробляється менша кількість вершин і трикутників.

Крім того, плитковий рендеринг не справляється з малими об'єктами зі складною геометрією в межах невеликої частини екрану. Це змушує мобільні графічні процесори сильно навантажувати одну плитку екрану, що значно знижує продуктивність, оскільки всі інші комірки повинні чекати на її завершення, перш ніж відобразити кадр.

Підсумовуючи, не турбуйтеся про кількість вершин на мобільному, але уникайте концентрації вершин у малих частинах екрану. Якщо персонаж, NPC, транспортний засіб тощо знаходиться далеко (тобто виглядає крихітним), використовуйте модель з меншим рівнем деталізації (LOD). Навіть на настільних графічних процесорах бажано уникати трикутників менших за розмір пікселя на екрані.

Зверніть увагу на додаткову обробку вершин, необхідну при використанні:

  • Скінінг (скелетної анімації)

  • Морфінг (ключі форми)

Піксельні/фрагментні шейдери та швидкість заповнення

In contrast to vertex processing, the costs of fragment (per-pixel) shading have increased dramatically over the years. Screen resolutions have increased: the area of a 4K screen is 8,294,400 pixels, versus 307,200 for an old 640×480 VGA screen. That is 27 times the area! Also, the complexity of fragment shaders has exploded. Physically-based rendering requires complex calculations for each fragment.

Перевірити, чи не обмежена частота заповнення проекту, дуже просто. Вимкніть 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 non-unshaded particles, consider forcing vertex shading in their material to decrease the shading cost.

Дивись також

On supported hardware, Variable rate shading can be used to reduce shading processing costs without impacting the sharpness of edges on the final image.

Якщо ви орієнтуєтесь на мобільні пристрої, використовуйте найпростіші шейдери, які ви можете собі дозволити.

Читання текстур

Іншим фактором у фрагментних шейдерах є вартість зчитування текстур. Зчитування текстур є дорогою операцією, особливо коли зчитується декілька текстур в одному фрагментному шейдері. Також враховуйте, що фільтрація може ще більше сповільнити її (трилінійна фільтрація між міпмапами та усереднення). Зчитування текстур також дорого коштує з точки зору використання енергії, що є великою проблемою на мобільних пристроях.

Якщо ви використовуєте сторонні шейдери або пишете власні, намагайтеся використовувати алгоритми, які вимагають якомога менше зчитувань текстури.

Стиснення текстури

За замовчуванням Godot стискає текстури 3D-моделей при імпорті, використовуючи стиснення відеопам'яті (VRAM). Стиснення відеопам'яті не таке ефективне при зберіганні, як PNG або JPG, але значно підвищує продуктивність під час малювання достатньо великих текстур.

Це пов'язано з тим, що основною метою стиснення текстур є зменшення пропускної здатності між пам'яттю та графічним процесором.

У 3D, форма об'єктів більше залежить від геометрії, ніж від текстури, тому стиснення, як правило, непомітне. У 2D стиснення більше залежить від форм всередині текстур, тому артефакти, що виникають в результаті 2D стиснення, більш помітні.

Попередження: більшість пристроїв Android не підтримують стиснення текстур з прозорістю (тільки непрозорі), тому майте це на увазі.

Примітка

Навіть у 3D для "піксельних" текстур слід вимкнути стиснення VRAM, оскільки воно негативно вплине на їхній зовнішній вигляд, не покращуючи при цьому продуктивність через низьку роздільну здатність.

Постобробка та тіні

Ефекти постобробки та тіні також можуть бути дорогими з точки зору активності затінення фрагментів. Завжди перевіряйте їхній вплив на різному обладнанні.

Зменшення розміру карти тіней може підвищити продуктивність, як з точки зору запису, так і з точки зору читання карти тіней. Крім того, найкращий спосіб покращити продуктивність тіней - це вимкнути тіні для якомога більшої кількості джерел світла та об'єктів. Для менших або віддалених OmniLights/SpotLights часто можна вимкнути тіні, що матиме лише невеликий візуальний вплив.

Прозорість і змішування

Прозорі об'єкти створюють особливі проблеми для ефективності рендерингу. Непрозорі об'єкти (особливо у 3D) можна візуалізувати у будь-якому порядку, а Z-буфер гарантує, що затінюватимуться лише передні частини об'єктів. З прозорими або змішаними об'єктами все інакше. У більшості випадків вони не можуть покладатися на Z-буфер і мають бути відрендереними у "порядку художника" (тобто ззаду наперед), щоб виглядати коректно.

Прозорі об'єкти також особливо погано впливають на заповнюваність, оскільки кожен об'єкт повинен бути намальований, навіть якщо згодом зверху будуть намальовані інші прозорі об'єкти.

Непрозорі об'єкти можуть цього не робити. Зазвичай вони можуть скористатися перевагами Z-буфера, записуючи спочатку в Z-буфер, а потім застосовуючи фрагментний шейдер лише до "переможного" фрагмента, тобто об'єкта, який знаходиться спереду на певному пікселі.

Прозорість особливо дорого коштує там, де кілька прозорих об'єктів накладаються один на одного. Зазвичай краще використовувати прозорі області якомога меншого розміру, щоб мінімізувати ці вимоги до заповнення, особливо на мобільних пристроях, де заповнення є дуже дорогим. Дійсно, у багатьох ситуаціях рендеринг складнішої непрозорої геометрії може виявитися швидшим, ніж використання прозорості для "обману".

Мультиплатформні поради

Якщо ви плануєте випустити гру на декількох платформах, тестуйте заздалегідь і тестуйте часто на всіх платформах, особливо на мобільних. Розробляючи гру для десктопів, намагатися перенести її на мобільні пристрої в останню хвилину - це рецепт катастрофи.

In general, you should design your game for the lowest common denominator, then add optional enhancements for more powerful platforms. For example, you may want to use the Compatibility rendering method for both desktop and mobile platforms where you target both.

Мобільні/плиткові рендерери

Як описано вище, графічні процесори на мобільних пристроях працюють кардинально інакше, ніж графічні процесори на десктопах. Більшість мобільних пристроїв використовують плитковий рендеринг. Плиткові рендери розбивають екран на плитки звичайного розміру, які поміщаються у надшвидку кеш-пам'ять, що зменшує кількість операцій читання/запису до основної пам'яті.

Однак є й деякі недоліки. Плитковий рендеринг може зробити певні техніки набагато складнішими та дорожчими у виконанні. Плитки, які покладаються на результати рендерингу в різних плитках або на збережені результати попередніх операцій, можуть працювати дуже повільно. Будьте дуже уважні під час тестування продуктивності шейдерів, текстур області перегляду та постобробки.