Эксперименты с графикой шейдеров: Делать больше с меньшими затратами

Вы можете повысить эффективность шейдера во время выполнения без ущерба для качества графики, упаковав информацию о материалах для физически-ориентированного рендеринга (PBR) в одну текстурную карту и поместив ее в компактный шейдер. Проверьте этот эксперимент.
Этот эксперимент работает как в Universal Render Pipeline (URP), так и в High Definition Render Pipeline (HDRP). Чтобы извлечь максимум пользы из этой статьи, вы должны быть немного знакомы с Shader Graph. Если вы впервые знакомитесь с Shader Graph, изучите наши ресурсы, чтобы получить представление и более подробную информацию об этом инструменте для визуального создания шейдеров.
При работе с художественными активами в среде, напоминающей рельеф, обычно предпочтительнее использовать несколько слоев плиточного материала, так как они дают лучшие результаты смешивания. Однако затраты производительности GPU на множественные выборки текстур и увеличение объема памяти с каждым добавленным в шейдер слоем могут оказаться непомерно высокими для некоторых устройств и неэффективными в целом.
В ходе этого эксперимента я стремился:
- Делайте больше, используя меньше
- Минимизируйте объем памяти и экономьте выборку текстур при изображении PBR-материала
- Минимизация инструкций шейдера
- Выполните смешивание слоев с минимальными цветовыми каналами splat map/vertex
- Расширение функциональности карты брызг/цвета вершин для дополнительных возможностей
Несмотря на то, что эксперимент достиг поставленных целей, он имеет некоторые оговорки. Вам придется расставить приоритеты в соответствии с требованиями своего проекта, чтобы определить, какие компромиссы для вас приемлемы.
Прежде чем приступить к наложению слоев, необходимо определиться с упаковкой материала PBR. Материал PBR обычно поставляется с параметрами для альбедо (BaseColor), маски сглаживания, Ambient Occlusion, Metalness и Normal.
Обычно все пять карт представлены в трех текстурных картах. Чтобы минимизировать использование текстур, я решил пожертвовать Metalness и Ambient Occlusion для этого эксперимента.
Остальные карты - Альбедо, Сглаженность и Нормальное определение - традиционно представлены как минимум двумя текстурными картами. Чтобы свести их к одной карте, требуется предварительная обработка каждого отдельного канала.

Конечный результат PBR-материала упакован в одну текстуру. Красный = dHdu (высота производной относительно направления U) для нормального определения#. Зеленый = dHdv (высота производной относительно направления V) для нормального определения#. Синий = линейный оттенок серого, представляющий альбедо (цвет реконструируется в шейдере). Alpha = Карта линейной гладкости (стандартная карта гладкости). Примечание: Текстура импортируется в Unity со снятым флажком sRGB и сжимается в формате BC7. При переносе на другие платформы переходите на поддерживаемый платформой эквивалентный 4-канальный формат текстур.
Обработка карт
Albedo
Альбедо обычно определяется как RGB-текстура, однако многие материалы, похожие на рельеф (камень, песок, грязь, трава и т. д.), имеют ограниченную цветовую палитру. Вы можете использовать это свойство, сохранив Albedo в виде градиента серого цвета и затем изменив его цвет в шейдере.
Не существует установленного метода преобразования альбедо RGB в градиент серого цвета. Для этого эксперимента полутоновое альбедо было создано путем выборочного маскирования каналов оригинальной карты альбедо и Ambient occlusion; для соответствия выделяющемуся цвету в шейдерном цветовом восстановлении, просто проследите за любыми ручными настройками.

Гладкость
Гладкость считается очень важной для определения материала в PBR. Чтобы определить гладкость более точно, у нее есть свой собственный канал.
Простой множитель был добавлен к гладкости в шейдере для некоторой вариативности материала.

