Одна из новых функций Unity 2019.3 и Universal Render Pipeline 7.x.x - это возможность вставлять пользовательский рендеринг в разные части конвейера рендеринга. Это очень похоже на то, что можно сделать с помощью буферов команд в C #, но на гораздо более высоком уровне и с графическим интерфейсом, позволяющим легко добавлять, удалять или переупорядочивать различные функции средства визуализации. Некоторые примеры того, что можно делать с этой системой, включены в Репозиторий UniversalRenderingExamples на github. В этой статье будет рассмотрен один из включенных примеров, определены ограничения метода и внесены некоторые изменения, чтобы дать нам несколько субъективно улучшенный эффект.

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

Существуют и другие методы постобработки для создания контуров, такие как алгоритмы обнаружения краев (sorbel) или создание контура путем выборки соседних пикселей в экранном пространстве из полноэкранного буфера. Хотя у этих методов есть свои преимущества и недостатки, метод Outline Hull, вероятно, будет самым быстрым из всех, что делает его подходящим для мобильных игр.

Открывая пример сцены, ToonOutlinePost, мы уже видим, что он выглядит не совсем правильно.

Хотя персонаж более или менее обрисован в общих чертах, во внутренней части меша есть много артефактов. Мы бы предпочли, чтобы был виден только силуэт персонажа. Для этого нам нужно будет использовать Stencil Buffer, чтобы замаскировать сетку главного персонажа, чтобы контуры не рисовались там, где персонаж находится на рассвете. Давайте посмотрим на наш существующий ресурс OutlineHullEffect, который представляет собой тип RenderData, который наш UniversalRenderPipelineAsset использует для определения настраиваемой визуализации.

Как видите, здесь уже есть что-то под названием «Outline», которое отображает «непрозрачность после рендеринга». Он отображает все в маске слоя «Постобработка», частью которой являются наши персонажи. Давайте добавим новую функцию рендеринга типа «Render Objects», назовем ее «Characters» и расположим ее перед эффектом Outline.

Это отрендерит наших персонажей (и все, что находится в слое постобработки) со значением трафарета 1, чтобы мы могли замаскировать контур. Я также меняю маску слоя по умолчанию, чтобы не отображать слой постобработки. Если бы мы этого не сделали, наши персонажи были бы визуализированы дважды!

Отлично, теперь мы меняем наш эффект Outline, чтобы замаскировать пиксели, которые не покрыты нашими персонажами.

Теперь у нас должен быть силуэт.

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

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

Наконец, с помощью постобработки мы можем сделать наш контур светящимся. Уловка состоит в том, чтобы сделать цветовой вывод контура в HDR. Мы можем изменить пример шейдера «Toon / Basic Outline».

Затем в материале вы можете изменить цвет и увеличить интенсивность примерно до 2,0. Убедитесь, что в вашем активе конвейера рендеринга включен HDR, и добавьте Volume with Bloom. Я установил свой порог на 1,1, чтобы светились только контуры, установил интенсивность на 2,0 и снизил разброс до подходящего значения.

На этом пока все. Удачного очерчивания!