diff --git a/addons/procedural_material/common.shader b/addons/procedural_material/common.shader index 42f80d8..56dcbc8 100644 --- a/addons/procedural_material/common.shader +++ b/addons/procedural_material/common.shader @@ -305,3 +305,20 @@ vec4 voronoi(vec2 uv, vec2 size, float intensity, int seed) { return vec4(point0, best_distance0*length(size)*intensity, edge_distance); } + +// From http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl +vec3 rgb2hsv(vec3 c) { + vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); + vec4 p = c.g < c.b ? vec4(c.bg, K.wz) : vec4(c.gb, K.xy); + vec4 q = c.r < p.x ? vec4(p.xyw, c.r) : vec4(c.r, p.yzx); + + float d = q.x - min(q.w, q.y); + float e = 1.0e-10; + return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); +} + +vec3 hsv2rgb(vec3 c) { + vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); + vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); + return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); +} diff --git a/addons/procedural_material/library/base.json b/addons/procedural_material/library/base.json index d889dc1..7f27ca0 100644 --- a/addons/procedural_material/library/base.json +++ b/addons/procedural_material/library/base.json @@ -120,6 +120,13 @@ "scale_x":4, "scale_y":4 }, + { + "tree_item":"Filters/AdjustHSV", + "type":"adjust_hsv", + "hue":0, + "saturation":1, + "value":1 + }, { "tree_item":"Filters/Colorize", "type":"colorize", diff --git a/addons/procedural_material/node_base.gd b/addons/procedural_material/node_base.gd index 517613f..d358763 100644 --- a/addons/procedural_material/node_base.gd +++ b/addons/procedural_material/node_base.gd @@ -34,6 +34,9 @@ func initialize_properties(object_list): elif o is SpinBox: set(o.name, o.value) o.connect("value_changed", self, "_on_value_changed", [ o.name ]) + elif o is HSlider: + set(o.name, o.value) + o.connect("value_changed", self, "_on_value_changed", [ o.name ]) elif o is OptionButton: set(o.name, o.selected) o.connect("item_selected", self, "_on_value_changed", [ o.name ]) @@ -53,6 +56,8 @@ func update_property_widgets(): o.text = str(get(o.name)) elif o is SpinBox: o.value = get(o.name) + elif o is HSlider: + o.value = get(o.name) elif o is OptionButton: o.selected = get(o.name) elif o is CheckBox: diff --git a/addons/procedural_material/nodes/adjust_hsv.gd b/addons/procedural_material/nodes/adjust_hsv.gd new file mode 100644 index 0000000..5f032d8 --- /dev/null +++ b/addons/procedural_material/nodes/adjust_hsv.gd @@ -0,0 +1,28 @@ +tool +extends "res://addons/procedural_material/node_base.gd" + +var hue +var saturation +var value + +func _ready(): + initialize_properties([ $HBoxContainer1/hue, $HBoxContainer2/saturation, $HBoxContainer3/value ]) + +func _get_shader_code(uv, output = 0): + var rv = { defs="", code="" } + var src = get_source() + var src_code = { defs="", code="", rgb="vec3(0.0)" } + if src == null: + return rv + src_code = src.get_shader_code(uv) + if generated_variants.empty(): + rv.defs = src_code.defs; + rv.defs += "vec3 %s_rgb(vec3 c) { vec3 hsv = rgb2hsv(c); return hsv2rgb(vec3(fract(hsv.x+%.9f), clamp(hsv.y*%.9f, 0.0, 1.0), clamp(hsv.z*%.9f, 0.0, 1.0))); }\n" % [ name, hue, saturation, value ] + var variant_index = generated_variants.find(uv) + if variant_index == -1: + variant_index = generated_variants.size() + generated_variants.append(uv) + rv.code = src_code.code + rv.code += "vec3 %s_%d_rgb = %s_rgb(%s);\n" % [ name, variant_index, name, src_code.rgb ] + rv.rgb = "%s_%d_rgb" % [ name, variant_index ] + return rv diff --git a/addons/procedural_material/nodes/adjust_hsv.tscn b/addons/procedural_material/nodes/adjust_hsv.tscn new file mode 100644 index 0000000..073fef8 --- /dev/null +++ b/addons/procedural_material/nodes/adjust_hsv.tscn @@ -0,0 +1,256 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://addons/procedural_material/nodes/adjust_hsv.gd" type="Script" id=1] + +[sub_resource type="Theme" id=1] + + +[node name="AdjustHSV" type="GraphNode" index="0"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_top = 1.0 +margin_right = 111.0 +margin_bottom = 74.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 1 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 +theme = SubResource( 1 ) +title = "AdjustHSV" +offset = Vector2( 0, 0 ) +show_close = true +resizable = false +selected = false +comment = false +overlay = 0 +slot/0/left_enabled = true +slot/0/left_type = 0 +slot/0/left_color = Color( 0.498039, 0.498039, 1, 1 ) +slot/0/right_enabled = true +slot/0/right_type = 0 +slot/0/right_color = Color( 0.494118, 0.494118, 1, 1 ) +slot/1/left_enabled = false +slot/1/left_type = 0 +slot/1/left_color = Color( 0.756863, 0.756863, 0.756863, 1 ) +slot/1/right_enabled = false +slot/1/right_type = 0 +slot/1/right_color = Color( 0.756863, 0.756863, 0.756863, 1 ) +slot/2/left_enabled = false +slot/2/left_type = 0 +slot/2/left_color = Color( 0.756863, 0.756863, 0.756863, 1 ) +slot/2/right_enabled = false +slot/2/right_type = 0 +slot/2/right_color = Color( 0.756863, 0.756863, 0.756863, 1 ) +script = ExtResource( 1 ) +_sections_unfolded = [ "Theme", "slot", "slot/0", "slot/1", "slot/2" ] + +[node name="HBoxContainer1" type="HBoxContainer" parent="." index="0"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 16.0 +margin_top = 24.0 +margin_right = 184.0 +margin_bottom = 40.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 1 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 +alignment = 0 + +[node name="Label" type="Label" parent="HBoxContainer1" index="0"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_top = 1.0 +margin_right = 64.0 +margin_bottom = 15.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 3 +size_flags_vertical = 4 +text = "Hue" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 + +[node name="hue" type="HSlider" parent="HBoxContainer1" index="1"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 68.0 +margin_right = 168.0 +margin_bottom = 16.0 +rect_min_size = Vector2( 100, 0 ) +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +focus_mode = 2 +mouse_filter = 0 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 0 +min_value = -0.5 +max_value = 0.5 +step = 0.02 +page = 0.0 +value = 0.0 +exp_edit = false +rounded = false +editable = true +tick_count = 0 +ticks_on_borders = false +focus_mode = 2 +_sections_unfolded = [ "Rect" ] + +[node name="HBoxContainer2" type="HBoxContainer" parent="." index="1"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 16.0 +margin_top = 40.0 +margin_right = 184.0 +margin_bottom = 56.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 1 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 +alignment = 0 + +[node name="Label" type="Label" parent="HBoxContainer2" index="0"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_top = 1.0 +margin_right = 64.0 +margin_bottom = 15.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 3 +size_flags_vertical = 4 +text = "Saturation" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 + +[node name="saturation" type="HSlider" parent="HBoxContainer2" index="1"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 68.0 +margin_right = 168.0 +margin_bottom = 16.0 +rect_min_size = Vector2( 100, 0 ) +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +focus_mode = 2 +mouse_filter = 0 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 0 +min_value = 0.0 +max_value = 2.0 +step = 0.1 +page = 0.0 +value = 1.0 +exp_edit = false +rounded = false +editable = true +tick_count = 0 +ticks_on_borders = false +focus_mode = 2 +_sections_unfolded = [ "Rect" ] + +[node name="HBoxContainer3" type="HBoxContainer" parent="." index="2"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 16.0 +margin_top = 57.0 +margin_right = 184.0 +margin_bottom = 73.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 1 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 1 +alignment = 0 + +[node name="Label" type="Label" parent="HBoxContainer3" index="0"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_top = 1.0 +margin_right = 64.0 +margin_bottom = 15.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 3 +size_flags_vertical = 4 +text = "Value" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 + +[node name="value" type="HSlider" parent="HBoxContainer3" index="1"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 68.0 +margin_right = 168.0 +margin_bottom = 16.0 +rect_min_size = Vector2( 100, 0 ) +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +focus_mode = 2 +mouse_filter = 0 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 0 +min_value = 0.0 +max_value = 2.0 +step = 0.1 +page = 0.0 +value = 1.0 +exp_edit = false +rounded = false +editable = true +tick_count = 0 +ticks_on_borders = false +focus_mode = 2 +_sections_unfolded = [ "Rect" ] + +