Базовые FX на GMS2. Сложные эффекты

Базовые FX на GMS2. Сложные эффекты VFX, Gms2, Gamedev, Гифка, Длиннопост

В предыдущих постах был обзор системы частиц и частично фишки по сношению частиц с кодом. Но не частицами едиными, как говорится. В некоторых задачах частицы вообще не нужны или выполняют только вспомогательную роль, а используется программная генерация и шейдеры.

Погнали!

Базовые FX на GMS2. Сложные эффекты VFX, Gms2, Gamedev, Гифка, Длиннопост

Молнии, ага. Их уже не сделать с помощью системы частиц. Это не массив объектов, это цельный, протяженный, хаотично-упорядоченный объект, который отрисовывается, зачастую сразу полностью (ну в реале типа так проиходит по ощущениям).

Базовые FX на GMS2. Сложные эффекты VFX, Gms2, Gamedev, Гифка, Длиннопост

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

Итак имеем:

-яркий протяженный объект, который меняет свою внутреннюю структуру

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

vertex_format_begin();
vertex_format_add_position();
vertex_format_add_colour();
vertex_format_add_textcoord();
v_format = vertex_format_end();
v_buff = vertex_create_buffer();
vertex_begin(v_buff, v_format);

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

функция отрисовки выглядит так:

vertex_submit(buff, pr_trianglelist, sprite_get_texture(sprite_index));

тут юзер сам решает что (buff), каким макаром (pr_trianglelist) и с использованием чего (prite_index) отрисовывать. Т.е. берётся массив точек из buff, и по типу построения pr_trianglelist(разрозненные треугольники) отрисовывается.

В нашей задаче молния непрерывна, поэтому функция отрисовки идет через pr_trianglestrip.

Базовые FX на GMS2. Сложные эффекты VFX, Gms2, Gamedev, Гифка, Длиннопост

чтобы сформировать саму загогулину, приходится мотать вертекс буфер по циклу, в каждой итерации прибавляя к текущему положению с помощью lengthdir_x/lengthdir_y значения для точек следующего шага. Честно говоря, тут я жоско втупил и полез даже на форум спрашивать совета, однако первый же ответ спровоцировал меня перепроверить свои вычисления и я нашел ошибку со знаками. Зря людей тревожил.

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

Базовые FX на GMS2. Сложные эффекты VFX, Gms2, Gamedev, Гифка, Длиннопост

в принципе, на этом хитрости заканчиваются(нет). И можно получить "молнию", распространяющуюся из точки в направлении на определённую дистанцию.

Базовые FX на GMS2. Сложные эффекты VFX, Gms2, Gamedev, Гифка, Длиннопост

Но что делать с монохромным зигзагом? Тут как раз пригодятся шейдеры. Совсем простой frag-шейдер. Вертексный тут нам вообще не нужно трогать.

varying vec2 v_vTexcoord;
uniform float cur_alpha;
uniform float col_r;
uniform float col_g;
uniform float col_b;
void main()
{
vec4 col = vec4 (col_r,col_g,col_b,0.0);
col.r *= (1.0-(abs((v_vTexcoord.x-0.5)*2.0)));
col.g *= (1.0-(abs((v_vTexcoord.x-0.5)*2.0)));
col.b *= (1.0-(abs((v_vTexcoord.x-0.5)*2.0)));
gl_FragColor = col;
gl_FragColor.a = (1.0-sqrt(abs(v_vTexcoord.x-0.5)*2.0)) * cur_alpha;
}

Он просто принимает из объекта(функции, откуда укажит пользователь) значения для цветов по ргб каналам, значение для корректировки альфы и всё это обсчитывает, основываясь на значениях текстурных координат. Тут надо пояснить, что текстурные координаты берутся из точки и я при формировании сам устанавливаю их для левых 0, для правых 1 (ну или наоборот, кто их знает). А в шейдере получаю градиент от границы объекта к центру. Градиент для цвета линейный. Градиент для шейдера - через квадратный корень. Кому интересно разница вот в чем:

Базовые FX на GMS2. Сложные эффекты VFX, Gms2, Gamedev, Гифка, Длиннопост

т.е. для корня в моём случае будет "острее" серединка, т.е. место где прозрачности не будет, потом резкий спад и плавное затухание. Этакая аура вокруг центральной части. Модификатор cur_alpha я тут использовал для реализации мерцания всей молнии... чтобы она просто не выглядела статичной, а "жила", как любят говорить всякие художники...

Шейдер вызывается из объекта. Вот функция отрисовки конечного результата:

shader_set(shader_lightning)

//color settings to shader

shader_col_r = shader_get_uniform(shader_lightning, "col_r");

shader_col_b = shader_get_uniform(shader_lightning, "col_b");

