Перейти к содержимому

Gpu skinning что такое

  • автор:

CPU Skinning vs. GPU Skinning

В процессе работы со скелетной анимацией возник вопрос о целесообразности скининга на GPU. Сейчас весь скиннинг у меня выполняется на CPU, шейдеры не используются, но недавно начал задумываться о том, чтобы доверить им скиннинг. Вопрос: какой из способов будет быстрее (на шейдЫрах или ЦПУ), если исп-ся попиксельное освещение и стенсильные тени. ИМХО, цпу будет пошустрее, ибо при GPU скиннинге вершины нужно преобразовывать каждый раз при рендере (в т.ч. при каждом из проходов при освещении), а на CPU можно расчитывать один раз за кадр. Правда, можно пользовать расширение EXT_pixel_buffer_object для рендернинга меша в пиксельный буффер, преобразования его шейдере и рендеринга меша из этого пиксельного буффера, но я слабо представляю себе это. Ещё одним плюсом скиннинга на CPU является испльзование одинаковых шейдеров для рендеринга статических и анимированных мешей.

Вобщем я сказал, теперь хочу увидеть ваши мнения.

#1
8:15, 4 апр 2006

Просто skinning — конечно, быстрее на шейдерах. Если есть стенсили — все становится чуть сложнее.
http://www.gamedev.ru/community/gamedev_lecture/articles/?id=19
Вот тут я пытался немного об этом рассказать. Есть вопросы — спрошай 🙂

#2
10:51, 4 апр 2006

Вот как идея, можно например теневой меш для скининга (тот который с дегенератными квадами) скинить на GPU и сразу экструзить его, так как рендерится он всего раз для источника. Остальные скинить на CPU.
Ещё лучше чтобы скининг подстраивался под GPU и CPU, т.е. часть на GPU часть на CPU в зависимости от загруженности того или иного :).

#3
11:02, 4 апр 2006

Помоему сейчас проше все на GPU делать.
Карточке не сложно, а процы чет почти и не развиваются

PlayerSettings.gpuSkinning

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

Ошибка внесения изменений

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

Оптимизация Скиннинга

Раздумывал я последнее время над ускорением скининга, так как увидел, что это самое узкое место моего движка. Во-первых, меня смутило то, что при написании GPU-skininga придется сделать вариант для каждого из эффектов (шейдеров) (тех у кого вертексные шейдеры разные, а они разные у всех моих эффектов). Идеально было бы отработать данные из одного вертекс буффера, лежащего в VRAM в другой вертекс буффер также лежащий в VRAM и затем отрисовать последний буффер эффектовыми Vertex & Pixel Shaders. Жаль так нельзя 🙂
Поэтому я занялся оптимизациями. Сначала я заменил подсчет (v*M1)*w1+(v*M2)*w2 на v*(M1*w1+M2*w2), немного выиграл. После этого стал писать SSE версию. Первая моя SSE версия работало немного медленней чем обычный вариант 🙂 Тяжелей всего просчитывались матрицы (M1*w1+M2*w2). Сейчас я закончил новую версию, которая разбивает вершины на группы принадлежащие одному множеству костей, эти группы доращиваются чтобы иметь кратное 4 число вершин, после этого скинятся группы по 4 вершины за раз.
Я получил 40% boost, но все равно хочется большего.
Еще одна идея в том, чтобы скинить не каждый кадр, а только по прошествие Accuracy time от прошлого скина.

Итого мне интересно, как кто реализовывал скиннинг. Если на GPU — то как скинятся меши с эффектами? Если на CPU — какие оптимизации.
Еще интересно, пробовал ли кто-нибудь Software Skinning из D3DX.

И наконец, есть два варианта: хранить вершинки в SYSRAM, каждый кадр отправляя их на GPU, или хранить на GPU, локая с DISCARD’ом и переписывая полностью буффер. SYSRAM у меня немного быстрее, почему — непонятно.

#1
23:06, 6 мар 2006

А почему именно на CPU скиннинг, а не на шейдере?

#2
23:23, 6 мар 2006

GPU скиннинг будет почти всегда быстрее, чем CPU. Возможно, если модельки очень костлявые, то выгоднее скиннить на CPU. Но слабо верится.

Единственная вещь, для которой нужен софтверный скиннинг — стенсельные тени. Тут уж если заморачиваться, то серьезно.

#3
0:57, 7 мар 2006

Чтобы скармливать вертексному шейдеру уже трансформированные вершинки, чтобы не писать Skin-Bump-Shader, Skin-Env-Shader. И так, если учесть сколько комбинаций источников света получается много шейдеров — грузить долго, в памяти хранить много и самое главное писать их надо 🙂

#4
5:45, 7 мар 2006

Siyanie
Такая опция (скиннинг/не скиннинг) — далеко не единственная, какая может быть в эффектах. Наличие тумана, блендинга, количество источников на объект и т.д. — все потребуют того же самого.
Так может лучше сделать поддержку условной компиляции шейдеров?

#5
12:49, 7 мар 2006

Боюсь, не очень получится уже трансформированные скармливать.

Потому что нужна не только трансформированная координата, но и normal, иногда tangent space. Очень сильно зависит от желаемых эффектов — bump ( object — ts ), parallax etc. Это решается условной компиляцией ( см. выше ). HLSL удачно приспособлен для #ifdef MEGA_PARALLAX_BUMP и разного рода for( i = 0; i < number_o_lights; ++i )<. >; C++ для таких штук приспособлен не очень. Диспатчить функцию по шаблонным параметрам — брр.

>грузить долго, в памяти хранить много

