Использование различных простых шейдеров в Godot 3.2

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Еще один мой проект в Godot 3 с использованием разных шейдеров, все шейдеры довольно простые.


Ссылка для запуска на itch.io, требуется WebGL2.
Исходный код проекта на github, проект graphic_demo_3d.


Статья разбита на такие разделы:


  1. Статические текстуры, генерация и плавная смена для эффекта освещения.
  2. Сглаживание и мультисэмплинг.
  3. Про используемые шейдеры и их логику.
  4. Немного про логику скриптов.

О чем это:


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


Скачать готовые сборки для Linux и Windows ссылка на itch.io.
Исходный код проекта ссылка на github.


Для разработки использовался официальный Godot 3.2.1, без модификаций.


Статические текстуры



Ray-tracer и убирание шума:
Для генерации всех текстур освещения, как не сложно догадаться, использовался raytracer. В основном это Blender-cycles.
В качестве деноизера я использовал этот код шейдера glslSmartDeNoise.


Разные цвета освещения:
В каталоге проекта graphic_demo_3d/game/models/objects/arc/ есть папки orig+цвет где все текстуры освещения для этой геометрии(меша).
И эти текстуры синхронно меняются через логику скрипта arc.gd


Панорамы:
Для создания текстур панорам, которые используются как текстура отражения на сферах, делал cubemap снимок и трансформировал в панораму, в Godot такое сделать быстрее чем в Blender.


Как пример многократные отражения друг друга у фиолетовых сфер — это просто несколько раз сделать снимок и применить прошлый снимок к окружающим шарам, в итоге многократные отражения.



Сглаживание и мультисэмплинг



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


На фиолетовых сферах используется мультисэмплинг текстуры, код шейдера:


    const int AA=4;
    for (int mx = 0; mx < AA; mx++)
        for (int nx = 0 ; nx < AA; nx++) {
            vec2 o = vec2(float(mx), float(nx)) / float(AA) - 0.5;
            o=tuv+o*baa;
            tot+=texture(p_o,o).rgb;
        }
    tot /= float(AA * AA);

Где baa это удаление фрагмента от камеры.


Это работает достаточно хорошо для этого конкретного случая.


В этом случае mipmaps нельзя использовать, так как эта панорама и сфера(размер пикселей не равномерный), кубемап на сферу тоже не выйдет натянуть без потери mipmaps…


Еще один случай, где нужно сглаживание — когда с удалением яркие объекты стали слишком маленькими, и пикселей не хватает чтоб их нарисовать:



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


Я просто взял точки(GL_POINT) и поставил их внутрь этих мелких объектов, и с удалением точка сохраняет свой размер и заменяет пропадающий объект. Вариант с точками на левой части видео.


Про используемые шейдеры и их логику


Шейдер outline для одного объекта



Корректный способ такое сделать описан по ссылке в разделе Silhouette Effect.
В Godot 3 нельзя, без модификации кода движка, записывать ни ID материала ни какие-либо дополнительные данные в процессе создания кадра.


Поэтому единственный способ это использовать дополнительную framebuffer(Viewport) где еще раз рендерить все нужные объекты, и пока объектов мало можно не волноваться о производительности, но это плохой способ в любом случае, ждем Godot 4.


В моем случае я поставил еще одну камеру на сцену, и эта камера видит только один объект — волка, поэтому всегда контур будет, камера в Viewport разрешение которого в 2 раза меньше текущего экрана.


Шейдер для освещения и теней



В Godot довольно мало возможностей влиять на освещение и тени, и некоторые из заявленных возможностей в Godot 3 просто не реализованы и перенесены в Godot 4.


Код этого шейдера в файле box/floor.shader


void light() {
    vec3 col=texture(floor_img,UV).rgb;
    if(col.r>0.001){
        float dif = clamp(dot(NORMAL,LIGHT), 0.0, 1.0);
        vec3 hal = normalize(VIEW+LIGHT);
        float spe = pow(clamp(dot(hal, NORMAL), 0.0, 1.0), 32.0);
        vec3 ta=ATTENUATION;
        vec2 tuv=UV*vec2(15.,10.)*50.;
        vec2 ddx = dFdx(tuv); 
        vec2 ddy = dFdy(tuv);
        float tx=filteredSquares(tuv, ddx, ddy);
        float tx2=filteredCrosses(tuv, ddx, ddy);
        DIFFUSE_LIGHT = dif*co*spe*4.* ta*col;
        DIFFUSE_LIGHT = clamp(DIFFUSE_LIGHT,0.,1.);
        SPECULAR_LIGHT = mix(ta,vec3(0.)+DIFFUSE_LIGHT,clamp(dif*spe*5.,0.,1.))*tx+0.5*((1.-tx2)*(clamp(1.-ta*5.,0.,1.)));
        SPECULAR_LIGHT = clamp(SPECULAR_LIGHT*col,0.,1.);
    }
    else{
        DIFFUSE_LIGHT=vec3(0.);
        SPECULAR_LIGHT=vec3(0.);
    }
}

Логика такая что, берется значение текстуры floor_img чтобы ограничить тень и свет в пределах белого прямоугольника текстуры, функции filteredSquares и filteredCrosses от iquilezles.org.
Эти функции выводят свой узор(патерн), и этот узор накладывается в зависимости от ATTENUATION, и дальше разделение цвета SPECULAR_LIGHT от DIFFUSE_LIGHT чтоб один сделать белым другой желтого цвета.


Depth — контур у фиолетового щита



Вся логика работы с глубиной(depth) отсюда godot_force_shield_shader
Шейдер шума на основе этого ссылка на shadertoy
Сам код шейдера в файле shield.shader.


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


Area lights




Используя материал Real-Time Polygonal-Light Shading with Linearly Transformed Cosines этот код на shadertoy ссылка, для прямоугольных источников.
И код этого шейдера для сферы и трубы ссылка на shadertoy.


Код этих шейдеров в этих файлах area_lights/floor.shader и area_lights2/floor_area.shader


Никакой сложности их переноса в Godot нет, все так же как во многих других движках, где этот эффект уже встроенный.


Немного про логику скриптов


Навигация модели волка — использует встроенную в Godot возможность Navigation, логика скопирована из туториала Godot 3D Navigation Mesh. Волк бежит к камере по клику правой кнопкой мыши.


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


Анимация квадратов на полу — используется отдельный framebuffer(Viewport) разрешения 20x20 пикселей.
В нем храниться состояние анимации всех квадратов, и передается положение камеры и волка, двух персонажей.


Бесконечное поле:



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


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


Производительность — я запускал на Nvidia 750 и Vega 8 картах, работает на 60fps в 1080p разрешении, думаю производительность в пределах нормы. Проверил на Windows и Linux — работает. В WebGL2 также работает очень хорошо.


Конец статьи


Кто прочитал — спасибо Вам что уделили столько времени этому тексту.

Источник: https://habr.com/ru/post/506120/


Интересные статьи

Интересные статьи

Для соединения пары домашних серверов мне захотелось выйти за пределы привычных 1Гбит/с и при этом сильно не переплачивать за сетевое оборудование. На известном сайте был...
При создании программного обеспечения все мы, как команда, соглашаемся следовать набору рекомендаций, которые обычно считаются лучшими практиками. Но во время разработки разработчики...
Привет, Хабр! Предлагаю вашему вниманию перевод статьи "Using GitHub Actions with C++ and CMake" о сборке проекта на C++ с использованием GitHub Actions и CMake автора Крист...
Этот пост будет из серии, об инструментах безопасности, которые доступны в Битриксе сразу «из коробки». Перечислю их все, скажу какой инструмент в какой редакции Битрикса доступен, кратко и не очень р...
Под удар попадут пластиковые соломинки, ватные палочки, мешалки для напитков, тарелки, столовые приборы, пластиковые пакетики, воздушные шарики и многое другое. Запрет вступит в силу с 2021 г...