shader_col_g = shader_get_uniform(shader_lightning, "col_g");

shader_set_uniform_f(shader_col_r,0.6)

shader_set_uniform_f(shader_col_g,0.6)

shader_set_uniform_f(shader_col_b,2)

//alpha settings to shader

shader_alpha = shader_get_uniform(shader_lightning, "cur_alpha");

shader_set_uniform_f(shader_alpha,random_range(0.8,1.2))

for (var i=0;i < ds_list_size(vb);i++)

{

cvb = ds_list_find_value(vb,i)

//draw call

vertex_submit(cvb,pr_trianglestrip,sprite_get_texture(sprite1,0))

//draw call to moar HOT effect

gpu_set_blendmode(bm_add)

vertex_submit(cvb,pr_trianglestrip,sprite_get_texture(sprite1,0))

gpu_set_blendmode(bm_normal)

}

shader_reset()

Что здесь происходит:

цикл прокатывается по всему массиву (vb, в моём случае). И отрисовывает все вертекс буферы, которые в нём лежат (а в него приходится складывать по частям кажду "веточку", потому что если их сцепить в один массив - то между концами потянуться перемычки, которые нам не нужны). Шейдер устанавливается на нужный, в него впихиваются все переменные (только сперва их нужно вызвать), устанавливается по вкусу. Внимательный зритель уже заметил, что в col_b стоит 2, что как бы вызывает сомнения в адекватности автора... на первый взгляд. Но, на самом деле, нет. Этот параметр реально будет работать за пределами единицы, ввиду того, что у нас для расчёта цвета стоит формула с линейным затуханием. Дальше сама отрисовка и тут приходится костылить. Можно закостылить в шейдере, по идее, но мне лень, так как есть более простой способ. Устанавливаем gpu_set_blendmode(bm_add) (режим смешивания для видеокарты) и отрисовывает этот же примитив поверх предыдущего. Add - смешивает цвета вашего объекта с цветами фона под ним. Поэтому нельзя просто так взять и... нужна подложка, без неё всё будет не так красочно.

Базовые FX на GMS2. Сложные эффекты VFX, Gms2, Gamedev, Гифка, Длиннопост

Ну и "на фоне" (рандомный картинка из интернетофф)

Базовые FX на GMS2. Сложные эффекты VFX, Gms2, Gamedev, Гифка, Длиннопост

ну и куда же без оружия. LightningGun в студию:

Базовые FX на GMS2. Сложные эффекты VFX, Gms2, Gamedev, Гифка, Длиннопост

Уж простите за непрезентабельную иконку "игрока" ) Думаю всем понятно, что она тут не главное. Молния выполнена по тому же принципу, с одной лишь разницей:

lightning_direction = (prev_lightning_dir+point_direction(start_pos_x,start_pos_y,end_pos_x,end_pos_y))/2+random_range((i-steps),(abs(i-steps)))

каждый проход молния всё сильнее стремиться попасть в точку назначения, где и заканчивается в итоге, иначе уходила бы она в сраные ебеня, само собой. Ну а "след" - просто несколько последовательно вызываемых партиклов.

З.ы. вопросы в комменты, ссылка на проект, для личного ковыряния: https://yadi.sk/d/HtxPPn8R3R29uU

Правила сообщества

ОБЩИЕ ПРАВИЛА:

- Уважайте чужой труд и используйте конструктивную критику

- Не занимайтесь саморекламой, пишите качественные и интересные посты

- Никакой политики


СТОИТ ПУБЛИКОВАТЬ:

- Посты о Вашей игре с историей её разработки и описанием полученного опыта

- Обучающие материалы, туториалы

- Интервью с опытными разработчиками

- Анонсы бесплатных мероприятий для разработчиков и истории их посещения;
- Ваши работы, если Вы художник/композитор и хотите поделиться ими на безвозмездной основе

НЕ СТОИТ ПУБЛИКОВАТЬ:

- Посты, содержащие только вопрос или просьбу помочь
- Посты, содержащие только идею игры

- Посты, единственная цель которых - набор команды для разработки игры

- Посты, не относящиеся к тематике сообщества

Подобные посты по решению администрации могут быть перемещены из сообщества в общую ленту.

ЗАПРЕЩЕНО:

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

- Выдавать чужой труд за свой

Подобные посты будут перемещены из сообщества в общую ленту, а их авторы по решению администрации могут быть внесены в игнор-лист сообщества.


О РАЗМЕЩЕНИИ ССЫЛОК:

Ссылка на сторонний ресурс, связанный с игрой, допускается только при следующих условиях:

- Пост должен быть содержательным и интересным для пользователей, нести пользу для сообщества

- Ссылка должна размещаться непосредственно в начале или конце поста и только один раз

- Cсылка размещается в формате: "Страница игры в Steam: URL"