Про Godot, GLSL и 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 вот что вышло


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


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


    Матрица поворота частиц(кусков пола), в моих шейдерах, это просто короткая запись из этой формулы,:


    mat4 rotationAxisAngle( vec3 v, float angle )
    {
        float s = sin( angle );
        float c = cos( angle );
        float ic = 1.0 - c;
    
        return mat4( v.x*v.x*ic + c,     v.y*v.x*ic - s*v.z, v.z*v.x*ic + s*v.y, 0.0,
                     v.x*v.y*ic + s*v.z, v.y*v.y*ic + c,     v.z*v.y*ic - s*v.x, 0.0,
                     v.x*v.z*ic - s*v.y, v.y*v.z*ic + s*v.x, v.z*v.z*ic + c,     0.0,
                     0.0,                0.0,                0.0,                1.0 );
    }

    к примеру v=vec3(0.0,0.0,1.0) это поворот по оси z, и angle=PI/2. подставить их и получиться нужный поворот.


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



    Физика в 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 в прошлых демках (ютуб и там ссылки на код) панорама облаков.
    И панорама цикла дня/ночи с движением облаков была использована в этой демке:



    еще одна панорама дня/ночи для примера, на shadertoy я ее не использовал нигде


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


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


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



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


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


    Показ текста-цифр в 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



    Щит у Ботов:



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





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


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


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


    Шейдер указан выше, в проекте файл 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.
    P.S. Сделал эту-же анимацию в одном шейдере, ссылка на shadertoy


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




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


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


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


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


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


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




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


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


    Обновление информации: WebGL версию удалось запустить в Windows10(только в Firefox, с выключенным ANGLE) на супер-мощном ПК(i9/16gb ram/8gb video), правда пол не отрендеился(по какойто причине), и файрфокс течет памятью(>16гб) за пять минут… лучше не запускать, на свой страх и риск только


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


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


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




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


    Добавлен мультиплеер, исключительно в тестовых целях (и пробы мультиплеера в Godot). Исходный код и бинарные версии рядом с основной версией на гитхабе и itch (ссылки в начале).



    Как выйдет Godot 3.2 добавлю WebRTC для теста тоже.

    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 12

      0
      А зачем подобные вычисления? После обычных ЯП непривычно смотрится.
      ALBEDO = 1.*colorx.rgb;
      ALPHA=0.0+intensity;

      Приведение типов?
        –2
        эти куски кода использованы в других шейдерах, где вместо 1 было 10, или умножить на 0 когда надо было цвет убрать для отладки, или другое число, тоже с ALPHA
        или я просто ставил значения чтоб посмотреть подходит ли оно по цвету к сцене, и копировал по другим шейдерам удаляя там где не надо…
        … просто остался мусор который я не удалял, ничего особенного
        –1
        на Убунту 18,04 бобер на запускается, ибо там libc6 2.27 версии только. Походу надо полсистемы сламать что-бы запустить…
          –2
          Качай виндовс версию и запускай через вайн.
          Или веб версию пробуй, раз Линукс.
          Я пересобирал Godot для всех платформ, и Линукс собрал на совей системе с libc6 2.27, уж извини, возможности запускать виртуалку и собирать там у меня нет.(памяти нет просто)
            0
            А за что минусуете то? Человек забахал классный проект на классном движке, вы хотите его посмотреть на самом стандартном линуксе из всех и:
            madness@ThinkPad-X140e:~/itch.io/e-ani/e-ani-linux$ ./e_ani.x86_64 
            ./e_ani.x86_64: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by ./e_ani.x86_64)
            И понимаете что вам надо 19.04 установить, и всегда иметь только самые распоследние версии софта, а то не дай бог забудешь обновится все, уже ничего не работает.

            Хотя наверно я погарячился, вот же проект на гитхабе есть. Но если автор так выкладывать все будет, то пользователи его поделий будут недовольный советом «Запусти в Wine» ибо они ожидают нативную версию.
              0
              я не понял тебя

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

              Все что у меня есть для сборки это Win7, Linux(OpenSuse Tumbleweed), 5Гб свободного места на жестком диске, и 4Гб RAM.

              Windows версия в wine работает в любом линуксе, и не имеет оверхеда потому что OpenGL.
          0
          Огромное человеческое спасибо за шейдер скайсферы!

          Насчет Godot, да, сначала казалось, что инструмент сырой странный, неудобный, но попробовав и поняв какие возможности есть у тех же GPU частиц был в шоке\восторге пару дней.)
            0
            могу еще такой шейдер дать для примера www.shadertoy.com/view/ttS3zW (тут тоже панорама дня ночи)
            на строке 203/204 комментируй `panorama_uv` и раскоментируй `def_uv` или наоборот, `def_uv` покажет трехмерную картину, панорама покажет на текстуре панорамы

            я делал этот шейдер месяца 3-4 назад, но не использовал нигде
            плюс в том что он практически бесплатный по затратам ресурсов GPU, очень мало ресурсов использует
              0
              Меня больше облака интересовали) Плюс после анриала пока сложно с одного типа шейдеров на другой прыгать) Так что буду пока его ковырять, тем более он и попроще вроде.
                0

                Шейдер крут, но какого хрена луна и солнце движутся навстречу друг другу?

                  0
                  ну сделай как хочешь, код простой, я ж говорю сделал и не понравилось как выглядит(негде использовать), вот и оставил как есть
              +1
              Читал переведённые учебники по Godot, там интересно всё написано. Но самые азы, только чтоб вкурить, как там что устроено. И эта статья неплохо так дополняет их по части практического применения и всяких трюков. Спасибо!

              Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

              Самое читаемое