Про Godot, GLSL и WebGL, шейдеры используемые в мини игре

в 13:50, , рубрики: gles, glsl, Godot, OpenGL, WebGL, игростроение, разработка игр

Статья в основном про GLSL-шейдеры, и как я их использовал в этой мини-демке-игре.

Статья разбита по такой очередности:

  • Ссылки и краткое описание.
  • Очень краткое описание игровой логики, и используемых возможностей Godot.
  • Про используемые шейдеры.
  • Еще немного про Godot, и его особенности.
  • WebGL2 работает
  • Мультиплеер


1. Ссылки и описание

Скачать Win/Linux версии можно по ссылка на itch.io

Исходный код всей игры доступен на github-е или gitlab.

Игровой процесс:

Минимальный, это не полноценная игра. (звука в игре нет)

Цель игры — продержаться максимальное количество раундов. Раунды начинаются когда HP сферы ноль, и нет роботов в игре.

При уничтожении фигур появляются бонусы, раз за раунд, дают скорость анимации выстрела, урон (только по главной сфере), и высоту прыжка, по цвету синий, красно/зеленый, желтый. Боты также дают бонус но случайно. Персонаж игрока восстанавливает +1HP каждый новый раунд.


2. Логика игры, и используемые ресурсы

Используемые ресурсы:

Blender использовался лишь для уменьшения количества полигонов на моделях, и для создания разрушенных кусков моделей.

Используется модуль futari-addon. (про него ниже еще напишу)

В игре две модели имеют анимации.
Движения персонажа игрока я сделал в Godot, оригинальная модель
Вторая модель это sphere-bot которая имеет качественные анимации.

Все используемые готовые сторонние модели объектов перечислены по ссылке.

Логика игры и возможности Godot:

Игровая логика сделана далеко не лучшим образом, перечислю моменты которые сделаны нормально.

Используется всего один Viewport для 3D сцены, и несколько Viewport-ов (низкого разрешения) в которых стоят ортогональные камеры для 2D-Viewport-ов (тоже низкого разрешения) в которых идет обработка Multipass/Feedback шейдеров, о них ниже.

Все текстуры имеют mipmap, и работают даже в браузере. Есть дополнительные настройки графики (Esc — Settings). Например можно сделать любое разрешение для игры, до размера 32x32 пикселя, например я поставил 320x240 разрешение в настройках, запустив игру в браузере, и включил максимальное сглаживание MSAA вот что вышло Про Godot, GLSL и WebGL, шейдеры используемые в мини игре - 1

Все источники света работают в реальном времени, их 16 штук всего.

Пол и забор это простейшие частицы которые дублируют одну модель множество раз, код тривиален.

Анимация разрушаемых блоков считается физическим движком в реальном времени

Физика в Godot довольно ограничена, и начинает сильно уменьшать FPS уже при десятке активных объектов, поэтому отключены все столкновения между разрушенными кусками, и другие, установлены уровни для физики, также стоит ограничение на количество одновременных разрушений, и максимальное число Ботов одновременно (шесть).

Физика инерции и взаимодействия персонажа игрока с динамическими объектами. Она выключена по умолчанию в Godot, я написал минимальное взаимодействие, код в файлах:

bot_hit.gd функция _integrate_forces и все что ей вызывается, это движения противника-бота
player_l.gd во первых функцией move_and_slide отключается бесконечная инерция, и функция process_collision отталкивает объекты.

Предварительная загрузка (preload) в начале игры используется чтоб избежать лага при первом появлении объекта, это помогает однако при включении Теней (и некоторых других опций) лаги опять появятся на первое появление объекта. Также в браузере это не помогает из за особенности работы браузеров с шейдерами.

Несколько дублирующихся объектов в одном, и несколько GIProbe, формы и параметры источников света-все так и задумано, сделано для обхода ограничений OpenGL или ограничений в Godot.


3. Используемые шейдеры

Панорама окружения:

В этой игре используется статическая панорама, картинка получена из этого шейдера (с1 с2 цвета, ldir положение)

vec3 sky(vec3 d, vec3 c1, vec3 c2) {
    vec3 ldir = normalize(vec3(0.,0.,-1.));
    vec3 col = mix(c1*100., c2*100., min(abs(d.y)*2. + .5, 1.)) / 255.*.5;
    col *= (1. + vec3(1., .7, .3) / sqrt(length(d - ldir))*2.); //sun
    return clamp(col,vec3(0.),vec3(1.));
}

для получения панорамы убрать комментарий со строке 57 panorama_uv(fragCoord,ro,rd); и поставить комментарий на строку 58

Динамические панорамы для Godot в прошлых демках (ютуб и там ссылки на код) панорама облаков и панорама цикла дня/ночи с движением облаков

Если нужно конвертировать CubeMap в панораму окружения для Godot, я сделал простейший веб конвертер.

Совсем простые шейдеры:

Шейдеры для частиц статически определяющие их позицию для анимации или без. Например spawn.shader)

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

float intensity = pow(0.122 + max(dot(NORMAL, normalize(VIEW)),0.), 010.85);

Про Godot, GLSL и WebGL, шейдеры используемые в мини игре - 2 Про Godot, GLSL и WebGL, шейдеры используемые в мини игре - 3

Показ текста-цифр в 3D, как я понял в Godot нет средств для этого (без создания дополнительного FBO (viewport)) поэтому простой шейдер печатающий цифры из текстуры (чтобы был mipmapping), код шейдера

Элементы UI:

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

Про модуль futari-addon:

