diff --git a/modules/material_maker/SCsub b/modules/material_maker/SCsub index 998cdba5e..10a756265 100644 --- a/modules/material_maker/SCsub +++ b/modules/material_maker/SCsub @@ -156,6 +156,7 @@ sources = [ "nodes/filter/colorize.cpp", "nodes/filter/brightness_contrast.cpp", "nodes/filter/blur_gaussian.cpp", + "nodes/filter/blur_slope.cpp", "nodes/filter/blend.cpp", "nodes/filter/adjust_hsv.cpp", ] diff --git a/modules/material_maker/config.py b/modules/material_maker/config.py index d1f223fbf..f2353f169 100644 --- a/modules/material_maker/config.py +++ b/modules/material_maker/config.py @@ -116,18 +116,20 @@ def get_doc_classes(): "MMFillToUv", "MMFillToSize", "MMFillToRandomGrey", - "MMFillToRandomColor", - "MMFillToPosition", - "MMFillToColor", - "MMFillChannel", - "MMEmboss", - "MMDecompose", - "MMCombine", - "MMColorize", - "MMBrightnessContrast", - "MMBlurGaussian", - "MMBlend", - "MMAdjustHsv", + + "MMFillToRandomColor", + "MMFillToPosition", + "MMFillToColor", + "MMFillChannel", + "MMEmboss", + "MMDecompose", + "MMCombine", + "MMColorize", + "MMBrightnessContrast", + "MMBlurGaussian", + "MMBlurSlope", + "MMBlend", + "MMAdjustHsv", ] def get_doc_path(): diff --git a/modules/material_maker/nodes/filter/blur_slope.cpp b/modules/material_maker/nodes/filter/blur_slope.cpp new file mode 100644 index 000000000..bd90de4be --- /dev/null +++ b/modules/material_maker/nodes/filter/blur_slope.cpp @@ -0,0 +1,165 @@ + +#include "blur_slope.h" + +#include "../../algos/mm_algos.h" +#include "../../editor/mm_graph_node.h" +#include "../mm_material.h" + +Ref MMBlurSlope::get_image() { + return image; +} + +void MMBlurSlope::set_image(const Ref &val) { + image = val; +} + +Ref MMBlurSlope::get_input() { + return input; +} + +void MMBlurSlope::set_input(const Ref &val) { + input = val; +} + +Ref MMBlurSlope::get_sigma() { + return sigma; +} + +void MMBlurSlope::set_sigma(const Ref &val) { + sigma = val; +} + +void MMBlurSlope::_init_properties() { + if (!image.is_valid()) { + image.instance(); + image->set_default_type(MMNodeUniversalProperty::DEFAULT_TYPE_IMAGE); + } + + image->set_output_slot_type(MMNodeUniversalProperty::SLOT_TYPE_IMAGE); + + if (!input.is_valid()) { + input.instance(); + input->set_default_type(MMNodeUniversalProperty::DEFAULT_TYPE_COLOR); + input->set_default_value(Color()); + } + + input->set_input_slot_type(MMNodeUniversalProperty::SLOT_TYPE_UNIVERSAL); + input->set_slot_name(">>> Input1 "); + + if (!sigma.is_valid()) { + sigma.instance(); + sigma->set_default_type(MMNodeUniversalProperty::DEFAULT_TYPE_FLOAT); + sigma->set_default_value(50); + } + + sigma->set_input_slot_type(MMNodeUniversalProperty::SLOT_TYPE_UNIVERSAL); + sigma->set_slot_name("Sigma"); + + register_input_property(input); + register_output_property(image); + register_input_property(sigma); +} + +void MMBlurSlope::_register_methods(MMGraphNode *mm_graph_node) { + mm_graph_node->add_slot_texture_universal(image); + mm_graph_node->add_slot_label_universal(input); + mm_graph_node->add_slot_float_universal(sigma); +} + +void MMBlurSlope::_render(const Ref &material) { + size = MAX(material->image_size.x, material->image_size.y); + Ref img = render_image(material); + image->set_value(img); +} + +Ref MMBlurSlope::_render_image(const Ref &material) { + Ref img; + img.instance(); + + img->create(material->image_size.x, material->image_size.y, false, Image::FORMAT_RGBA8); + img->lock(); + + float w = img->get_width(); + float h = img->get_width(); + //float pseed = Math::randf() + Math::rand(); + + for (int x = 0; x < img->get_width(); ++x) { //x in range(img.get_width()) + + for (int y = 0; y < img->get_height(); ++y) { //y in range(img.get_height()) + Vector2 v = Vector2(x / w, y / h); + Color col = slope_blur(v, size); + img->set_pixel(x, y, col); + } + } + + img->unlock(); + + return img; +} + +//slope_blur.mmg; +/* +vec4 $(name) _fct(vec2 uv) { + float dx = 1.0 / $size; + float v = $heightmap(uv); + vec2 slope = vec2($heightmap(uv + vec2(dx, 0.0)) - v, $heightmap(uv + vec2(0.0, dx)) - v); + float slope_strength = length(slope) * $size; + vec2 norm_slope = (slope_strength == 0.0) ? vec2(0.0, 1.0) : normalize(slope); + vec2 e = dx * norm_slope; + vec4 rv = vec4(0.0); + float sum = 0.0; + float sigma = max($sigma * slope_strength, 0.0001); + for (float i = 0.0; i <= 50.0; i += 1.0) { + float coef = exp(-0.5 * (pow(i / sigma, 2.0))) / (6.28318530718 * sigma * sigma); + rv += $in(uv + i * e) * coef; + sum += coef; + } + return rv / sum; +} +*/ + +Color MMBlurSlope::slope_blur(const Vector2 &uv, const float psize) { + float dx = 1.0 / psize; + float v = sigma->get_value(uv); + float sx = sigma->get_value(uv + Vector2(dx, 0.0)); + float sy = sigma->get_value(uv + Vector2(0.0, dx)); + + Vector2 slope = Vector2(sx - v, sy - v); + float slope_strength = slope.length() * psize; + Vector2 norm_slope = (slope_strength == 0.0) ? Vector2(0.0, 1.0) : slope.normalized(); + Vector2 e = dx * norm_slope; + Color rv = Color(); + float sum = 0.0; + float sigma = MAX(v * slope_strength, 0.0001); + + for (float i = 0.0; i <= 50.0; i += 1.0) { + float coef = exp(-0.5 * (pow(i / sigma, 2.0))) / (6.28318530718 * sigma * sigma); + rv += Color(input->get_value(uv + i * e)) * coef; + sum += coef; + } + + return rv / sum; +} + +MMBlurSlope::MMBlurSlope() { + size = 0; +} + +MMBlurSlope::~MMBlurSlope() { +} + +void MMBlurSlope::_bind_methods() { + ClassDB::bind_method(D_METHOD("get_image"), &MMBlurSlope::get_image); + ClassDB::bind_method(D_METHOD("set_image", "value"), &MMBlurSlope::set_image); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "image", PROPERTY_HINT_RESOURCE_TYPE, "MMNodeUniversalProperty"), "set_image", "get_image"); + + ClassDB::bind_method(D_METHOD("get_input"), &MMBlurSlope::get_input); + ClassDB::bind_method(D_METHOD("set_input", "value"), &MMBlurSlope::set_input); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "input", PROPERTY_HINT_RESOURCE_TYPE, "MMNodeUniversalProperty"), "set_input", "get_input"); + + ClassDB::bind_method(D_METHOD("get_sigma"), &MMBlurSlope::get_sigma); + ClassDB::bind_method(D_METHOD("set_sigma", "value"), &MMBlurSlope::set_sigma); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "sigma", PROPERTY_HINT_RESOURCE_TYPE, "MMNodeUniversalProperty"), "set_sigma", "get_sigma"); + + ClassDB::bind_method(D_METHOD("slope_blur", "uv", "psize"), &MMBlurSlope::slope_blur); +} diff --git a/modules/material_maker/nodes/filter/blur_slope.h b/modules/material_maker/nodes/filter/blur_slope.h new file mode 100644 index 000000000..cb9baf6b2 --- /dev/null +++ b/modules/material_maker/nodes/filter/blur_slope.h @@ -0,0 +1,40 @@ +#ifndef MM_BLUR_SLOPE_H +#define MM_BLUR_SLOPE_H + +#include "../mm_node.h" +#include "../mm_node_universal_property.h" + +class MMBlurSlope : public MMNode { + GDCLASS(MMBlurSlope, MMNode); + +public: + Ref get_image(); + void set_image(const Ref &val); + + Ref get_input(); + void set_input(const Ref &val); + + Ref get_sigma(); + void set_sigma(const Ref &val); + + void _init_properties(); + void _register_methods(MMGraphNode *mm_graph_node); + void _render(const Ref &material); + Ref _render_image(const Ref &material); + + Color slope_blur(const Vector2 &uv, const float psize); + + MMBlurSlope(); + ~MMBlurSlope(); + +protected: + static void _bind_methods(); + + Ref image; + Ref input; + Ref sigma; + + float size; +}; + +#endif diff --git a/modules/material_maker/register_types.cpp b/modules/material_maker/register_types.cpp index 9bd818c44..79e165999 100644 --- a/modules/material_maker/register_types.cpp +++ b/modules/material_maker/register_types.cpp @@ -133,6 +133,7 @@ SOFTWARE. #include "nodes/filter/adjust_hsv.h" #include "nodes/filter/blend.h" #include "nodes/filter/blur_gaussian.h" +#include "nodes/filter/blur_slope.h" #include "nodes/filter/brightness_contrast.h" #include "nodes/filter/colorize.h" #include "nodes/filter/combine.h" @@ -371,6 +372,8 @@ void register_material_maker_types(ModuleRegistrationLevel p_level) { MMAlgos::register_node_class("Filter", "MMBrightnessContrast"); ClassDB::register_class(); MMAlgos::register_node_class("Filter", "MMBlurGaussian"); + ClassDB::register_class(); + MMAlgos::register_node_class("Filter", "MMBlurSlope"); ClassDB::register_class(); MMAlgos::register_node_class("Filter", "MMBlend"); ClassDB::register_class();