Использование разных частиц в Godot 3. Без использования эффектов постобработки.
Ссылки:
Запустить WebGL2 и скачать другие версии ссылка на itch.io.
Исходный код на github.
Статья разбита на разделы:
Сглаживание мелких частиц, разные способы.
Много шаров - частиц без потери производительности. И 3d-проекция в шейдере.
Система отпечатков Screen space decals.
Прочее.
1. Сглаживание частиц
Использую плоский объект размером в 2 или 4 раза больше чем отображаемая графика, самая критичная графика по центру текстуры, выглядит так, слева в 2 раза больше справа в 4 раза:
И черное становится прозрачным.
Идея в том чтобы иметь хотяб 1 пиксель вокруг основной линии при даже самых маленьких углах поворота и удалении от объекта. Я использую 4-х кратный отступ на самом дальнем объекте:
Код шейдера particlelineAAbase.shader включает три версии для теста - без фильтрации, с процедурной фильтрацией используя dFd*
функцию, и используя текстуру, порядок слева на право:
2. Проекция трехмерных частиц на плоскость
Использую intersection и projection логику в фрагментном шейдере.
Идея в том что - отобразить 1000 трехмерных шаров-частиц для видеокарты(GPU) стоит слишком дорого, и 1000 трехмерных шаров-частиц у меня уже нагружают GPU на 100%. Когда рендеринг 1000 кругов(не шаров) использует меньше 25% GPU.
И поворачивая плоский круг или квадрат относительно камеры можно иметь полноценный шар-частицу:
И можно использовать тысячи таких частиц без потери производительности, эти частицы генерируются на плоскости:
Исходный код шейдера шара particle_cloud_base.shader и код шейдера куба и линии.
Для шара оригинал кода взят из iquilezles.org.
3. Система отпечатков Screen space decals
Использую код шейдера из Screen-Space-Decals, мои модификации:
Поворот относительно позиции, по нормали к поверхности при установке.
Затухание на краях куба с dacal.
Логика Material-ID для того чтобы Decals оставались только на выбранной поверхности не затрагивая другие объекты рядом.
Работает так:
Про логику Material-ID:
В Godot нет возможности записывать дополнительную информацию в основном render-pass, информацию о типе материала. Поэтому я использую отдельный Viewport в котором есть только статическая сцена:
Красный канал для material-ID синий для значения глубины(depth). Глубина(depth) используется чтобы вырезать объекты. Логика выглядит так, на скриншоте частицы и персонаж не существуют на Material-ID Viewport и вырезаются по depth:
Использование отдельного Viewport это очевидный overhead, в качестве оптимизации можно уменьшить разрешение, это можно тестировать в этой версии - в меню Debug (мышку в левый верхний угол для показа меню) и установить множитель для теста, от 0.25 до 1.
4. Прочее
Частицы фонтана - идея в том чтобы оптимизировать логику частиц, где каждая частица генерируется из треугольников и меняет свой размер в зависимости от положения камеры, и частица всегда смотрит на камеру.
В таком случае нужна всего одна плоскость, минимум треугольников, чтоб генерировать частицы любой длины и они будут выглядеть объемными.
В качестве оригинала такой логики я использовал этот шейдер Garden Fireworks - @P_Malin.
Шейдер для картинки загрузки - мой старый шейдер.
Анимация форм функций - моя старая демка. (старая версия так и не заработала в WebGL,по прежнему работает только в браузере на Linux)
Логика - 360 линий поворачиваются на 1 градус каждая и вращаются вокруг центральной оси, каждая линия имеет форму одной из функций. Выглядит также как в оригинальной демке:
Баги:
В ходе написания этих шейдеров нашел несколько багов в драйверах Nvidia:
Краш компилятора, баг с матрицами в Vetrex шейдере, также запуская некоторые шейдеры в Vulkan там тоже есть баг в драйвере.
Лицензия и используемые материалы:
Все 3d модели взяты со sketchfab и имеют CC-non comercial лицензию.
Музыка взята с сайта patrickdearteaga.com
Весь мой код и все шейдеры имеют лицензию MIT license.
Ссылка на список используемых ресурсов.
Спасибо за чтение этой статьи.