Он работает практически также как этот шейдер для 2D-частиц на видео (смотреть с 1:41).

На видео строится 2D-SDF карта всех полигонов один раз на старте и полученная текстура просто отправляется частицам, частицы сами строят normal в текущей позиции и меняют движение.

futari-addon делает практически тоже самое, только вместо 2D карты-текстуры передаются координаты 3D сфер и плоскостей которые обрабатываются по условию в шейдере частиц, поэтому свободно можно менять их положение и другие параметры.

Плюс ветер (в моем 2D-примере ветер добавить очень просто, как еще одну текстуру с +- значениями к скорости, и частицы просто добавляют значение скорости из этой карты по своему положению).

Модуль futari-addon очень хорош, использовал его вместо создания своей системы для частиц.

Эффект щита:

Частицы которым передаются координаты удара по сфере и положение игрока, и угасание используя буфер transform feedback. Код шейдера в файле en_m.shader

Щит у Ботов:

Про Godot, GLSL и WebGL, шейдеры используемые в мини игре - 4 Про Godot, GLSL и WebGL, шейдеры используемые в мини игре - 5
Шейдер по типу трехмерного шума sheild.shader по сути все работает благодаря функции flow оригинал тут
Задний фон определяется gl_FrontFacing, и закрашивается в более темный и зеленый, а не синий.
Реакция на удар-просто передается таймер события удара.


Шейдеры читающие свой прошлый кадр, или Feedback/Multipass шейдеры:

Почти все эффекты сделаны используя эту логику.
Один из шейдеров из игры.
В качестве источника я поставил ортогональную камеру которая снимает на маленькое расстояние объекты в определенной группе (не обрабатывая всю сцену)
Про Godot, GLSL и WebGL, шейдеры используемые в мини игре - 6.

Эффект поля льда:

Шейдер указан выше, в проекте файл ice_feedback.shader, и fragment шейдер для плоскости который создает иллюзию глубины пола используя простой depth цикл:

while(current_depth < depth){
    ofs -= delta;
    depth = textureLod(texture_depth, ofs,0.0).r;
    current_depth += layer_depth;
}

Эффект поля частиц:

Шейдер тот-же, координата y (высота) частиц по яркости цвета буфера кадра от шейдера, цвет также по яркости цвета (шейдер частиц я не сохранял отдельно, он в проекте в объекте floor/visible_/floor3/grass/grass).

Динамическая анимация флага:

В Godot есть SoftBody для анимации ткани, но это CPU, поэтому я не использовал. Я использовал уже готовый код ссылка на оригинал. Этот флаг отталкивается от трех шаров сбоку и голова персонажа четвертый шар.
Логика multipass-шейдера, как в примере выше, только с тремя осями, код multipass шейдера (1)flag.shader, шейдер рисующий флаг просто показывает текстуру с меняет геометрию плоскости (2)flag.shader.

Появление фигур:

У фигур нет UV, поэтому triplanar-texture-mapping для наложения текстуры, и разрезание по треугольникам (vertex), весь код в cchess.shader

Анимация hitbox-а (красная рамка) который наносит урон персонажу игрока, и след от рамки (частицы очевидно):

Используется всего лишь уже указанный шейдер gglow.shader.

Для частиц используется всего две текстуры, круг и квадрат.


4. Про Godot, и его особенности

Godot очень хорош и прост (не для новичка). Мне Godot очень понравился своими возможностями.

Багов очень много, документация Godot не полная и порой вводит в заблуждение из за ошибок и не указания критических моментов (не очевидных для меня), чтоб понять которые приходилось весь исходный код Godot многократно перечитывать (код не большой и хорошо написан).
Это лишь мое впечатление, может быть ошибочное, никого не хочу ввести в заблуждение.

Подчеркну что даже очень критические баги в Godot можно обходить в самом-же Godot через GDScript, с минимальными усилиями. Что несомненно большой плюс

Также отмечу что Godot никак не защищен от особенностей внешних факторов, это WASM в браузерах, ограничения ANGLE, сильные ограничения самих браузеров, и конечно-же десятки багов в драйверах видеокарт, это все приходится вручную обходить.

Лаги — есть большая проблема с управлением, это 100% на стороне Godot, я не исправлял это. (управление заклинивает во время компиляции шейдеров и лагов FPS (например в браузере)), также другие лаги связанные с особенностями 3D-рендера в Godot, я сделал обход части из них, но они всеравно есть/могут быть.


5. WebGL2 работает только в Linux

Не запускайте игру по ссылке, если у вас Windows. Ссылка на WebGL2/WASM версию.

Работает только в Chrome 76+ и Firefox (Linux).

Про Виндовс отправлен багрепорт (ссылка), если это баг браузера то гугл реагирует через 2 месяца. Но судя по всему это баг в ANGLE, а это wontfix почти наверняка.
Багрепорт уже закрыть, и ANGLE также править никто не будет. Значит на Windows в браузере не заработает.

По ходу этого проекта был исправлен один баг в Chrome благодаря чему заработал transform-feedback и моя прошлая демка (выше видео с панорамой дня/ночи), которая до этого не работала.


6. Мультиплеер

Это TODO. Обновлю эту часть как будет сделано.

Будет добавлен мультиплеер на двух игроков, для обычных версий (вне барузера) (в ближайшую неделю/две).

И как только выйдет Godot 3.2 с поддержкой WebRTC будет добавлена поддержка WebRTC, мультиплеер в браузере будет работать (пусть хоть только в Linux, хоть так).

Автор: atri1

Источник


* - обязательные к заполнению поля