Если компилировать не на лету, а заранее, то нормально.

#6
13:10, 7 мар 2006

Семен
> Так может лучше сделать поддержку условной компиляции шейдеров?

Оно себя оправдывает ?
Где-нибудь такая штука уже реализована ?

#7
13:23, 7 мар 2006

Nikopol
В Cg почти на уровне языка реализовано. Через interfaces. HLSL потому и sucks.

#8
14:16, 7 мар 2006

Оно на уровне языка реализовано. #ifdef #endif

#9
14:42, 7 мар 2006

neteraser
Всего лишь слова, так как есть куда более разумная вещь как Linker.
Nikopol
У нас была реализация, как линкови так и условной компиляции. И то и другое ИМХО дурно пахнет, так как влечёт за собой массу граблей в виде затруднённой отладки и интеграции нововведений.

#10
14:42, 7 мар 2006

IronPeter
Это не на уровне языка! 😉

#11
15:06, 7 мар 2006

Семен
Да, именно. И над каждым свойством (туман, как считается альфа) раздумываешь сделать ли условной компиляцией или в каждый шейдер зашить, чтобы использовалось всегда. Потому как наличие новой фичи есть *2 в количестве откомпилированных шейдеров. Поэтому у меня туман есть всегда if ( FogEnable ), а альфа есть произведение Factor.a*cBase.a.
Вот, скажем эффект Бамп — 60 fxo файлов. 30 на параллаксовый, 30 на обыкновенный.
Если я еще сделаю скин-вариант. 120 файлов, если сделаю вариант для Shadow-maps — 240.
А мои немногочисленные эффекты и так уже занимают в памяти 12 мб и грузятся 1.7 сек.

IronPeter
Да, приходится иногда и Tangent/Binormal скиннить :/

morffiy
Мне страшно линковать шейдеры 🙂

#12
15:18, 7 мар 2006

Линковали с лёту без потерь, и откуда такие “дикие” цифры, может я чего “не догоняю” но как на счёт параметризации FX файлов?

#13
15:27, 7 мар 2006

morffiy
> Всего лишь слова, так как есть куда более разумная вещь как Linker.
Во-первых, я сомневаюсь что это разумная вещь. Во-вторых с помощью Inrefaces & парой десятков макросов можно за пару-тройку дней написать shader paths & shader bindings & preshaders так, чтобы включать shader code в .cpp. Все статично и быстро и полный trash.

В прошлый раз обломался на compiler bug в Cg 1.3. Он зарубил на корню. (генерировал для good-formed — empty shader). Проверил бы как сейчас, но надобность в такой системе вообще отпала. Это прошлый век, на PS3 не взлетит ;)))

#14
15:33, 7 мар 2006

morffiy
afaik, fragment linker — это мертвая ветка DX. Т.к. рантайм-линковка (скомпилированных фрагментов) мешает оптимизации (вцелом). Прекомпиляция всех пермутаций шейдера — лучший выход. Да и нет особых проблем с #ifdef/#endif (если заранее иметь в виду необходимость прекомпиляции).

Gpu skinning что такое

Оптимизация производительности графики

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

Какова стоимость графики

Графическая часть вашей игры нагружает в первую очередь две системы компьютера: 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

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

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-карте и количество жёстких рёбер (удваивающих вершины) как можно более низким

Следует отметить, что количество вершин, которое обрабатывает видеокарта, обычно не совпадает с количеством, показываемым 3D-приложением. Приложения для моделирования обычно показывают геометрическое количество вершин, то есть, количество угловых точек, составляющих модель. Для видеокарты некоторые геометрические вершины необходимо разбить на несколько логических вершин для корректной визуализации. Вершина может быть разбита на несколько, если она имеет несколько нормалей, UV-координат или вертексных цветов. Следовательно, количество вершин в Unity неизменно выше, чем количество вершин в 3D-приложении.

В то время как количество геометрии в моделях оказывает влияние в первую очередь на 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:

  • Use the Level Of Detail system
  • 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.

Список шагов для увеличения производительности вашей игры

  • Сохраняйте количество вершин между 200 000 и 3 000 000 в каждом кадре, если целевая платформа — PC
  • Если вы используете встроенные шейдеры, проверьте категории шейдеров Mobile и Unlit. Они прекрасно работают и на немобильных платформ, но являются упрощёнными версиями более сложных шейдеров.
  • Уменьшите количество различных материалов в сцене — используйте один материал для нескольких объектов, где это возможно.
  • Установите свойство Static для неподвижных объектов, чтобы использовать внутреннию оптимизацию static batching.
  • Only have a single (preferably directional) pixel light affecting your geometry, rather than multiples.
  • Bake lighting rather than using dynamic lighting.
  • Используйте сжатие текстур, когда это возможно, а также отдавайте предпочтение 16-битным текстурами перед 32-битными.
  • Avoid using fog where possible.
  • Узнайте преимущества технологии Occlusion Culling и используйте её для снижения количества видимой геометрии и количества draw calls в случаях со сложными статичными сценами с большим количеством перекрывающих друг друга объектов. Планируйте свои игровые уровни с учётом этой технологии.
  • Используйте скайбоксы для имитации далеко расположенной геометрии.
  • Используйте пиксельные шейдеры или инструменты для совмещения текстур, чтобы смешивать текстуры вместо многопроходной визуализации.
  • Use half precision variables where possible.
  • Сводите к минимуму количество сложных математических операций в пиксельных шейдерах: pow , sin , cos и т. п.
  • Используйте меньше текстур.
  • Unity Profiler Window. Производительность освещения

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *