Unity - керівництво оптимізація продуктивності графіки

Оптимізація продуктивності графіки

Хороша продуктивність критична для багатьох ігор. Нижче дані прості поради по захопленню швидкості рендеринга у вашій грі.

Яка вартість графіки

Графічна частина вашої гри навантажує в першу чергу дві системи комп'ютера: GPU (графічний процесор) і CPU (центральний процесор). Перше правило будь-якої оптимізації: знайти, де виникає проблема. так як стратегія оптимізації для GPU і CPU має істотні відмінності (іноді навіть виникає ситуація, коли при оптимізації для GPU більше навантаження лягає на CPU і навпаки).

Типові вузькі місця і їх перевірка:

  • GPU часто обмежений філлрейтом (fillrate) або пропускною спроможністю пам'яті.
  • Запуск гри з більш низьким дозволом екрану збільшує продуктивність? Тоді ви швидше за все обмежені філлрейтом GPU.
  • CPU часто обмежений кількістю речей, які повинні бути намальовані, також відомо, як "draw calls".
  • Перевірте показателль "draw calls" у вікні Rendering Statistics; якщо він становить більше кількох тисяч (для PC) або декількох сотень (для мобільних пристроїв), то вам може знадобитися оптимізація кількості об'єктів.
  • GPU обробляє занадто багато вершин. Яка кількість вершин є нормальним, визначається GPU і набором вертексних шейдеров. Можна порадити використовувати не більше 100 тисяч для мобільних пристроїв і не більше декількох мільйонів для PC.
  • The CPU has too many vertices to process. This could be in skinned meshes, cloth simulation, particles, or other game objects and meshes. As above, it is generally good practice to keep this number as low as possible without compromising game quality. See the section on CPU optimization below for guidance on how to do this.
  • Візуалізація НЕ створює проблем ні для GPU, ні для CPU. Проблема може бути, наприклад, в скриптах або фізики. Використовуйте профайлер для пошуку джерела проблеми.

CPU optimization

All this "per object" CPU usage is resource-intensive, so if you have lots of visible objects, it can add up. For example, if you have a thousand triangles, it is much easier on the CPU if they are all in one mesh, rather than in one mesh per triangle (adding up to 1000 meshes). The cost of both scenarios on the GPU is very similar, but the work done by the CPU to render a thousand objects (instead of one) is significantly higher.

Reduce the visible object count. To reduce the amount of work the CPU needs to do:

  • Об'єднуйте близько розташовані об'єкти: вручну або використовуючи інструмент draw call batching в Unity.
  • Використовуйте менше матеріалів, об'єднуйте текстури в великі текстурні атласи.
  • Використовуйте менше об'єктів, які повинні візуалізувати кілька разів (відображення, тіні, попіксельно джерела світла і т. П. Дивіться нижче).

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

Однак, коли ви використовуєте багато піксельних джерел світла при Forward rendering path. бувають ситуації, в яких не має сенсу об'єднувати об'єкти, це більш докладно описано нижче.

GPU: Оптимізація геометрії моделей

There are two basic rules for optimizing the geometry of a model:

  • Не використовуйте трикутників більше, ніж необхідно
  • Намагайтеся тримати кількість швів на UV-карті і кількість жорстких ребер (подвоює вершини) якомога нижчим

У той час як кількість геометрії в моделях впливає в першу чергу на GPU, деякі функції Unity припускають обробку моделей і на CPU, наприклад mesh skinning.

Найшвидше освітлення - це те, яке не розраховується. Використовуйте карти освітлення для запікання статичного освітлення замість розрахунку освітлення в кожному кадрі. Процес створення карт освітлення вимагає багато часу, ніж просте розміщення джерел світла в сцені, але:

  • Це набагато швидше працює (в 2-3 рази в порівнянні з 2 пиксельними джерелами світла)
  • Це виглядає краще, так як ви можете запекти глобальне освітлення і з більш високою якістю

У багатьох випадках можна замінити розміщення джерел світла правильному налаштуванні шейдеров і контенту. Для прикладу, замість розміщення джерела світла прямо перед камерою для отримання ефекту "підсвічування країв моделі" (rim lighting), простіше додати розрахунок цього ефекту прямо в шейдера.

