Не так давно мы публиковали материал о тестирование Unity Cloth на мобильных устройствах .
В другой статья на сайте render.ru. рассказал о том, как арт-отделу Plarium Krasnodar удалось создать высокодетализированную модель персонажа, не перегружая проект. Теперь поговорим о работе над шейдером и анимацией волос этой модели.
ТК
Перед командой графической разработки стояли следующие задачи:- определить приемлемый уровень детализации геометрии;
- устранить угловатость модели и текстуры;
- создать реалистичную подсветку;
- придайте прическе немного движения.
Детализация геометрии
Никаких особых требований к детализации геометрии выявлено не было (как обычно — чем меньше вершин, тем лучше).Для измерения производительности мы взяли тестовый источник без очистки и использовали 3D-пакет с модификаторами Smooth для повышения детализации.
Детализация | Медиана PlayerLoop (мс) |
1396 вершин | 33.15 |
4423 вершины | 33.2 |
15537 вершин | 33.1 |
58003 вершины | 33.2 |
Устранение угловатости
С волосами персонажа была очевидная проблема: шейдер вместе с текстурой создавал жёсткие концы, а анизотропное блики подчеркивали выступающие один за другим полигоны волос.Отсюда стали понятны требования к текстуре и модели:
- многоугольники прядей не должны пересекаться там, где видно мелирование – так оно будет красиво двигаться по волосам, не подчеркивая угловатость;
- Верхние слои прядей волос должны быть более детализированными, чем нижние, чтобы создать общую форму и эффект движения.
Затем мы приступили к работе над текстурой.
Чтобы кончики волос выглядели лучше, потребовалась коррекция альфа-канала.
Здесь выбор стоял между двумя вариантами:
- первый — использовать жёсткую обрезку вырезающим шейдером (т.е.
фильтровать альфа-канал по пороговому значению, получая полностью прозрачный или непрозрачный пиксель, без промежуточных областей);
- второй — использовать мягкий прозрачный шейдер, который работает более плавно, но более требователен к оборудованию.
Вырезной шейдер/Прозрачный шейдер Мягкий шейдер выполнил только одну дополнительную операцию — чтение буфера кадра (для смешивания текущего пикселя волос с изображением, уже находящимся на экране), за счет чего достигался плавный переход к прозрачности.
Кроме того, занимаемая область экрана волосами нашего персонажа и количество наложений были небольшими — так что в нашем случае особой разницы в потреблении ресурсов между шейдерами не было.
Однако с мягким шейдером волосы выглядели лучше.
Но была одна загвоздка — камера превращала изображение в текстуру.
Поэтому, чтобы он корректно обрезался по альфе и волосы отображались на текстуре, требовался дополнительный проход, создающий эту альфу.
В результате был написан шейдер, содержащий три прохода.
Первый записывает в альфа-текстуре правильный силуэт прически, а также объем волос и правильную их стрижку на концах.
Второй рисует геометрию выреза, а третий (прозрачный) добавляет мягкие кончики.
Реалистичная вспышка
Чтобы волосы выглядели живыми, они должны блестеть.Чтобы добиться такого эффекта, мы рассмотрели два варианта: анизотропную динамическую блику, реагирующую на освещение, и статическую подделку, которая могла бы облегчить обработку шейдера.
Для создания статического блика мы использовали технологию текстурирования.
Маткап — имитация материала и окружающей среды с помощью всего одного изображения.
Источник изображения Matcap Shader Эта технология позволяет растягивать предварительно запеченное в текстуре освещение на 3D-модель для имитации освещения (тени, блики, оттенки и т. д.).
То есть мы могли поверх текстуры волос нанести окрашенный блик так, как нам было удобно.
Форму блика можно регулировать, но он никак не будет реагировать на изменения освещения.
Визуальная разница между анизотропными и искусственными бликами:
Анизотропная вспышка
Маткап-мигает Разница в коде шейдера при обработке анизотропных и ложных бликов:
анизотрофный | Маткап |
фиксированный4 фрагмент (v2f i): SV_Target { float3 зеркальный; float3 binormal = нормализовать (cross( i.normal, i.tangent.xyz )); float3 касательная = нормализовать (mul (unity_ObjectToWorld, i.tangent)); float HdotN = точка (полукаталог, i.normal); float VdotN = точка (i.viewDir, i.normal); float anX = точка (полуDir, бинормальный) / _AnisotropicX; float anY = точка (полунаправление, тангенс) / 4; float диффузныйSpecular = lerp(1.0, specTex.g, _SpecularPower); specular = диффузныйSpecular *_LightColor * _Specular * _SpecularColor * exp (-2.0 * (anX * anX + anY + anY) / (1.0 + HdotN )); } | v2f vert (данные приложения v) { .
float3 worldNorm = UnityObjectToWorldNormal(v.normal); worldNorm = mul((float3x3)UNITY_MATRIX_V, worldNorm); o.matcapUV = worldNorm.xy * 0,5 + 0,5; . } фиксированный4 фрагмент (v2f i): SV_Target { . исправлена specularMask = tex2D(_MatcapTex, i.uv). g; . } |
Но первый вариант порождал больше математических операций, поэтому мы выбрали второй.
Чтобы блики выглядели органично и не создавали эффекта плоскости, мы решили использовать маску.
Сначала мы попробовали вариант карты нормалей, но позже заменили его более светлой альфа-маской, которая имела аналогичный эффект.
Маска карты нормалей / маска альфа-блика Использование альфа-маски в коде:
fixed specDetail = tex2D(_MatcapTex, i.uv).
b;specDetail = pow(specDetail, _MatcapPow);matcapSpec = matcapSpec * specDetail;
Анимация и цветокоррекция
За основу мы взяли обычную костную анимацию для прядей.А для создания дополнительной динамики мы решили использовать движение в вершинном шейдере.
Для цветокоррекции мы использовали запеченное освещение в виде коэффициентов, которое называется SHA, или сферические гармоники .
Этот метод рендеринга может создавать очень реалистичное затенение с относительно небольшими накладными расходами.
Он основан на заранее рассчитанных коэффициентах и отлично подходит для рассеянного окружающего освещения (например, светового люка).
Тот же принцип был использован не только для волос, но и для самой модели персонажа.
Источники:
Детализация геометрии | 2500 |
Количество текстур | 3 |
Разрешение текстуры 1 | 512x512 |
Разрешение текстур 2 | 256x256 |
Разрешение текстур 3 | 128x128 |
Количество проходов | 3 |
Количество чтений текстур | 1-й проход: 3 чтения, 2-й проход: 3 чтения, 3 прохода: 1 чтение |
Количество математических операций в вершинном шейдере | 1-й проход: 54 математики, 2-й проход: 51 математика, 3 проход: 13 математика |
Количество математических операций во фрагментном шейдере | 1-й проход: 11 математики, 2-й проход: 17 математики, 3 проход: 0 математика |
Но именно благодаря сочетанию этих техник мы добились желаемого результата.
Теги: #Игры и игровые приставки #разработка #Работа с 3D графикой #анимация #текстуры #3d графика #3d графика #plariumkrasnodar #шейдер #графика #персонаж #vikingswarofclans #glare
-
Обычный Ibm-Pc Xt
19 Oct, 24 -
Гараж Ризен
19 Oct, 24