Нормальное определение
Карта нормалей важна для отображения детальных характеристик поверхности. Типичный PBR-материал использует карту нормалей касательного пространства. В этом эксперименте я выбрал предварительно преобразованную производную карту с использованием системы градиентов поверхности по следующим причинам. (Более подробную информацию см. в статье МортенаМиккельсена "Поверхностный градиент" ).
Чтобы предварительно преобразовать карты нормалей касательного пространства в производные, воспользуйтесь этим действием Photoshop.
Использование предварительно сконвертированной карты Derivatives имеет ряд преимуществ:
- Может быть напрямую преобразована в градиент поверхности, используя меньше инструкций, чем стандартная карта нормалей в тангенциальном пространстве, которая требует преобразования производных в шейдере
- Может храниться в двух каналах (dHdu и dHdv), что приводит к уменьшению объема памяти и текстурного кэша во время выполнения.
- Не требует восстановления синего канала в шейдере, что типично для обработки карт нормалей касательного пространства, поскольку градиентный фреймворк поверхности берет на себя восстановление нормалей (меньше инструкций шейдера)
- Корректно работает при корректировке в Photoshop - то есть при наложении бленда, маскировании или уменьшении интенсивности - и не требует перенормировки. Например, чтобы уменьшить интенсивность, просто смешайте карту с RGB(128,128,0).
В сочетании с системой градиента поверхности преимущества также включают:
- Информация о нормальном бампе может быть смешана и скомпонована в шейдере так же, как и смешение/композиция альбедо, с корректным результатом.
- Увеличение, уменьшение и отмена взносов за неровности - тривиальные и точные действия.
Но у предварительно преобразованных производных от карты нормалей касательного пространства есть и недостатки:
- С помощью преобразования в Photoshop нормальное определение зажимается под углом более 45 градусов, чтобы сбалансировать точность 8-битной текстуры.
- Художники привыкли работать с картами нормалей тангенциального пространства и требуют их предварительной конвертации в Photoshop в рамках своего рабочего процесса.
Примечание: Зажим под углом более 45 градусов не применяется к преобразованию производных на основе шейдеров.
В зависимости от вашего случая использования, ограничение может иметь меньший или больший эффект. В данном эксперименте направление нормали менее 45 градусов не оказывает заметного негативного влияния на конечный результат. На самом деле, в этом случае он дает преимущество, уменьшая нежелательное отражение от крайних нормальных направлений.





Полный процесс распаковки



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

Sub Graph для перераспределения одного канала для представления шести слоев.
Подграфик, показанный выше, предопределен для шести уровней смешивания на основе уровней. Чтобы создать больше слоев, разделите 1 на желаемое количество смешиваемых слоев, вычтите 1, а затем перенастройте каждый слой в соответствии с этим диапазоном значений.
Например, для девятислойного смесового материала диапазон изменения параметров каждого слоя составляет 1/(9-1) = 0,125.
Имейте в виду, что при делении одного канала на более мелкие части уменьшается диапазон оттенков.



