Как я могу уменьшить влияние на производительность рендеринга деревьев?

24

Я делаю низкополигональную стилизованную игру. У меня есть местность с небольшим количеством воды, и я хочу много-много деревьев; На данный момент у меня есть масса 10000 деревьев. Каждое дерево состоит не более чем из 200 треугольников, поэтому они не слишком обременительны.

Основная проблема в том, что здесь есть озера, а озера довольно большие. Вы не можете видеть деревья на другой стороне озера, и это выглядит очень плохо, особенно когда вы идете туда и деревья внезапно появляются.

Чтобы это исправить, мне нужно увеличить расстояние до деревьев, чтобы вы могли видеть приличное количество деревьев на другой стороне озера, но это снижает производительность до 40-50 кадров в секунду, и в игре пока ничего больше нет. Я использую GTX 1080, если это поможет.

Что я могу сделать, чтобы моя игра работала быстрее с большим количеством деревьев?

MR-матовый
источник
IIRC, Silent Hill использовал туман, чтобы скрыть отсечку в дальнем отсечном самолете, что позволило им начать динамическую загрузку вещей сразу за тем местом, где туман отсекается. Вы могли бы извлечь выгоду из изменения атмосферы игры.
Коди
Деревья притягивают вас, чтобы выглянуть в окно, что снижает вашу производительность.
mbomb007
Вы пробовали запустить профилировщик? Если так, то где узкое место?
Микаэль Хогстрем
Вы делаете какие-либо отбраковки?
Krythic
Что такое отбраковка усеченного конуса?
г -

Ответы:

43

Есть несколько вещей, которые вы можете сделать, чтобы повысить производительность рисования.

  1. Вы сказали, что они были довольно далеко. Вы можете использовать LOD, чтобы уменьшить количество вершин этих деревьев и, следовательно, уменьшить время, необходимое для прохождения всех прорисовываемых вершин. Хотя это, скорее всего, не проблема под рукой (GTX1080 с 10 000 деревьев по 200 трис в каждом, ничтожные цифры для GPU), я все же включил его. Рекламный щит - эффективный инструмент для самого низкого уровня LOD, поскольку он по сути является плоской плоскостью, всегда обращенной к камере с визуализированным изображением дерева на ней. Он теряет чувство глубины, поэтому хорошо подходит для самого низкого уровня, так как игрок, скорее всего, не заметит разницы.

  2. Вы включили дозирование ? Динамическое пакетирование обычно выполняется автоматически, если количество вершин в сетках достаточно мало. Статическое пакетирование также можно попробовать, сделав деревья статичными, установив флажок в редакторе единиц на родительском игровом объекте. Это плохо работает с анимированными объектами. Вам нужны объекты, чтобы иметь общий материал, чтобы сделать эту работу.

  3. Настраиваемая пакетная обработка позволяет вам управлять рендерингом, генерируя порции самостоятельно, вместо того, чтобы позволить единице обрабатывать его, а также позволяет пакетировать для больших сеток. Это легко сделать с помощью Mesh.CombineMeshes . Это также не очень хорошо работает с анимированными объектами. Вам нужны объекты, чтобы иметь общий материал, чтобы сделать эту работу. Вы, вероятно, хотите разделить свой мир на какие-то куски и создать пакеты из них. Как должны генерироваться эти фрагменты, зависит от того, как движется ваша камера в мире.

  4. Включить инстансинг на шейдерах. Instancing позволяет движку рисовать несколько объектов (с одной и той же сеткой) всего одним вызовом рисования. Вам нужно, чтобы объекты имели общий меш и общий шейдер, чтобы это работало. Материал может варьироваться, но шейдер должен поддерживать все различные свойства.

    Чтобы сделать движок лучше для создания экземпляров рендеринга, вы, вероятно, захотите сгруппировать одни и те же сетки в сцене. Также игра с очередью рендеринга материала даст вам хорошие результаты, если в одной сетке всегда один и тот же материал. Во время разработки мобильной игры, над которой я сейчас работаю, я использовал ее, чтобы уменьшить количество вызовов в моей тестовой сцене более чем наполовину. Также начиная с Unity 5.6 убедитесь, что вы отметили Enable Instancingфлажок в материале.

  5. Сдерживайте ваши вызовы и вызовы SetPass в целом. Это необработанные вызовы для графического процессора для рисования, и у них большие накладные расходы. Уменьшение количества вызовов (что делает пакетирование и создание экземпляров) увеличит общую производительность, которую может обеспечить ваш ЦП, поскольку требуется гораздо меньше времени ожидания. Вызовы SetPass - это изменения ваших текущих шейдеров, поэтому, если у вас много разных материалов, у вас будет несколько вызовов SetPass, которые также заставляют ЦП немного подождать.

  6. Если ваша сцена огромна и ваше процессорное время уходит на прохождение всех объектов сцены, попробуйте уменьшить количество объектов в сцене. Сгруппируйте несколько деревьев вместо того, чтобы размещать их по отдельности и собирайте их как один объект. Также убедитесь, что вы не перемещаете деревья или родительские объекты, поскольку это заставляет Unity отбрасывать кэшированные преобразования и пересчитывать все дерево сцены.

  7. Если ваша сцена огромна, и ваше процессорное время по-прежнему в основном сводится к тому, что Unity проходит по дереву сцен, чтобы создавать списки для рендеринга всех объектов, одну вещь, которую вы можете сделать, это не позволить Unity обрабатывать рендеринг. Если у вас есть лучший способ отслеживать нарисованные объекты, вы можете использовать CommandBuffer.DrawMeshInstanced или Graphics.DrawMeshInstanced, чтобы рисовать их вручную. Я не буду вдаваться в подробности об этом, поскольку он намного более продвинутый и включает в себя отбраковку объектов самостоятельно и еще много чего.

