Вступление

Примерно год назад мы все чаще замечали, что наша команда художников недовольна тем, как наши игры выглядят на устройствах. Они хотели, и мы хотели, чтобы визуальные эффекты нашей игры выходили за рамки всего, на что мы были способны раньше. Итак, за последний год или около того мы разработали Uber Shader, используя набор инструментов Варианты шейдеров Unity.

Uber Shader был задуман как универсальный инструмент для каждой поверхности, которая есть в наших играх. Это шейдер, вдохновленный PBR, поскольку он не следует набору правил PBR, а использует его в качестве руководства. Для тех, кто еще не сталкивался с PBR, я могу порекомендовать пост Трента Ридса Physically Based Shading и Image Based Lighting. По мере того, как он был принят во всей студии, арт-команда запрашивала все больше и больше функций, и шейдер превратился в то, что мы знаем как сегодня. Он поддерживает целый ряд функций, включая, помимо прочего:

  • Подробные карты
  • Смешивание текстур
  • Размышления
  • Псевдо подповерхностное рассеяние
  • Френель
  • Карты нормалей
  • Металлические поверхности
  • Рабочие процессы в линейном и гамма-пространстве

Проблемы

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

У нас есть собственный инспектор шейдеров. Инспектор включает и отключает функции шейдера, когда установлены определенные текстуры или когда включены переключатели. Мы заметили, что инспектор становится слишком сложным, и наша первоначальная мысль заключалась в том, чтобы разбить его на модули, разделив функции, чтобы художникам было легче находить вещи. Но быстро стало очевидно, что все стало слишком сложно.

Мы дали команде художников такую ​​гибкость, что им стало практически невозможно балансировать материалы в игре. Они тратили слишком много времени на создание и настройку материалов. Более того, наши материалы выглядят совершенно по-разному в нашей инструментальной цепочке (Maya, Substance Painter и Unity), а это означает, что художникам приходилось настраивать поверхности три раза с совершенно разными настройками.

Художник по субстанции

Наша команда художников пользуется и любит Substance Painter. Для тех, кто не знает, он позволяет создавать и смешивать материалы в очень визуальной и художественной манере. Его используют сотни студий по всему миру. Им также нравится, как их материалы выглядят внутри Painter. Немного изучив, мы сразу заметили, что у Substance есть конвейер PBR. В идеале материалы, которые команда художников создает в Substance, должны выглядеть в Unity на мобильных устройствах одинаковыми или максимально близкими к идентичности.

Исследовать

Когда речь идет о физическом рендеринге и затенении, есть много информации. Он получил широкое распространение за последние 5 лет. Я принялся читать статьи, смотреть доклады и листать слайды. Сбор как можно большего количества информации. Первое, что выяснилось, это то, что почти всю информацию о PBR и исследованиях мы разработали для настольного и консольного оборудования. Однако мы хотим добиться того же визуального эффекта на мобильных устройствах. Нам пришлось прервать нашу работу! В качестве примечания я добавил много ссылок на исследования, которые я нашел внизу этого сообщения.

Решения

Принципы Disney PBR

PBR впервые привлек внимание общественности, когда Disney опубликовал свою статью под названием Physically-Based Shading в Disney. Они рассказывают о том, как они перешли на PBR при создании Wreck-It Ralph в 2012 году. Помимо определения своих моделей освещения, они также определили ряд правил, которые вы должны использовать для создания и установки конвейера PBR:

  1. Следует использовать интуитивно понятные, а не физические параметры.
  2. Параметров должно быть как можно меньше.
  3. Параметры должны быть от нуля до единицы в допустимом диапазоне.
  4. Следует позволить параметрам выходить за рамки того, где это имеет смысл.
  5. Все комбинации параметров должны быть правдоподобными.

Рабочий процесс

При разработке конвейеров PBR используются два основных рабочих процесса:

  1. Зеркальный
    Состоит из 7 каналов:
    Альбедо (RGB),
    Зеркальное отражение (RGB),
    Гладкость [0, 1]

  1. Металлик
    Состоит из 5 каналов:
    Базовый цвет (RGB)
    Шероховатость [0, 1]
    Металлик [0, 1]

Для диэлектрических материалов цвет зеркального выделения является значением шкалы серого. Таким образом, используя зеркальную модель, вы теряете два канала в зеркальной текстуре. Для металлических поверхностей диффузный цвет почти черный, поэтому снова в зеркальной модели вы тратите 3 канала в текстуре альбедо. Принимая во внимание это, тот факт, что были на мобильных устройствах, и тот факт, что второй принцип Disney гласит, что «должно быть как можно меньше параметров», мы решили использовать исключительно металлический рабочий процесс. Bungee (Destiny 2), Unreal Engine, Frostbite Engine и Unity - все поддерживают металлический рабочий процесс (Unity также поддерживает зеркальный рабочий процесс).