Для смешивания слоев требуется только один канал (красный канал вершины). Оставшиеся три вершинных канала предлагают дополнительные функции. Окончательный Shader Graph выдает результаты, используя оставшиеся вершинные каналы.
В этом эксперименте рисование вершин осуществлялось в редакторе Unity с помощью Polybrush (доступен в менеджере пакетов). Предлагаемая палитра цветов Vertex Paint для этого шейдера.
Красный: Используется для определения веса вклада слоя. Демонстрация рисования красного вершинного канала
Зеленый: Устанавливает свойство градиента поверхности, чтобы перевернуть, уменьшить или добавить вклад в нормали к неровностям (ремаппинг на -1 и 1).
- 0 изменяет нормальный удар (-1)
- Значение 0,5 обнуляет нормальную неровность (0)
- 1 устанавливает нормальную неровность на исходное значение (+1).
Демонстрация рисования зеленого вершинного канала
Синий: Регулирует гладкость и масштаб градиента поверхности для создания эффекта мокрой воды
- 0 = без изменений
- 255 = максимальная гладкость и плоская карта нормалей (влажный вид)
Демонстрация рисования синего вершинного канала
Альфа: Управляет весом слоя Albedo, устанавливая базовый цвет белым, а вклад основан на оси y нормали поверхности. Он не изменяет гладкость и использует преимущества исходной гладкости поверхностного слоя и свойства неровности.
- 0 = нет снега
- 255 = плотный снег
Альфа-канал вершинного рисования в сочетании с предыдущими каналами, чтобы показать, как все слои взаимодействуют со снегом
Комбинированные результаты различных каналов закрашивания вершин:
Вы можете настроить метод смешивания шейдеров и параметры различных функций вертексного канала/сплат-карт в соответствии с требованиями вашего проекта.
Целью этого эксперимента было расширение функциональности Shader Graph при минимизации ресурсов. Текстура была предварительно обработана и распакована, но есть ли польза от этого в эффективности выполнения?
Профилирование производительности показывает, насколько эффективны эти усилия.
Стандартный шестислойный шейдер наложения был создан для сравнения с компактным шестислойным шейдером наложения. Оба шейдера были созданы с использованием идентичного метода смешивания с одинаковыми функциональными возможностями. Основное отличие заключается в том, что стандартный шейдер использует три различные текстуры для представления одного слоя.
Для профилирования одна сетка рендерилась на экране с материалом смешивания с помощью Universal Render Pipeline в целевой платформе.
Мобильная память и профиль производительности
Сжатие текстур для мобильных устройств (Android):
Стандартный PBR с картами Albedo, Mask и Normal в разрешении 1024x1024 для мобильных устройств:
- 6x Карта альбедо ASTC 10x10 = 6x 222.4 KB
- 6x Карта масок ASTC 8x8 = 6x 341.4 KB
- 6x Нормальная карта ASTC 8x8 = 6x 341.4 KB
Общее использование памяти текстур 5,431 МБ
Компактный PBR с разрешением 1024x1024 для мобильных устройств:
- 6x PackedPBR Texture ASTC 8x8 = 6x 341.4 KB
Общее использование памяти текстур 2,048 МБ
Благодаря компактному шестислойному материалу потребление текстурной памяти на мобильных устройствах (Android) снижено примерно на 62%, экономия составляет более половины. Мобильный Android/Vulcan с Adreno 630 (Snapdragon 845); результаты профиля Snapdragon:
- Примерно на 70 % меньше текстурной памяти считывается во время выполнения.
- Стандартная отрисовка заняла 9971020 часов.
- На рендеринг компакта ушло 6951439 часов.
Компактный материал отображается на экране примерно на 30 % быстрее. Результат профилирования с помощью Snapdragon Profiler.
Профиль памяти и производительности компьютера
Стандартный PBR с картами Albedo, Mask и Normal при разрешении 1024x1024:
- 6x Карта альбедо DTX1 = 6x 0,7 МБ
- 6x Карта масок DXT5/BC7 = 6x 1,3 МБ
- 6x Карта нормалей DXT5/BC7 = 6x 1,3 МБ Общее использование памяти текстур 19,8 МБ
Компактный PBR в разрешении 1024x1024:
- 6x PackedPBR Texture BC7 = 6x 1.3 MB
Общее использование памяти текстур 7,8 МБ
Компактный шестислойный материал потребляет на 60% меньше текстурной памяти компьютера (экономия более чем в два раза).
Ноутбук с Radeon 460 Pro рендерит при 2880x1800; результаты профиля RenderDoc:
- Рисунок Opaques для стандартной 6-слойной смеси: 5,186 мс.
- Рисуйте опаки для компактной 6-слойной смеси: 3,632 мс. Компактный материал отображается на экране примерно на 30 %* быстрее. * Значение профиля RenderDoc колеблется; 30 % - это среднее значение по образцам.
Рабочий стол ПК с nVidia GTX 1080, рендеринг при 2560x1440; результаты профиля nSight:
- Рендер Opaques для стандартного 6-слойного материала: 0,87 мс
- Render Opaques для компактного 6-слойного материала: 0,48 мс
Компактный материал отображается на экране примерно на 45 % быстрее. Результаты профилирования с помощью системы nSight.
Профиль производительности консоли
На PlayStation 4 использование компактного материала дает 60 % экономии памяти, что идентично показателю для ПК, поскольку PS4 использует то же сжатие.
Базовый рендеринг PS4 при разрешении 1920x 1080; результаты профилей Razer:
- Рендер Opaques для стандартного 6-слойного материала: 2,11 мс
- Render Opaques для компактного 6-слойного материала: 1,59 мс
Компактный материал отображается на экране примерно на 24,5 % быстрее.
Результат профилирования с помощью профилировщика PS4 Razor.
В итоге, использование компактного шестислойного PBR-шейдера обеспечивает прирост производительности и значительную экономию памяти. Разница в производительности GPU интересна, но ожидаема, так как распаковка материала потребляет больше ALU, чем выборка большего количества текстур.
Этот пример проекта с шейдерными графиками и субграфиками можно загрузить здесь:
[DOWNLOAD HERE], Unity 2020.2.5f1 с HDRP 10.3.1
[DOWNLOAD HERE], Unity 2020.2.5f1 с URP 10.3.1
[DOWNLOAD HERE], действие Photoshop для предварительного преобразования карты нормалей касательного пространства в производные.
Скриншот из версии проекта Universal Render Pipeline.
Основными компонентами этого эксперимента являются:
- График шейдеров для пользовательского материала
- Предконвертированные производные инструменты
- Система поверхностных градиентов
- Восстановление цвета альбедо
- Одноканальное смешивание слоев
- Техника смешивания UpVector, управление сглаживанием и неровностями с помощью смешивания вершинных каналов
Этот эксперимент показывает, как можно использовать Shader Graph для создания красивой и одновременно эффективной графики. Надеемся, этот пример вдохновит художников и разработчиков на расширение эстетических границ в своих проектах Unity.
Ринальдо Тьян (технический арт-директор, R&D, Spotlight Team) - 3D-художник, увлеченный системами освещения и рендеринга в реальном времени.
Начав свою карьеру во времена PlayStation 2, он уже более десяти лет владеет знаниями о сквозном рабочем процессе художника - от текстурирования до создания финальной рендерной сцены. До прихода в Unity Technologies он помогал создавать такие AAA-игры, как BioShock 2, The Bureau: XCOM Declassified, и Mafia III.
В настоящее время он работает с клиентами Unity, помогая им расширить свои проекты и реализовать их потенциал с помощью Unity, а также помогает в разработке внутренних стандартов и функций рендеринга Unity.