В случае, если статическое или динамическое пакетирование не работает должным образом (что вы можете увидеть, проверив отладчик фреймов), вам необходимо убедиться, что вы действительно используете общий материал и не делаете копии материала случайно с вызовом meshRenderer.material . Позвонив .material, сделаем копии ваших материалов и перестанем дозировать. Используйте .sharedMaterialвместо этого.

Начиная с Unity 5.6, вы можете использовать Отладчик фрейма, чтобы определить, почему определенные вызовы не совпали с предыдущими вызовами. Это будет очень полезно при попытке уменьшить количество вызовов вашей игры.

Instancing имеет следующие преимущества по сравнению со статическим / динамическим / настраиваемым пакетированием:

  • Использует меньше памяти, так как меш не должен дублироваться в памяти
  • Можно использовать несколько материалов, требуется только общий шейдер
  • Объекты могут быть анимированы

Также как недостаток, это довольно новая функция в Unity и может быть немного нестабильной. Также старые графические процессоры или мобильные устройства не обязательно поддерживают создание экземпляров.

Лассе
источник
1. Да, я пробовал LOD, и, к моему большому удивлению, это на самом деле ухудшило ситуацию. У меня было 3 варианта деревьев, каждое с немного меньшим количеством вершин, и одна плоская плоскость с визуализированным изображением дерева на нем.
г -
2. Все мои деревья помечены как статические. Насколько я знаю, что позволяет дозировать? Это верно? И когда вы говорите, что делитесь материалом, вы просто подразумеваете, что деревья имеют одинаковый материал?
г -
3. Какое улучшение производительности это могло бы сделать? Стоит ли пытаться?
г -
1
2/3: По моему опыту Unity не очень хорошо справляется с динамическим пакетированием, а статическое пакетирование увеличивает размер сборки, поэтому я сам реализовал пакетирование и сделал сетку, комбинирующую время загрузки. Используя эту технику, мне удалось сделать 2500 вызовов, чтобы сжать их примерно до 300, что было крайне важно для нашей мобильной игры, в которой важны вызовы. Это сделало немного ненужных вершин для вычисления (за кадром), но оно того стоило.
Лассе
2
Когда вы читаете вопрос о плохой работе с деревьями, и ни одно слово о рекламном щите не теряется
Num Lock
13

Итак, проблема была просто в том, что я не использовал предварительно вычисленный GI в реальном времени. Я проверил это некоторое время назад, но это не дало немедленного эффекта, поэтому я оставил его и забыл об этом, и время обработки освещения было слишком долгим. Тем не менее, он только что завершил его обработку, и мое слово, мой fps подскочил в 3 раза. Итак, сейчас я оставлю это на месте и в будущем буду всегда следить за тем, чтобы я всегда использовал прекомпьютерный GI в реальном времени!

Если я еще могу что-то сделать для дальнейшего улучшения производительности, пожалуйста, дайте мне знать, я был бы очень признателен!

MR-матовый
источник
2
Используйте Occlusion Culling, также, если ваша сцена большая - рассмотрите возможность ее разделения на куски, например, на множество местностей, и загрузите и разгрузите их.
Candid Moon _Max_
Учитывая, что вы, похоже, решили свою проблему, вы, вероятно, должны принять этот ответ.
Гнемлок