Освітлення в forward rendering

Освітлення в forward rendering

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

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

В процесі візуалізації Unity знаходить все джерела світла навколо заважав і розраховує їх важливість для даного заважав. В налаштуваннях Quality Settings можна задати, скільки джерел світла в кінці кінців може використовуватися для освітлення кожного заважав. Для кожного джерела світла його пріоритет обчислюється на підставі відстані до заважав і яскравості цього джерела світла. Також має значення параметр Render Mode всередині компонента Light, який може приймати два значення: Important або Not Important. Джерела світла, помічені як Not Important мають більш низький пріоритет.

Для прикладу розглянемо гру, де гравець управляє автомобілем, що рухається в темряві з включеними фарами. Швидше за все, передні фари будуть найбільш важливим джерелом світла в грі і параметр Render Mode буде встановлений для них в значення Important. Задні ліхтарі будуть менш важливі, не надаючи значного впливу на кінцеве зображення, так що для них Render Mode можна встановити в Not Important. заощадивши тим самим апаратні ресурси.

Оптимізація пиксельного освітлення зберігає ресурси і CPU і GPU: CPU робить менше draw calls, а GPU обробляє менше вершин і растеризуются менше пікселів для кожного додаткового об'єкта.

GPU: стиснення текстур і міпмапи

Використання стислих текстур зменшує розмір ваших текстур (в результаті вони швидше завантажуються і займають менше пам'яті), а також може значно підвищити продуктивність. Стислі текстури використовують малу частину пропускної здатності пам'яті, в порівнянні з 32-бітними RGBA-текстурами.

Використання міпмап для текстур

Як правило, параметр імпорту Generate Mip Maps включений для текстур, які використовуються в 3D-сцені. В цьому випадку стиснення текстур допоможе обмежити кількість текстурних даних, що транспортуються в GPU при візуалізації. Мімпапи дозволяють GPU використовувати для маленьких трикутників текстури зниженого дозволу.

Є виключення з цього правила: коли один тексель (піксель текстури) відповідає одному пікселю екрану, що зустрічається в елементах користувальницького інтерфейсу і в 2D-іграх.

LOD і пошарове завдання дистанції для сulling

Culling objects involves making objects invisible. This is an effective way to reduce both the CPU and GPU load.

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

There are a number of ways you can achieve this:

Manually set per-layer culling distances on the camera

Це може бути досягнуто використанням системи Level Of Detail або налаштуванням дистанції обрізки для камери по верствам. Ви можете помістити дрібні об'єкти в окремий шар і поставити йому дистанцію обрізки, використовуючи властивість Camera.layerCullDistances.

Тіні в реальному часі

Тіні в реальному часі добре виглядають, але вони можуть сильно знижувати продуктивність, одночасно додаючи додаткові draw calls для CPU і додаткову обробку для GPU. Деталі описано на сторінці Shadows.

GPU: поради для написання високопродуктивних шейдеров

Different platforms have vastly different performance capabilities; a high-end PC GPU can handle much more in terms of graphics and shaders than a low-end mobile GPU. The same is true even on a single platform; a fast GPU is dozens of times faster than a slow integrated GPU.

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

Нижче наведено кілька порад, які важливі для GPU в мобільних пристроях і PC низького рівня:

Складні математичні операції

Transcendental mathematical functions (such as pow. Exp. Log. Cos. Sin. Tan) are quite resource-intensive, so avoid using them where possible. Consider using lookup textures as an alternative to complex math calculations if applicable.

Avoid writing your own operations (such as normalize. Dot. Inversesqrt). Unity's built-in options ensure that the driver can generate much better code. Remember that the Alpha Test (discard) operation often makes your fragment shader slower.

Операції з плаваючою точкою

While the precision (float vs half vs fixed) of floating point variables is largely ignored on desktop GPUs, it is quite important to get a good performance on mobile GPUs. See the Shader Data Types and Precision page for details.

Подробиці про продуктивність шейдеров можна прочитати на сторінці Shader Performance.

Список кроків для збільшення продуктивності вашої гри

Приклад - створення площині-білборда

Батчінг викликів відтворення (Draw Call Batching)