Сделал анимации деревьям через шейдер в Unity

Итоговый результат

Подготовка модели

Модели пальм взял отсюда, но перекрасил под свой атлас под стиль игры (спасибо YadroGames):

Сделал через VertexColor маски в Blender, чтобы по красному каналу двигать все дерево, а по зеленому двигать дополнительно вертексы листьев:

Красный канал вертикальный линейный градиент (внизу черный цвет) и зеленый канал чисто на листя радиальный, в центре (по центру кроны черный цвет)
Красный канал вертикальный линейный градиент (внизу черный цвет) и зеленый канал чисто на листя радиальный, в центре (по центру кроны черный цвет)

Использовал Blender Vertex Color Master аддон v0.8.4 под Blender 3.1.1 (в новых версиях не работает нормально покраска VertexColor по каналам).

Выбираем отображение VertexColor у моделей (сверху справа):

Сделал анимации деревьям через шейдер в Unity

Заходим в Vertex Paint через Ctrl+Tab:

Сделал анимации деревьям через шейдер в Unity

Нажимаем V клавишу и выбираем Isolate channel (нужны будут R и G соотв по порядку):

Сделал анимации деревьям через шейдер в Unity

Далее в красном канале снова V нажимаем и выбираем Linear Gradient, рисуем его, получится что-то такое, если градиент получился наоборот (внизу белый), то там есть Invert в Basic operations:

Получается такая маска движения по красному каналу (шейдер будет наклонять дерево, где белый цвет там максимальный эффект будет)
Получается такая маска движения по красному каналу (шейдер будет наклонять дерево, где белый цвет там максимальный эффект будет)

Ну и в конце снова V и в Isolated 'Col R' выбираем Apply Changes - так мы применим изменения по красному каналу.

По листьям: в Edit Mode выбираем их (курсор + L кнопку) все полигоны

Триангуляцию для листьев я тут сделал, потому что Unity делал её по-другому и появлялись артефакты (не обращайте внимание на это)
Триангуляцию для листьев я тут сделал, потому что Unity делал её по-другому и появлялись артефакты (не обращайте внимание на это)

В VertexPaint режим заходим, выбираем режим маски (сверху слева):

Сделал анимации деревьям через шейдер в Unity

Нажимаем V клавишу и выбираем Isolate channel G (зеленый канал), ещё раз V и Circular Gradient, рисуем от центра кроны по радиусу кроны с вида сверху:

Что получится. Инвертируем, если в центре не черный цвет. 
Что получится. Инвертируем, если в центре не черный цвет. 

Применяем изменения по каналу.

Затем можно экспортировать в Unity. Рекомендую ознакомиться с Super Batch Export аддоном для блендера (очень удобно экспортировать объекты в 1 клик).

Шейдер через ShaderGraph

В конце есть ссылка на шейдерграф базу, текстуру шума и Custom Function в виде файла hlsl, но тут вкратце расскажу как делал:

Необходим порт Vertex Position в ShaderGraph, чтобы изменить позицию вершин модели.

Сделал анимации деревьям через шейдер в Unity

Создаем в проводнике в проекте PalmWindAnimation.hlsl файл, в него добавляем следующий код:

void PalmWindAnimation_float( float3 ObjectPosition, float4 VertexColor, UnityTexture2D NoiseTex, float NoiseTile, float WindSpeedTrunk, float WindStrengthTrunk, float WindSpeedLeaves, float WindStrengthLeaves, out float3 Position ) { float Time = _Time.y; // Trunk movement float maskTrunk = VertexColor.r; float maskLeaves = VertexColor.g; float trunkTime = Time * WindSpeedTrunk; float trunkSwayX = sin(trunkTime) * cos(trunkTime * 0.7); float3 offsetTrunk = float3(trunkSwayX, 0, 0) * maskTrunk * WindStrengthTrunk; // Leaves movement float2 noiseUV = ObjectPosition.xz * NoiseTile + Time * WindSpeedLeaves; float noiseR = SAMPLE_TEXTURE2D_LOD(NoiseTex, NoiseTex.samplerstate, noiseUV, 0).r; float noiseG = SAMPLE_TEXTURE2D_LOD(NoiseTex, NoiseTex.samplerstate, noiseUV + float2(0.317, 0), 0).g; float flutterX = (noiseR * 2.0 - 1.0); float flutterZ = (noiseG * 2.0 - 1.0); float flutterY = abs(flutterX) * 2; float3 offsetLeaves = float3(flutterX, flutterY, flutterZ) * maskLeaves * WindStrengthLeaves; // Combine end result Position = ObjectPosition + offsetTrunk + offsetLeaves; }

В шейдер графе добавляем Custom Function и указываем тип файл и ссылку на тот, что выше сделали. В Name пишем PalmWindAnimation (название функции), добавляем все параметры как на картинке:

Сделал анимации деревьям через шейдер в Unity

И выход Position подключаем в блок Vertex - Position.

Создал материал и оставил такие значения (текстуру можно шума прикрепил в конце):

Сделал анимации деревьям через шейдер в Unity

Текстура шума, лит шейдер с настроенными нодами в ShaderGraph можно взять отсюда:

Конечно, можно улучшить функцию hlsl, чтобы учитывалось направление ветра и его сила (добавить глобальную переменную ветра в Shader классе через C# и потом считывать её в шейдере, но для моей игры это не нужно).

Делаю это все для моей игры Wheel Balance в Steam. Демо версия уже доступна, также заходите на мой ТГ, если хотите следить за разработкой.

Надеюсь этот материал будет кому-то полезен!

8
1 комментарий