ALU против LUT

Наш набор инструментов Uber Shader запекает результаты зеркального и рассеянного освещения в текстуру поиска. Затем мы сэмплируем эту текстуру, используя N.L для диффузного и [N.H, гладкость] для зеркального блика. Это действительно дешево и позволяет использовать много дорогих моделей освещения. Однако мы заметили, что блики иногда были недостаточно резкими, мы теряли некоторые данные из-за текстуры и сжатия данных. Мы также знаем, что в будущем поддержка нескольких источников света невозможна. Если у нас есть четыре источника света, воздействующих на одну поверхность, это приведет к получению восьми текстурных выборок только на основе освещения.

Модель освещения

Самая известная модель зеркального освещения - это, возможно, модель Блинна. Он существует уже несколько десятилетий. Переходя на PBR, люди приняли нормализованную модель освещения Blinn Phong. Но мы хотели добиться большего. Большинство консольных и настольных игр сегодня используют зеркальную модель GGX, она выглядит намного более реалистичной по сравнению с зеркальной подсветкой в ​​реальном мире. К сожалению, этот реализм требует больших затрат! Я провел много исследований и наткнулся на статью, опубликованную Unity на SIGGRAPH 2015 под названием Оптимизация PBR. Это отличное чтение, в нем изложена принятая нами формула. Это очень близкое приближение, которое действительно работает на мобильных устройствах.

Реализация

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

Мы сохраняем параметры гладкости, металлика и окружающей окклюзии в линейной текстуре. Мы также храним эмиссионную цветовую маску и маску наложения текстур во второй текстуре, хотя мы можем попытаться сжать все это в одну текстуру за счет некоторых накладных расходов на распаковку ALU. Мы предварительно выбираем как можно больше данных текстуры внутри вызовов функций sampleMaterialTexture () и initSurface (). Мы также предварительно рассчитываем много многоразовой информации о поверхности и сохраняем ее в структуре SurfaceData, например:

  • Шероховатость
  • Нормали
  • Диффузные и зеркальные термины
  • Образцы отражающего зонда

Наш BRDF разбит на довольно много вспомогательных функций, есть чем поделиться, но вот основная его часть:

Вот так мы комбинируем наше экологическое освещение. Мы предварительно выбираем данные кубической карты в начале нашего шейдера (в вызове функции initSurface ()), чтобы предотвратить срывы - вы можете прочитать об этом чуть ниже.

Профилирование

Определенно стоит профилировать ваши шейдеры, лучший инструмент для этого - отладчик графического процессора XCode - он показывает вам построчно стоимость вашего шейдера. У нас был застой в шейдере PBR, который занимал 40% всего времени шейдера! Эта задержка возникла из-за выборки кубической карты среды и немедленного декодирования значения. Выборка кубической карты в начале нашего шейдера, а затем ее декодирование намного позже в шейдере позволили нам сократить время задержки до 3% от общего времени шейдера.

Заключение

Нам удалось разработать прототип, который очень похож на всю нашу цепочку инструментов и без проблем работает на наших целевых платформах (Android и iOS).

Производительность: ALU или выборка текстур

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

Мы ясно видим, что подход, основанный на ALU, использует больше инструкций ALU и меньше выборок текстур. Это больше подходит для нашей целевой платформы. Пропускная способность на мобильном телефоне очень дорогая! С годами мобильные графические процессоры становятся все более и более мощными, они могут обрабатывать множество сложных математических расчетов, однако добавление дополнительных считываний текстур в шейдер может привести к значительному зависанию графического процессора.

Производительность: ALU против sRGB Гамма для линейного преобразования

Мобильные устройства, поддерживающие Open GL ES 3.0 и выше, обеспечивают поддержку чтения текстур sRGB. Сэмплер текстуры GPU может преобразовывать данные текстуры из гаммы в линейное пространство. Для более ранних устройств нам нужно вручную преобразовывать гамму в линейное пространство:

Прежде чем совершать какие-либо действия, нам необходимо выяснить стоимость каждого из них. Используя отладчик графического процессора XCode, я обнаружил, что при рендеринге целой группы сфер преобразование ALU заняло 3,05 мс, тогда как метод sRGB занял 2,79 мс. Если вы можете отказаться от поддержки OpenGL ES 2.0 или, возможно, просто работать в гамма-пространстве на этих устройствах 😢, тогда используйте метод sRGB.

Следующие шаги

До сих пор вся эта работа была основана на наших собственных испытаниях и исследованиях. Мы все еще находимся на стадии прототипа и дорабатываем окончательный набор функций, который мы перенесем в финальный производственный конвейер. Мы сделали код шейдера максимально модульным и гибким. Наша цель - переход на конвейеры рендеринга с поддержкой сценариев и, в конечном итоге, на отложенное затенение.

использованная литература