From b5f227b5c50b5c3fcbb7adbcc268dc9c47ced94a Mon Sep 17 00:00:00 2001 From: Tanasart Date: Sat, 22 Jun 2024 17:09:44 +0700 Subject: [PATCH] - New Path Blur node. --- PixelComposer.resource_order | 3 + PixelComposer.yyp | 3 + scripts/blurSurface/blurSurface.gml | 10 +- scripts/node_bloom/node_bloom.gml | 25 ++- scripts/node_blur/node_blur.gml | 69 +++++++- scripts/node_blur_path/node_blur_path.gml | 103 ++++++++++++ scripts/node_blur_path/node_blur_path.yy | 13 ++ .../node_blur_path/node_color_adjustment.yy | 12 ++ .../node_blur_path/node_color_replacement.yy | 12 ++ scripts/node_blur_path/node_glow.yy | 12 ++ scripts/node_blur_path/node_outline.yy | 12 ++ scripts/node_blur_shape/node_blur_shape.gml | 8 +- scripts/node_registry/node_registry.gml | 1 + shaders/sh_blur_gaussian/sh_blur_gaussian.fsh | 13 +- shaders/sh_blur_path/sh_blur_path.fsh | 159 ++++++++++++++++++ shaders/sh_blur_path/sh_blur_path.vsh | 19 +++ shaders/sh_blur_path/sh_blur_path.yy | 12 ++ .../b69062de-1043-4ac5-84f1-a72065b36cf5.png | Bin 0 -> 1192 bytes .../8a433c50-e223-4d7f-bdbf-42704debc24f.png | Bin 0 -> 1192 bytes sprites/s_node_blur_path/s_node_blur_path.yy | 90 ++++++++++ 20 files changed, 548 insertions(+), 28 deletions(-) create mode 100644 scripts/node_blur_path/node_blur_path.gml create mode 100644 scripts/node_blur_path/node_blur_path.yy create mode 100644 scripts/node_blur_path/node_color_adjustment.yy create mode 100644 scripts/node_blur_path/node_color_replacement.yy create mode 100644 scripts/node_blur_path/node_glow.yy create mode 100644 scripts/node_blur_path/node_outline.yy create mode 100644 shaders/sh_blur_path/sh_blur_path.fsh create mode 100644 shaders/sh_blur_path/sh_blur_path.vsh create mode 100644 shaders/sh_blur_path/sh_blur_path.yy create mode 100644 sprites/s_node_blur_path/b69062de-1043-4ac5-84f1-a72065b36cf5.png create mode 100644 sprites/s_node_blur_path/layers/b69062de-1043-4ac5-84f1-a72065b36cf5/8a433c50-e223-4d7f-bdbf-42704debc24f.png create mode 100644 sprites/s_node_blur_path/s_node_blur_path.yy diff --git a/PixelComposer.resource_order b/PixelComposer.resource_order index c69f35d9e..179317b3f 100644 --- a/PixelComposer.resource_order +++ b/PixelComposer.resource_order @@ -707,6 +707,7 @@ {"name":"node_blur_bokeh","order":3,"path":"scripts/node_blur_bokeh/node_blur_bokeh.yy",}, {"name":"node_blur_contrast","order":4,"path":"scripts/node_blur_contrast/node_blur_contrast.yy",}, {"name":"node_blur_directional","order":5,"path":"scripts/node_blur_directional/node_blur_directional.yy",}, + {"name":"node_blur_path","order":13,"path":"scripts/node_blur_path/node_blur_path.yy",}, {"name":"node_blur_radial","order":6,"path":"scripts/node_blur_radial/node_blur_radial.yy",}, {"name":"node_blur_shape","order":7,"path":"scripts/node_blur_shape/node_blur_shape.yy",}, {"name":"node_blur_simple","order":8,"path":"scripts/node_blur_simple/node_blur_simple.yy",}, @@ -1306,6 +1307,7 @@ {"name":"sh_blur_directional","order":5,"path":"shaders/sh_blur_directional/sh_blur_directional.yy",}, {"name":"sh_blur_final","order":6,"path":"shaders/sh_blur_final/sh_blur_final.yy",}, {"name":"sh_blur_gaussian","order":7,"path":"shaders/sh_blur_gaussian/sh_blur_gaussian.yy",}, + {"name":"sh_blur_path","order":14,"path":"shaders/sh_blur_path/sh_blur_path.yy",}, {"name":"sh_blur_radial","order":8,"path":"shaders/sh_blur_radial/sh_blur_radial.yy",}, {"name":"sh_blur_shape","order":9,"path":"shaders/sh_blur_shape/sh_blur_shape.yy",}, {"name":"sh_blur_simple","order":10,"path":"shaders/sh_blur_simple/sh_blur_simple.yy",}, @@ -1693,6 +1695,7 @@ {"name":"s_node_bloom","order":7,"path":"sprites/s_node_bloom/s_node_bloom.yy",}, {"name":"s_node_blur_contrast","order":2,"path":"sprites/s_node_blur_contrast/s_node_blur_contrast.yy",}, {"name":"s_node_blur_directional","order":3,"path":"sprites/s_node_blur_directional/s_node_blur_directional.yy",}, + {"name":"s_node_blur_path","order":9,"path":"sprites/s_node_blur_path/s_node_blur_path.yy",}, {"name":"s_node_blur_simple","order":4,"path":"sprites/s_node_blur_simple/s_node_blur_simple.yy",}, {"name":"s_node_blur_slope","order":5,"path":"sprites/s_node_blur_slope/s_node_blur_slope.yy",}, {"name":"s_node_blur","order":1,"path":"sprites/s_node_blur/s_node_blur.yy",}, diff --git a/PixelComposer.yyp b/PixelComposer.yyp index 22cc990fa..a9d706b93 100644 --- a/PixelComposer.yyp +++ b/PixelComposer.yyp @@ -1097,6 +1097,7 @@ {"id":{"name":"node_blur_bokeh","path":"scripts/node_blur_bokeh/node_blur_bokeh.yy",},}, {"id":{"name":"node_blur_contrast","path":"scripts/node_blur_contrast/node_blur_contrast.yy",},}, {"id":{"name":"node_blur_directional","path":"scripts/node_blur_directional/node_blur_directional.yy",},}, + {"id":{"name":"node_blur_path","path":"scripts/node_blur_path/node_blur_path.yy",},}, {"id":{"name":"node_blur_radial","path":"scripts/node_blur_radial/node_blur_radial.yy",},}, {"id":{"name":"node_blur_shape","path":"scripts/node_blur_shape/node_blur_shape.yy",},}, {"id":{"name":"node_blur_simple","path":"scripts/node_blur_simple/node_blur_simple.yy",},}, @@ -1790,6 +1791,7 @@ {"id":{"name":"sh_blur_directional","path":"shaders/sh_blur_directional/sh_blur_directional.yy",},}, {"id":{"name":"sh_blur_final","path":"shaders/sh_blur_final/sh_blur_final.yy",},}, {"id":{"name":"sh_blur_gaussian","path":"shaders/sh_blur_gaussian/sh_blur_gaussian.yy",},}, + {"id":{"name":"sh_blur_path","path":"shaders/sh_blur_path/sh_blur_path.yy",},}, {"id":{"name":"sh_blur_radial","path":"shaders/sh_blur_radial/sh_blur_radial.yy",},}, {"id":{"name":"sh_blur_shape","path":"shaders/sh_blur_shape/sh_blur_shape.yy",},}, {"id":{"name":"sh_blur_simple","path":"shaders/sh_blur_simple/sh_blur_simple.yy",},}, @@ -2241,6 +2243,7 @@ {"id":{"name":"s_node_bloom","path":"sprites/s_node_bloom/s_node_bloom.yy",},}, {"id":{"name":"s_node_blur_contrast","path":"sprites/s_node_blur_contrast/s_node_blur_contrast.yy",},}, {"id":{"name":"s_node_blur_directional","path":"sprites/s_node_blur_directional/s_node_blur_directional.yy",},}, + {"id":{"name":"s_node_blur_path","path":"sprites/s_node_blur_path/s_node_blur_path.yy",},}, {"id":{"name":"s_node_blur_simple","path":"sprites/s_node_blur_simple/s_node_blur_simple.yy",},}, {"id":{"name":"s_node_blur_slope","path":"sprites/s_node_blur_slope/s_node_blur_slope.yy",},}, {"id":{"name":"s_node_blur","path":"sprites/s_node_blur/s_node_blur.yy",},}, diff --git a/scripts/blurSurface/blurSurface.gml b/scripts/blurSurface/blurSurface.gml index 0a307e693..1393563cc 100644 --- a/scripts/blurSurface/blurSurface.gml +++ b/scripts/blurSurface/blurSurface.gml @@ -28,7 +28,7 @@ function __gaussian_get_kernel(size) { return gau_array; } -function surface_apply_gaussian(surface, size, bg = false, bg_c = c_white, sampleMode = 0, overColor = noone, gamma = false) { +function surface_apply_gaussian(surface, size, bg = false, bg_c = c_white, sampleMode = 0, overColor = noone, gamma = false, ratio = 1, angle = 0) { var format = surface_get_format(surface); var _sw = surface_get_width_safe(surface); var _sh = surface_get_height_safe(surface); @@ -52,6 +52,7 @@ function surface_apply_gaussian(surface, size, bg = false, bg_c = c_white, sampl shader_set_i("size", size); shader_set_i("horizontal", 1); shader_set_i("gamma", gamma); + shader_set_f("angle", degtorad(angle)); shader_set_i("overrideColor", overColor != noone); shader_set_f("overColor", colToVec4(overColor)); @@ -62,10 +63,13 @@ function surface_apply_gaussian(surface, size, bg = false, bg_c = c_white, sampl surface_set_target(__blur_vert); draw_clear_alpha(bg_c, bg); - + var _size_v = round(size * ratio); + shader_set(sh_blur_gaussian); + shader_set_f("weight", __gaussian_get_kernel(_size_v)); + shader_set_i("size", _size_v); shader_set_i("horizontal", 0); - + draw_surface_safe(__blur_hori, 0, 0); shader_reset(); surface_reset_target(); diff --git a/scripts/node_bloom/node_bloom.gml b/scripts/node_bloom/node_bloom.gml index 330070c4a..f63955507 100644 --- a/scripts/node_bloom/node_bloom.gml +++ b/scripts/node_bloom/node_bloom.gml @@ -26,9 +26,16 @@ function Node_Bloom(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) con __init_mask_modifier(5); // inputs 9, 10 + inputs[| 11] = nodeValue("Aspect Ratio", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1) + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 12] = nodeValue("Direction", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0) + .setDisplay(VALUE_DISPLAY.rotation); + input_display_list = [ 7, 8, - ["Surfaces", true], 0, 5, 6, 9, 10, - ["Bloom", false], 1, 2, 3, 4, + ["Surfaces", true], 0, 5, 6, 9, 10, + ["Bloom", false], 1, 2, 3, 4, + ["Directional", true], 11, 12, ] outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); @@ -42,11 +49,13 @@ function Node_Bloom(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) con } #endregion static processData = function(_outSurf, _data, _output_index, _array_index) { - var _size = _data[1]; - var _tole = _data[2]; - var _stre = _data[3]; - var _mask = _data[4]; - var pass1 = surface_create_valid(surface_get_width_safe(_outSurf), surface_get_height_safe(_outSurf), attrDepth()); + var _size = _data[1]; + var _tole = _data[2]; + var _stre = _data[3]; + var _mask = _data[4]; + var _ratio = _data[11]; + var _angle = _data[12]; + var pass1 = surface_create_valid(surface_get_width_safe(_outSurf), surface_get_height_safe(_outSurf), attrDepth()); surface_set_shader(pass1, sh_bloom_pass); draw_clear_alpha(c_black, 1); @@ -59,7 +68,7 @@ function Node_Bloom(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) con draw_surface_safe(_data[0]); surface_reset_shader(); - var pass1blur = surface_apply_gaussian(pass1, _size, true, c_black, 1); + var pass1blur = surface_apply_gaussian(pass1, _size, true, c_black, 1, noone, false, _ratio, _angle); surface_free(pass1); surface_set_shader(_outSurf, sh_blend_add_alpha_adj); diff --git a/scripts/node_blur/node_blur.gml b/scripts/node_blur/node_blur.gml index 0593c04d8..112cc5661 100644 --- a/scripts/node_blur/node_blur.gml +++ b/scripts/node_blur/node_blur.gml @@ -27,13 +27,22 @@ function Node_Blur(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons inputs[| 11] = nodeValue("Gamma Correction", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false); + inputs[| 12] = nodeValue("Aspect Ratio", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1) + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 13] = nodeValue("Direction", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 0) + .setDisplay(VALUE_DISPLAY.rotation); + outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); input_display_list = [ 7, 8, - ["Surfaces", true], 0, 5, 6, 9, 10, - ["Blur", false], 1, 3, 4, 11, + ["Surfaces", true], 0, 5, 6, 9, 10, + ["Blur", false], 1, 3, 4, 11, + ["Directional", true], 12, 13, ]; + temp_surface = [ 0, 0 ]; + attribute_surface_depth(); attribute_oversample(); surface_blur_init(); @@ -43,22 +52,70 @@ function Node_Blur(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) cons } #endregion static processData = function(_outSurf, _data, _output_index, _array_index) { #region - var _size = _data[1]; + var _surf = _data[0]; + var _size = min(128, _data[1]); var _clamp = struct_try_get(attributes, "oversample"); var _isovr = _data[3]; var _mask = _data[5]; var _mix = _data[6]; var _overc = _isovr? _data[4] : noone; var _gam = _data[11]; + var _aspc = _data[12]; + var _dirr = _data[13]; inputs[| 4].setVisible(_isovr); + var format = surface_get_format(_surf); + var _sw = surface_get_width_safe(_surf); + var _sh = surface_get_height_safe(_surf); + + for(var i = 0; i < 2; i++) + temp_surface[i] = surface_verify(temp_surface[i], _sw, _sh, format); + + BLEND_OVERRIDE + gpu_set_tex_filter(true); + + surface_set_target(temp_surface[0]); + draw_clear_alpha(c_white, false); + + shader_set(sh_blur_gaussian); + shader_set_f("dimension", [ _sw, _sh ]); + shader_set_f("weight", __gaussian_get_kernel(_size)); + + shader_set_i("sampleMode", _clamp); + shader_set_i("size", _size); + shader_set_i("horizontal", 1); + shader_set_i("gamma", _gam); + + shader_set_i("overrideColor", _overc != noone); + shader_set_f("overColor", colToVec4(_overc)); + shader_set_f("angle", degtorad(_dirr)); + + draw_surface_safe(_surf, 0, 0); + shader_reset(); + surface_reset_target(); + + surface_set_target(temp_surface[1]); + draw_clear_alpha(c_white, false); + + var _size_v = round(_size * _aspc); + + shader_set(sh_blur_gaussian); + shader_set_f("weight", __gaussian_get_kernel(_size_v)); + shader_set_i("size", _size_v); + shader_set_i("horizontal", 0); + + draw_surface_safe(temp_surface[0], 0, 0); + shader_reset(); + surface_reset_target(); + + gpu_set_tex_filter(false); + surface_set_target(_outSurf); draw_clear_alpha(_isovr? _overc : 0, 0); - BLEND_OVERRIDE; - draw_surface_safe(surface_apply_gaussian(_data[0], _size, false, c_white, _clamp, _overc, _gam), 0, 0); - BLEND_NORMAL; + draw_surface(temp_surface[1], 0, 0); surface_reset_target(); + BLEND_NORMAL; __process_mask_modifier(_data); _outSurf = mask_apply(_data[0], _outSurf, _mask, _mix); diff --git a/scripts/node_blur_path/node_blur_path.gml b/scripts/node_blur_path/node_blur_path.gml new file mode 100644 index 000000000..10dee4f59 --- /dev/null +++ b/scripts/node_blur_path/node_blur_path.gml @@ -0,0 +1,103 @@ +function Node_Blur_Path(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) constructor { + name = "Path Blur"; + + inputs[| 0] = nodeValue("Surface in", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); + inputs[| 1] = nodeValue("Blur Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.pathnode, noone) + .setVisible(true, true); + + inputs[| 2] = nodeValue("Resolution", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 32); + + inputs[| 3] = nodeValue("Mask", self, JUNCTION_CONNECT.input, VALUE_TYPE.surface, noone); + + inputs[| 4] = nodeValue("Mix", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1) + .setDisplay(VALUE_DISPLAY.slider); + + inputs[| 5] = nodeValue("Active", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, true); + active_index = 5; + + inputs[| 6] = nodeValue("Channel", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0b1111) + .setDisplay(VALUE_DISPLAY.toggle, { data: array_create(4, THEME.inspector_channel) }); + + __init_mask_modifier(3); // inputs 7, 8 + + inputs[| 9] = nodeValue("Intensity", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, 1); + + inputs[| 10] = nodeValue("Intensity Along Path", self, JUNCTION_CONNECT.input, VALUE_TYPE.curve, CURVE_DEF_11); + + inputs[| 11] = nodeValue("Range", self, JUNCTION_CONNECT.input, VALUE_TYPE.float, [ 0, 1 ]) + .setDisplay(VALUE_DISPLAY.slider_range); + + input_display_list = [ 5, 6, + ["Surfaces", true], 0, 3, 4, 7, 8, + ["Path", false], 1, 11, + ["Blur", false], 2, 9, 10, + ]; + + outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); + + attribute_surface_depth(); + attribute_oversample(); + + static step = function() { + __step_mask_modifier(); + } + + static processData = function(_outSurf, _data, _output_index, _array_index) { + if(!is_surface(_data[0])) return _outSurf; + + var _samp = struct_try_get(attributes, "oversample"); + var _surf = _data[0]; + var _path = _data[1]; + var _reso = _data[2]; + var _intn = _data[9]; + var _curv = _data[10]; + var _rang = _data[11]; + + var _pntc = clamp(_reso, 2, 128); + if(!is_struct(_path)) return _outSurf; + + var _dim = surface_get_dimension(_surf) + var _points_x = array_create(_pntc); + var _points_y = array_create(_pntc); + var _p = new __vec2(); + + var _rst = _rang[0]; + var _red = _rang[1]; + var _rrr = _red - _rst; + + var ox = 0, oy = 0; + _p = _path.getPointRatio(0, 0, _p); + ox = _p.x; + oy = _p.y; + + for(var i = 0; i < _pntc; i++) { + var _pg = clamp(_rst + _rrr * i / (_pntc - 1), 0., 0.99); + _p = _path.getPointRatio(_pg, 0, _p); + + _points_x[i] = (_p.x - ox) / _dim[0]; + _points_y[i] = (_p.y - oy) / _dim[1]; + } + + surface_set_shader(_outSurf, sh_blur_path); + shader_set_f("dimension", _dim); + shader_set_i("sampleMode", _samp); + + shader_set_i("resolution", _pntc); + shader_set_i("pointAmount", _pntc); + shader_set_f("points_x", _points_x); + shader_set_f("points_y", _points_y); + + shader_set_f("intensity", _intn); + shader_set_f("i_curve", _curv); + shader_set_i("i_amount", array_length(_curv)); + + draw_surface_safe(_surf); + surface_reset_shader(); + + __process_mask_modifier(_data); + _outSurf = mask_apply(_surf, _outSurf, _data[3], _data[4]); + _outSurf = channel_apply(_surf, _outSurf, _data[6]); + + return _outSurf; + } +} \ No newline at end of file diff --git a/scripts/node_blur_path/node_blur_path.yy b/scripts/node_blur_path/node_blur_path.yy new file mode 100644 index 000000000..8fd7008bd --- /dev/null +++ b/scripts/node_blur_path/node_blur_path.yy @@ -0,0 +1,13 @@ +{ + "$GMScript":"", + "%Name":"node_blur_path", + "isCompatibility":false, + "isDnD":false, + "name":"node_blur_path", + "parent":{ + "name":"blur", + "path":"folders/nodes/data/filter/blur.yy", + }, + "resourceType":"GMScript", + "resourceVersion":"2.0", +} \ No newline at end of file diff --git a/scripts/node_blur_path/node_color_adjustment.yy b/scripts/node_blur_path/node_color_adjustment.yy new file mode 100644 index 000000000..b90346cca --- /dev/null +++ b/scripts/node_blur_path/node_color_adjustment.yy @@ -0,0 +1,12 @@ +{ + "isDnD": false, + "isCompatibility": false, + "parent": { + "name": "process", + "path": "folders/nodes/data/process.yy", + }, + "resourceVersion": "1.0", + "name": "node_color_adjustment", + "tags": [], + "resourceType": "GMScript", +} \ No newline at end of file diff --git a/scripts/node_blur_path/node_color_replacement.yy b/scripts/node_blur_path/node_color_replacement.yy new file mode 100644 index 000000000..024aa6a80 --- /dev/null +++ b/scripts/node_blur_path/node_color_replacement.yy @@ -0,0 +1,12 @@ +{ + "isDnD": false, + "isCompatibility": false, + "parent": { + "name": "process", + "path": "folders/nodes/data/process.yy", + }, + "resourceVersion": "1.0", + "name": "node_color_replacement", + "tags": [], + "resourceType": "GMScript", +} \ No newline at end of file diff --git a/scripts/node_blur_path/node_glow.yy b/scripts/node_blur_path/node_glow.yy new file mode 100644 index 000000000..27053f0a6 --- /dev/null +++ b/scripts/node_blur_path/node_glow.yy @@ -0,0 +1,12 @@ +{ + "isDnD": false, + "isCompatibility": false, + "parent": { + "name": "process", + "path": "folders/nodes/data/process.yy", + }, + "resourceVersion": "1.0", + "name": "node_glow", + "tags": [], + "resourceType": "GMScript", +} \ No newline at end of file diff --git a/scripts/node_blur_path/node_outline.yy b/scripts/node_blur_path/node_outline.yy new file mode 100644 index 000000000..86468bc09 --- /dev/null +++ b/scripts/node_blur_path/node_outline.yy @@ -0,0 +1,12 @@ +{ + "isDnD": false, + "isCompatibility": false, + "parent": { + "name": "process", + "path": "folders/nodes/data/process.yy", + }, + "resourceVersion": "1.0", + "name": "node_outline", + "tags": [], + "resourceType": "GMScript", +} \ No newline at end of file diff --git a/scripts/node_blur_shape/node_blur_shape.gml b/scripts/node_blur_shape/node_blur_shape.gml index 5e1b05404..240752953 100644 --- a/scripts/node_blur_shape/node_blur_shape.gml +++ b/scripts/node_blur_shape/node_blur_shape.gml @@ -20,13 +20,13 @@ function Node_Blur_Shape(_x, _y, _group = noone) : Node_Processor(_x, _y, _group inputs[| 7] = nodeValue("Mode", self, JUNCTION_CONNECT.input, VALUE_TYPE.integer, 0) .setDisplay(VALUE_DISPLAY.enum_button, [ "Blur", "Max" ]); - __init_mask_modifier(3); // inputs 7, 8 + __init_mask_modifier(3); // inputs 8, 9, - inputs[| 9] = nodeValue("Gamma Correction", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false); + inputs[| 10] = nodeValue("Gamma Correction", self, JUNCTION_CONNECT.input, VALUE_TYPE.boolean, false); input_display_list = [ 5, 6, - ["Surfaces", true], 0, 3, 4, 7, 8, - ["Blur", false], 7, 1, 2, 9, + ["Surfaces", true], 0, 3, 4, 8, 9, + ["Blur", false], 7, 1, 2, 10, ]; outputs[| 0] = nodeValue("Surface out", self, JUNCTION_CONNECT.output, VALUE_TYPE.surface, noone); diff --git a/scripts/node_registry/node_registry.gml b/scripts/node_registry/node_registry.gml index 6e4a6840c..f995f377d 100644 --- a/scripts/node_registry/node_registry.gml +++ b/scripts/node_registry/node_registry.gml @@ -572,6 +572,7 @@ function __initNodes() { addNodeObject(filter, "Lens Blur", s_node_bokeh, "Node_Blur_Bokeh", [1, Node_Blur_Bokeh], ["bokeh"], "Create bokeh effect. Blur lighter color in a lens-like manner.").setVersion(1110); addNodeObject(filter, "Contrast Blur", s_node_blur_contrast, "Node_Blur_Contrast", [1, Node_Blur_Contrast],, "Blur only pixel of a similiar color."); addNodeObject(filter, "Shape Blur", s_node_shape_blur, "Node_Blur_Shape", [1, Node_Blur_Shape]).setVersion(11650); + addNodeObject(filter, "Path Blur", s_node_blur_path, "Node_Blur_Path", [1, Node_Blur_Path]).setVersion(11750); addNodeObject(filter, "Average", s_node_average, "Node_Average", [1, Node_Average],, "Average color of every pixels in the image.").setVersion(1110); addNodeObject(filter, "Smear", s_node_smear, "Node_Smear", [1, Node_Smear]).setVersion(11670); addNodeObject(filter, "Kuwahara", s_node_kuwahara, "Node_Kuwahara", [1, Node_Kuwahara]).setVersion(11660); diff --git a/shaders/sh_blur_gaussian/sh_blur_gaussian.fsh b/shaders/sh_blur_gaussian/sh_blur_gaussian.fsh index 424908cb6..f67c2e9d1 100644 --- a/shaders/sh_blur_gaussian/sh_blur_gaussian.fsh +++ b/shaders/sh_blur_gaussian/sh_blur_gaussian.fsh @@ -1,6 +1,3 @@ -// -// Simple passthrough fragment shader -// varying vec2 v_vTexcoord; varying vec4 v_vColour; @@ -9,6 +6,7 @@ uniform int horizontal; uniform float weight[128]; uniform int size; +uniform float angle; uniform int sampleMode; uniform int overrideColor; @@ -48,19 +46,20 @@ vec4 sample(in vec2 pos, in int index) { } void main() { - vec2 tex_offset = 1.0 / dimension, pos; - vec4 result = sample( v_vTexcoord, 0 ); + vec2 tex_offset = 1.0 / dimension, pos; + vec4 result = sample( v_vTexcoord, 0 ); + mat2 rot = mat2(cos(angle), -sin(angle), sin(angle), cos(angle)); if(horizontal == 1) { for(int i = 1; i < size; i++) { - pos = vec2(tex_offset.x * float(i), 0.0); + pos = rot * vec2(tex_offset.x * float(i), 0.0); result += sample( v_vTexcoord + pos, i ); result += sample( v_vTexcoord - pos, i ); } } else { for(int i = 1; i < size; i++) { - pos = vec2(0.0, tex_offset.y * float(i)); + pos = rot * vec2(0.0, tex_offset.y * float(i)); result += sample( v_vTexcoord + pos, i ); result += sample( v_vTexcoord - pos, i ); diff --git a/shaders/sh_blur_path/sh_blur_path.fsh b/shaders/sh_blur_path/sh_blur_path.fsh new file mode 100644 index 000000000..a15769938 --- /dev/null +++ b/shaders/sh_blur_path/sh_blur_path.fsh @@ -0,0 +1,159 @@ +varying vec2 v_vTexcoord; +varying vec4 v_vColour; + +#define MAX_POINTS 256 + +uniform vec2 dimension; +uniform int sampleMode; + +uniform int resolution; +uniform int pointAmount; +uniform float points_x[MAX_POINTS]; +uniform float points_y[MAX_POINTS]; + +uniform float intensity; +uniform float i_curve[64]; +uniform int i_amount; + +vec4 sample(vec2 pos) { #region + if(pos.x >= 0. && pos.y >= 0. && pos.x <= 1. && pos.y <= 1.) + return texture2D(gm_BaseTexture, pos); + + if(sampleMode == 0) + return vec4(0.); + + else if(sampleMode == 1) + return texture2D(gm_BaseTexture, clamp(pos, 0., 1.)); + + else if(sampleMode == 2) + return texture2D(gm_BaseTexture, fract(pos)); + + else if(sampleMode == 3) + return vec4(vec3(0.), 1.); + + return vec4(0.); +} #endregion + +float eval_curve_segment_t(in float _y0, in float ax0, in float ay0, in float bx1, in float by1, in float _y1, in float prog) { + return _y0 * pow(1. - prog, 3.) + + ay0 * 3. * pow(1. - prog, 2.) * prog + + by1 * 3. * (1. - prog) * pow(prog, 2.) + + _y1 * pow(prog, 3.); +} + +float eval_curve_segment_x(in float _y0, in float ax0, in float ay0, in float bx1, in float by1, in float _y1, in float _x) { + float st = 0.; + float ed = 1.; + float _prec = 0.0001; + + float _xt = _x; + int _binRep = 8; + + if(_x <= 0.) return _y0; + if(_x >= 1.) return _y1; + if(_y0 == ay0 && _y0 == by1 && _y0 == _y1) return _y0; + + for(int i = 0; i < _binRep; i++) { + float _ftx = 3. * pow(1. - _xt, 2.) * _xt * ax0 + + 3. * (1. - _xt) * pow(_xt, 2.) * bx1 + + pow(_xt, 3.); + + if(abs(_ftx - _x) < _prec) + return eval_curve_segment_t(_y0, ax0, ay0, bx1, by1, _y1, _xt); + + if(_xt < _x) st = _xt; + else ed = _xt; + + _xt = (st + ed) / 2.; + } + + int _newRep = 16; + + for(int i = 0; i < _newRep; i++) { + float slope = ( 9. * ax0 - 9. * bx1 + 3.) * _xt * _xt + + (-12. * ax0 + 6. * bx1) * _xt + + 3. * ax0; + float _ftx = 3. * pow(1. - _xt, 2.) * _xt * ax0 + + 3. * (1. - _xt) * pow(_xt, 2.) * bx1 + + pow(_xt, 3.) + - _x; + + _xt -= _ftx / slope; + + if(abs(_ftx) < _prec) + break; + } + + _xt = clamp(_xt, 0., 1.); + return eval_curve_segment_t(_y0, ax0, ay0, bx1, by1, _y1, _xt); +} + +float curveEval(in float[64] curve, in int amo, in float _x) { + + int _shf = amo - int(floor(float(amo) / 6.) * 6.); + int _segs = (amo - _shf) / 6 - 1; + float _shift = _shf > 0? curve[0] : 0.; + float _scale = _shf > 1? curve[1] : 1.; + + _x = _x / _scale - _shift; + _x = clamp(_x, 0., 1.); + + for( int i = 0; i < _segs; i++ ) { + int ind = _shf + i * 6; + float _x0 = curve[ind + 2]; + float _y0 = curve[ind + 3]; + //float bx0 = _x0 + curve[ind + 0]; + //float by0 = _y0 + curve[ind + 1]; + float ax0 = _x0 + curve[ind + 4]; + float ay0 = _y0 + curve[ind + 5]; + + float _x1 = curve[ind + 6 + 2]; + float _y1 = curve[ind + 6 + 3]; + float bx1 = _x1 + curve[ind + 6 + 0]; + float by1 = _y1 + curve[ind + 6 + 1]; + //float ax1 = _x1 + curve[ind + 6 + 4]; + //float ay1 = _y1 + curve[ind + 6 + 5]; + + if(_x < _x0) continue; + if(_x > _x1) continue; + + return eval_curve_segment_x(_y0, ax0, ay0, bx1, by1, _y1, (_x - _x0) / (_x1 - _x0)); + } + + return curve[0]; +} + +void main() { + vec4 p = vec4(0.); + float a = 0.; + float x = float(pointAmount); + float sg = float(pointAmount) / float(resolution); + float ind, frc, pg, intn; + int i0, i1; + vec2 px, p0, p1; + vec4 ss; + + for(float i = 0.; i < float(resolution); i++) { + ind = sg * i; + i0 = int(floor(ind)); + i1 = i0 + 1; + frc = fract(ind); + + px.x = v_vTexcoord.x - mix(points_x[i0], points_x[i1], frc); + px.y = v_vTexcoord.y - mix(points_y[i0], points_y[i1], frc); + + ss = sample(px); + pg = i / x; + + intn = curveEval(i_curve, i_amount, pg); + ss *= intn * intensity; + + p += ss; + a += ss.a; + } + + p.rgb /= a; + p.a /= x; + + gl_FragColor = p; +} diff --git a/shaders/sh_blur_path/sh_blur_path.vsh b/shaders/sh_blur_path/sh_blur_path.vsh new file mode 100644 index 000000000..3900c20f4 --- /dev/null +++ b/shaders/sh_blur_path/sh_blur_path.vsh @@ -0,0 +1,19 @@ +// +// Simple passthrough vertex shader +// +attribute vec3 in_Position; // (x,y,z) +//attribute vec3 in_Normal; // (x,y,z) unused in this shader. +attribute vec4 in_Colour; // (r,g,b,a) +attribute vec2 in_TextureCoord; // (u,v) + +varying vec2 v_vTexcoord; +varying vec4 v_vColour; + +void main() +{ + vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0); + gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos; + + v_vColour = in_Colour; + v_vTexcoord = in_TextureCoord; +} diff --git a/shaders/sh_blur_path/sh_blur_path.yy b/shaders/sh_blur_path/sh_blur_path.yy new file mode 100644 index 000000000..188674fe5 --- /dev/null +++ b/shaders/sh_blur_path/sh_blur_path.yy @@ -0,0 +1,12 @@ +{ + "$GMShader":"", + "%Name":"sh_blur_path", + "name":"sh_blur_path", + "parent":{ + "name":"blur", + "path":"folders/shader/filter/blur.yy", + }, + "resourceType":"GMShader", + "resourceVersion":"2.0", + "type":1, +} \ No newline at end of file diff --git a/sprites/s_node_blur_path/b69062de-1043-4ac5-84f1-a72065b36cf5.png b/sprites/s_node_blur_path/b69062de-1043-4ac5-84f1-a72065b36cf5.png new file mode 100644 index 0000000000000000000000000000000000000000..4c3464ce416ce6d5b4e9a24d929b3fc04495eeff GIT binary patch literal 1192 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=3dtTpz6=aiY77hwEes65fI|H*Yfq{9pr;B4q#jU5a&wGmo ziX6AsKN>ITIb&JcOs>BMU58v}D|DFYM!8<7zp%=+TkP#(jzyu}3(Vdw3iGno&Jbi3 z6jTayTalRRHS^aW+slv6eOdOh_xMIoDERfF&oHsi2V<^zEX*mhss z&X&M_p?B^s{;Z>74a!f{^gAbbGOWFqX#I=9+l)a*N%CU+q2KHVoC~C0s7PL%&v|bK z(*;+fMfR==ztk8@lE2sAXH;vv`9XXc!<%g!55x@|H9n~^nk-(n)9Q8otUE2I7@zG) zZgc3*7j7u|65hbS;>5Y*hAB)A+@EA0ct6iaOc)}3gd5^gtPdE<_FiFK(0(U5U$gTZV+oT5M~qvY zkjcaphS+(Jk2f&CxcMxJ_kiXDp;h7QKiL%rYW|#DFRonr_I)J7zL{(VVmmnBbp6<; zdtry-6=(KXsf(!=TnCsR#7s2H3ON7gc*FNuw^p9ci(}|-yqtO?>-!tttc>RqG#SKC zm)r~IewEmga*9u=`0aiXhU+XjWsB5wy$g9OtJaSz^bN(7)jB*(38gcomp8W-wg3<&UG+Q>&!%n4oX5Q0*HS+3fwklA&GX)NU9fyrCAWjo#`tB8 z!~tE$-NBV}dYTMaV;pm<4A%L)IC?Vi${oADO$X8!#iw)EeG}N>KkshzGLd&I{!H^V z>P?S3t`!zp^>_OL+xI!4Gi}zNlXJhCv{FDOLFVdAH`o3AFWB$hD67$BuxqJH$evg> zEpY3e8OJ{|KH&T?@U<%y4rrF$tzVsqw+VvjH_DW8c~vxSdwa$T$Bo=7>o>zOmq#* zbd8Kc3@ojT%&kl9nO2Eg!%8mcRX`0Ia2rZ8b5n~;5_1c1 V>-i^dRSML@;OXk;vd$@?2>@nh<(B{e literal 0 HcmV?d00001 diff --git a/sprites/s_node_blur_path/layers/b69062de-1043-4ac5-84f1-a72065b36cf5/8a433c50-e223-4d7f-bdbf-42704debc24f.png b/sprites/s_node_blur_path/layers/b69062de-1043-4ac5-84f1-a72065b36cf5/8a433c50-e223-4d7f-bdbf-42704debc24f.png new file mode 100644 index 0000000000000000000000000000000000000000..4c3464ce416ce6d5b4e9a24d929b3fc04495eeff GIT binary patch literal 1192 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=3dtTpz6=aiY77hwEes65fI|H*Yfq{9pr;B4q#jU5a&wGmo ziX6AsKN>ITIb&JcOs>BMU58v}D|DFYM!8<7zp%=+TkP#(jzyu}3(Vdw3iGno&Jbi3 z6jTayTalRRHS^aW+slv6eOdOh_xMIoDERfF&oHsi2V<^zEX*mhss z&X&M_p?B^s{;Z>74a!f{^gAbbGOWFqX#I=9+l)a*N%CU+q2KHVoC~C0s7PL%&v|bK z(*;+fMfR==ztk8@lE2sAXH;vv`9XXc!<%g!55x@|H9n~^nk-(n)9Q8otUE2I7@zG) zZgc3*7j7u|65hbS;>5Y*hAB)A+@EA0ct6iaOc)}3gd5^gtPdE<_FiFK(0(U5U$gTZV+oT5M~qvY zkjcaphS+(Jk2f&CxcMxJ_kiXDp;h7QKiL%rYW|#DFRonr_I)J7zL{(VVmmnBbp6<; zdtry-6=(KXsf(!=TnCsR#7s2H3ON7gc*FNuw^p9ci(}|-yqtO?>-!tttc>RqG#SKC zm)r~IewEmga*9u=`0aiXhU+XjWsB5wy$g9OtJaSz^bN(7)jB*(38gcomp8W-wg3<&UG+Q>&!%n4oX5Q0*HS+3fwklA&GX)NU9fyrCAWjo#`tB8 z!~tE$-NBV}dYTMaV;pm<4A%L)IC?Vi${oADO$X8!#iw)EeG}N>KkshzGLd&I{!H^V z>P?S3t`!zp^>_OL+xI!4Gi}zNlXJhCv{FDOLFVdAH`o3AFWB$hD67$BuxqJH$evg> zEpY3e8OJ{|KH&T?@U<%y4rrF$tzVsqw+VvjH_DW8c~vxSdwa$T$Bo=7>o>zOmq#* zbd8Kc3@ojT%&kl9nO2Eg!%8mcRX`0Ia2rZ8b5n~;5_1c1 V>-i^dRSML@;OXk;vd$@?2>@nh<(B{e literal 0 HcmV?d00001 diff --git a/sprites/s_node_blur_path/s_node_blur_path.yy b/sprites/s_node_blur_path/s_node_blur_path.yy new file mode 100644 index 000000000..29cce88e8 --- /dev/null +++ b/sprites/s_node_blur_path/s_node_blur_path.yy @@ -0,0 +1,90 @@ +{ + "$GMSprite":"", + "%Name":"s_node_blur_path", + "bboxMode":0, + "bbox_bottom":62, + "bbox_left":2, + "bbox_right":61, + "bbox_top":1, + "collisionKind":1, + "collisionTolerance":0, + "DynamicTexturePage":false, + "edgeFiltering":false, + "For3D":false, + "frames":[ + {"$GMSpriteFrame":"","%Name":"b69062de-1043-4ac5-84f1-a72065b36cf5","name":"b69062de-1043-4ac5-84f1-a72065b36cf5","resourceType":"GMSpriteFrame","resourceVersion":"2.0",}, + ], + "gridX":0, + "gridY":0, + "height":64, + "HTile":false, + "layers":[ + {"$GMImageLayer":"","%Name":"8a433c50-e223-4d7f-bdbf-42704debc24f","blendMode":0,"displayName":"default","isLocked":false,"name":"8a433c50-e223-4d7f-bdbf-42704debc24f","opacity":100.0,"resourceType":"GMImageLayer","resourceVersion":"2.0","visible":true,}, + ], + "name":"s_node_blur_path", + "nineSlice":null, + "origin":4, + "parent":{ + "name":"blur", + "path":"folders/nodes/icons/filter/blur.yy", + }, + "preMultiplyAlpha":false, + "resourceType":"GMSprite", + "resourceVersion":"2.0", + "sequence":{ + "$GMSequence":"", + "%Name":"s_node_blur_path", + "autoRecord":true, + "backdropHeight":768, + "backdropImageOpacity":0.5, + "backdropImagePath":"", + "backdropWidth":1366, + "backdropXOffset":0.0, + "backdropYOffset":0.0, + "events":{ + "$KeyframeStore":"", + "Keyframes":[], + "resourceType":"KeyframeStore", + "resourceVersion":"2.0", + }, + "eventStubScript":null, + "eventToFunction":{}, + "length":1.0, + "lockOrigin":false, + "moments":{ + "$KeyframeStore":"", + "Keyframes":[], + "resourceType":"KeyframeStore", + "resourceVersion":"2.0", + }, + "name":"s_node_blur_path", + "playback":1, + "playbackSpeed":30.0, + "playbackSpeedType":0, + "resourceType":"GMSequence", + "resourceVersion":"2.0", + "showBackdrop":true, + "showBackdropImage":false, + "timeUnits":1, + "tracks":[ + {"$GMSpriteFramesTrack":"","builtinName":0,"events":[],"inheritsTrackColour":true,"interpolation":1,"isCreationTrack":false,"keyframes":{"$KeyframeStore":"","Keyframes":[ + {"$Keyframe":"","Channels":{ + "0":{"$SpriteFrameKeyframe":"","Id":{"name":"b69062de-1043-4ac5-84f1-a72065b36cf5","path":"sprites/s_node_blur_path/s_node_blur_path.yy",},"resourceType":"SpriteFrameKeyframe","resourceVersion":"2.0",}, + },"Disabled":false,"id":"7551c0e8-5e58-4cb5-bbb8-558ce6491fdf","IsCreationKey":false,"Key":0.0,"Length":1.0,"resourceType":"Keyframe","resourceVersion":"2.0","Stretch":false,}, + ],"resourceType":"KeyframeStore","resourceVersion":"2.0",},"modifiers":[],"name":"frames","resourceType":"GMSpriteFramesTrack","resourceVersion":"2.0","spriteId":null,"trackColour":0,"tracks":[],"traits":0,}, + ], + "visibleRange":null, + "volume":1.0, + "xorigin":32, + "yorigin":32, + }, + "swatchColours":null, + "swfPrecision":0.5, + "textureGroupId":{ + "name":"Default", + "path":"texturegroups/Default", + }, + "type":0, + "VTile":false, + "width":64, +} \ No newline at end of file