diff --git a/addons/procedural_material/blend.gd b/addons/procedural_material/blend.gd new file mode 100644 index 0000000..dbdc3a9 --- /dev/null +++ b/addons/procedural_material/blend.gd @@ -0,0 +1,38 @@ +tool +extends "res://addons/procedural_material/node_base.gd" + +var amount = 0.0 + +func _ready(): + set_slot(0, true, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1)) + set_slot(1, true, 0, Color(0.5, 0.5, 1), false, 0, Color(0.5, 0.5, 1)) + set_slot(2, true, 0, Color(0.5, 0.5, 1), false, 0, Color(0.5, 0.5, 1)) + initialize_properties([ $amount ]) + +func color_to_string(c): + return "vec3("+str(c.r)+","+str(c.g)+","+str(c.b)+")" + +func get_shader_code(uv): + var rv = { defs="", code="", uv=null, rgb=null, f=null } + var src0 = get_source(0) + var src1 = get_source(1) + var src2 = get_source(2) + if src0 == null or src1 == null: + return rv + var src0_code = src0.get_shader_code(uv) + var src1_code = src1.get_shader_code(uv) + var src2_code = { defs="", code="" } + var amount_str = str(amount) + if src2 != null: + src2_code = src2.get_shader_code(uv) + amount_str = str(src2_code.f) + if !generated: + rv.defs = src0_code.defs+src1_code.defs+src2_code.defs + rv.code = src0_code.code+src1_code.code+src2_code.code + rv.code += "vec3 "+name+"_rgb = mix("+get_source_rgb(src0_code)+", "+get_source_rgb(src1_code)+", "+amount_str+");\n" + generated = true + rv.rgb = name+"_rgb" + return rv + +func _get_state_variables(): + return [ "amount" ] diff --git a/addons/procedural_material/blend.tscn b/addons/procedural_material/blend.tscn new file mode 100644 index 0000000..f763828 --- /dev/null +++ b/addons/procedural_material/blend.tscn @@ -0,0 +1,122 @@ +[gd_scene load_steps=3 format=2] + +[ext_resource path="res://addons/procedural_material/blend.gd" type="Script" id=1] + +[sub_resource type="Theme" id=1] + + +[node name="Blend" type="GraphNode" index="0"] + +anchor_left = 0.0 +anchor_top = 0.0 +anchor_right = 0.0 +anchor_bottom = 0.0 +margin_left = 618.0 +margin_top = 148.0 +margin_right = 751.0 +margin_bottom = 310.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 = "Blend" +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.5, 0.5, 1, 1 ) +slot/0/right_enabled = true +slot/0/right_type = 0 +slot/0/right_color = Color( 0.5, 0.5, 1, 1 ) +slot/1/left_enabled = false +slot/1/left_type = 0 +slot/1/left_color = Color( 1, 1, 1, 1 ) +slot/1/right_enabled = false +slot/1/right_type = 0 +slot/1/right_color = Color( 1, 1, 1, 1 ) +slot/2/left_enabled = false +slot/2/left_type = 0 +slot/2/left_color = Color( 1, 1, 1, 1 ) +slot/2/right_enabled = false +slot/2/right_type = 0 +slot/2/right_color = Color( 1, 1, 1, 1 ) +script = ExtResource( 1 ) +_sections_unfolded = [ "Theme" ] + +[node name="Label1" type="Label" 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 = 117.0 +margin_bottom = 38.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 4 +text = "Source 1" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 + +[node name="Label2" type="Label" 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 = 38.0 +margin_right = 117.0 +margin_bottom = 52.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +mouse_filter = 2 +mouse_default_cursor_shape = 0 +size_flags_horizontal = 1 +size_flags_vertical = 4 +text = "Source 2" +percent_visible = 1.0 +lines_skipped = 0 +max_lines_visible = -1 + +[node name="amount" type="LineEdit" 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 = 53.0 +margin_right = 117.0 +margin_bottom = 77.0 +rect_pivot_offset = Vector2( 0, 0 ) +rect_clip_content = false +focus_mode = 2 +mouse_filter = 0 +mouse_default_cursor_shape = 1 +size_flags_horizontal = 1 +size_flags_vertical = 1 +text = "0.5" +focus_mode = 2 +context_menu_enabled = true +placeholder_alpha = 0.6 +caret_blink = false +caret_blink_speed = 0.65 +caret_position = 0 + +[connection signal="close_request" from="." to="." method="queue_free"] + + diff --git a/addons/procedural_material/boolean.gd b/addons/procedural_material/boolean.gd deleted file mode 100644 index 5eb41d0..0000000 --- a/addons/procedural_material/boolean.gd +++ /dev/null @@ -1,21 +0,0 @@ -tool -extends "res://addons/procedural_material/node_base.gd" - -func _ready(): - set_slot(0, true, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1)) - set_slot(1, true, 0, Color(0.5, 0.5, 1), false, 0, Color(0.5, 0.5, 1)) - -func get_shader_code(uv): - var rv = { defs="", code="", uv=null, rgb=null, f=null } - var src0 = get_source(0) - var src1 = get_source(1) - if src0 == null || src1 == null: - return rv - var src0_code = src0.get_shader_code(uv) - var src1_code = src1.get_shader_code(uv) - if !generated: - rv.defs = src0_code.defs+src1_code.defs - rv.code = "float "+name+"_f = "+src0_code.f+"+"+src1_code.f+";\n" - generated = true - rv.f = name+"_f" - return rv diff --git a/addons/procedural_material/bricks.gd b/addons/procedural_material/bricks.gd index 3998d60..586b836 100644 --- a/addons/procedural_material/bricks.gd +++ b/addons/procedural_material/bricks.gd @@ -12,11 +12,15 @@ func _ready(): initialize_properties([ $GridContainer/rows, $GridContainer/columns, $GridContainer/row_offset, $GridContainer/mortar, $GridContainer/bevel ]) func get_shader_code(uv): - var rv = { defs="", code="", rgb=null, f=null } - if !generated: - rv.defs = "float "+name+"_f(vec2 uv) { return bricks(uv, vec2("+str(rows)+", "+str(columns)+"), "+str(row_offset)+", "+str(mortar)+", "+str(bevel)+"); }\n" - generated = true - rv.f = name+"_f("+uv+")" + var rv = { defs="", code="" } + if generated_variants.empty(): + rv.defs = "float "+name+"_f(vec2 uv) { return bricks(uv, vec2("+str(rows)+", "+str(columns)+"), "+str(row_offset)+", "+str(mortar)+", "+str(max(0.001, bevel))+"); }\n" + var variant_index = generated_variants.find(uv) + if variant_index == -1: + variant_index = generated_variants.size() + generated_variants.append(uv) + rv.code = "float "+name+"_"+str(variant_index)+"_f = "+name+"_f("+uv+");\n" + rv.f = name+"_"+str(variant_index)+"_f" return rv func _get_state_variables(): diff --git a/addons/procedural_material/bricks.tscn b/addons/procedural_material/bricks.tscn index 2ea26dd..0e69e02 100644 --- a/addons/procedural_material/bricks.tscn +++ b/addons/procedural_material/bricks.tscn @@ -11,10 +11,9 @@ anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 -margin_left = 251.0 -margin_top = 121.0 -margin_right = 405.0 -margin_bottom = 286.0 +margin_left = 1.0 +margin_right = 155.0 +margin_bottom = 165.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 diff --git a/addons/procedural_material/colorize.gd b/addons/procedural_material/colorize.gd new file mode 100644 index 0000000..6076d45 --- /dev/null +++ b/addons/procedural_material/colorize.gd @@ -0,0 +1,29 @@ +tool +extends "res://addons/procedural_material/node_base.gd" + +var color0 +var color1 + +func _ready(): + set_slot(0, true, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1)) + initialize_properties([ $color0, $color1 ]) + +func color_to_string(c): + return "vec3("+str(c.r)+","+str(c.g)+","+str(c.b)+")" + +func get_shader_code(uv): + var rv = { defs="", code="", uv=null, rgb=null, f=null } + var src = get_source() + if src == null: + return rv + var src_code = src.get_shader_code(uv) + if !generated: + rv.defs = src_code.defs; + rv.code = src_code.code+"vec3 "+name+"_rgb = mix("+color_to_string(color0)+", "+color_to_string(color1)+", "+src_code.f+");\n" + generated = true + rv.f = src_code.f + rv.rgb = name+"_rgb" + return rv + +func _get_state_variables(): + return [ "color0", "color1" ] diff --git a/addons/procedural_material/boolean.tscn b/addons/procedural_material/colorize.tscn similarity index 70% rename from addons/procedural_material/boolean.tscn rename to addons/procedural_material/colorize.tscn index 22d5b44..2723f8c 100644 --- a/addons/procedural_material/boolean.tscn +++ b/addons/procedural_material/colorize.tscn @@ -1,20 +1,20 @@ [gd_scene load_steps=3 format=2] -[ext_resource path="res://addons/procedural_material/boolean.gd" type="Script" id=1] +[ext_resource path="res://addons/procedural_material/colorize.gd" type="Script" id=1] [sub_resource type="Theme" id=1] -[node name="Boolean" type="GraphNode" index="0"] +[node name="Colorize" type="GraphNode" index="0"] anchor_left = 0.0 anchor_top = 0.0 anchor_right = 0.0 anchor_bottom = 0.0 -margin_left = 329.0 -margin_top = 117.0 -margin_right = 462.0 -margin_bottom = 279.0 +margin_left = 618.0 +margin_top = 148.0 +margin_right = 751.0 +margin_bottom = 310.0 rect_pivot_offset = Vector2( 0, 0 ) rect_clip_content = false mouse_filter = 1 @@ -22,7 +22,7 @@ mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 theme = SubResource( 1 ) -title = "Boolean" +title = "Colorize" offset = Vector2( 0, 0 ) show_close = true resizable = false @@ -35,16 +35,16 @@ slot/0/left_color = Color( 0.5, 0.5, 1, 1 ) slot/0/right_enabled = true slot/0/right_type = 0 slot/0/right_color = Color( 0.5, 0.5, 1, 1 ) -slot/1/left_enabled = true +slot/1/left_enabled = false slot/1/left_type = 0 -slot/1/left_color = Color( 0.5, 0.5, 1, 1 ) +slot/1/left_color = Color( 1, 1, 1, 1 ) slot/1/right_enabled = false slot/1/right_type = 0 -slot/1/right_color = Color( 0.5, 0.5, 1, 1 ) +slot/1/right_color = Color( 1, 1, 1, 1 ) script = ExtResource( 1 ) _sections_unfolded = [ "Theme" ] -[node name="OptionButton" type="OptionButton" parent="." index="0"] +[node name="color0" type="ColorPickerButton" parent="." index="0"] anchor_left = 0.0 anchor_top = 0.0 @@ -62,16 +62,17 @@ mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 toggle_mode = false -action_mode = 0 enabled_focus_mode = 2 shortcut = null group = null +text = "0" flat = false -align = 0 -items = [ ] -selected = -1 +align = 1 +color = Color( 0, 0, 0, 1 ) +edit_alpha = true +_sections_unfolded = [ "Caret", "Placeholder" ] -[node name="OptionButton2" type="OptionButton" parent="." index="1"] +[node name="color1" type="ColorPickerButton" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 @@ -89,14 +90,15 @@ mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 toggle_mode = false -action_mode = 0 enabled_focus_mode = 2 shortcut = null group = null +text = "0" flat = false -align = 0 -items = [ ] -selected = -1 +align = 1 +color = Color( 1, 1, 1, 1 ) +edit_alpha = true +_sections_unfolded = [ "Caret", "Placeholder" ] [connection signal="close_request" from="." to="." method="queue_free"] diff --git a/addons/procedural_material/iqnoise.gd b/addons/procedural_material/iqnoise.gd index 5671351..3d42df3 100644 --- a/addons/procedural_material/iqnoise.gd +++ b/addons/procedural_material/iqnoise.gd @@ -10,7 +10,7 @@ func _ready(): initialize_properties([ $GridContainer/subdivide, $GridContainer/u, $GridContainer/v ]) func get_shader_code(uv): - var rv = { defs="", code="", rgb=null, f=null } + var rv = { defs="", code="" } if !generated: rv.defs = "float "+name+"_f(vec2 uv) { return iqnoise(uv, "+str(subdivide)+", "+str(u)+", "+str(v)+"); }\n" generated = true diff --git a/addons/procedural_material/iqnoise.tscn b/addons/procedural_material/iqnoise.tscn index a759705..bc1286c 100644 --- a/addons/procedural_material/iqnoise.tscn +++ b/addons/procedural_material/iqnoise.tscn @@ -92,7 +92,7 @@ mouse_filter = 0 mouse_default_cursor_shape = 1 size_flags_horizontal = 1 size_flags_vertical = 1 -text = "3" +text = "8" focus_mode = 2 context_menu_enabled = true placeholder_alpha = 0.6 diff --git a/addons/procedural_material/material.gd b/addons/procedural_material/material.gd index 2103bfa..efaea42 100644 --- a/addons/procedural_material/material.gd +++ b/addons/procedural_material/material.gd @@ -14,12 +14,11 @@ func get_shader_code(uv): var src_code = src.get_shader_code("UV") rv.code += src_code.defs rv.code += "void fragment() {\n" - rv.code += src_code.code+"\n" - if src_code.rgb != null: - rv.code += "vec3 "+name+"_rgb = "+src_code.rgb+"\n" - rv.code += "COLOR = vec4("+name+"_rgb.r, "+name+"_rgb.g, "+name+"_rgb.b, 1.0);" - elif src_code.f != null: - rv.code += "float "+name+"_f = "+src_code.f+";\n" - rv.code += "COLOR = vec4("+name+"_f, "+name+"_f, "+name+"_f, 1.0);" - rv.code += "\n}\n" - return rv \ No newline at end of file + rv.code += src_code.code + rv.code += "vec3 "+name+"_rgb = "+get_source_rgb(src_code)+";\n" + rv.code += "COLOR = vec4("+name+"_rgb, 1.0);\n" + rv.code += "}\n" + return rv + +func _get_state_variables(): + return [ ] diff --git a/addons/procedural_material/node_base.gd b/addons/procedural_material/node_base.gd index 7a29335..d430d95 100644 --- a/addons/procedural_material/node_base.gd +++ b/addons/procedural_material/node_base.gd @@ -2,20 +2,38 @@ tool extends GraphNode var generated = false +var generated_variants = [] + +var property_widgets = [] func _ready(): - pass + print("ready: "+name) func initialize_properties(object_list): + property_widgets = object_list for o in object_list: if o is LineEdit: set(o.name, float(o.text)) o.connect("text_changed", self, "_on_text_changed", [ o.name ]) + elif o is ColorPickerButton: + set(o.name, o.color) + o.connect("color_changed", self, "_on_color_changed", [ o.name ]) + +func update_property_widgets(): + for o in property_widgets: + if o is LineEdit: + o.text = str(get(o.name)) + elif o is ColorPickerButton: + o.color = get(o.name) func _on_text_changed(new_text, variable): set(variable, float(new_text)) get_parent().get_parent().generate_shader() +func _on_color_changed(new_color, variable): + set(variable, new_color) + get_parent().get_parent().generate_shader() + func get_source(index = 0): for c in get_parent().get_children(): if c != self && c is GraphNode: @@ -23,6 +41,43 @@ func get_source(index = 0): return c return null +func get_source_rgb(source): + var rv + if source.has("rgb"): + rv = source.rgb + elif source.has("f"): + rv = "vec3("+source.f+")" + else: + rv = "***error***" + return rv + func queue_free(): get_parent().remove_node(self.name) .queue_free() + +func serialize_element(e): + if typeof(e) == TYPE_COLOR: + return { type= "Color", r=e.r, g=e.g, b=e.b, a=e.a } + return e + +func deserialize_element(e): + if typeof(e) == TYPE_DICTIONARY: + if e.type == "Color": + return Color(e.r, e.g, e.b, e.a) + return e + +func serialize(): + var type = get_script().resource_path + type = type.right(type.find_last("/")+1) + type = type.left(type.find_last(".")) + var data = { name=name, type=type } + for v in _get_state_variables(): + data[v] = serialize_element(get(v)) + return data + +func deserialize(data): + print("deserialize: "+name) + for v in _get_state_variables(): + set(v, deserialize_element(data[v])) + print(" "+v+" = "+str(deserialize_element(data[v]))) + update_property_widgets() diff --git a/addons/procedural_material/perlin.gd b/addons/procedural_material/perlin.gd index e3422a1..ed767c8 100644 --- a/addons/procedural_material/perlin.gd +++ b/addons/procedural_material/perlin.gd @@ -9,7 +9,7 @@ func _ready(): initialize_properties([ $GridContainer/iterations, $GridContainer/turbulence ]) func get_shader_code(uv): - var rv = { defs="", code="", rgb=null, f=null } + var rv = { defs="", code="" } if !generated: rv.defs = "float "+name+"_f(vec2 uv) { return perlin(uv, "+str(iterations)+", "+str(turbulence)+"); }\n" generated = true diff --git a/addons/procedural_material/pm_editor.gd b/addons/procedural_material/pm_editor.gd index b903121..fb782c9 100644 --- a/addons/procedural_material/pm_editor.gd +++ b/addons/procedural_material/pm_editor.gd @@ -4,12 +4,16 @@ extends Container var popup_position = Vector2(0, 0) const MENU = [ + { command="load_texture", description="Load texture" }, + { command="save_texture", description="Save texture" }, { name="sine", description="Sine" }, - { name="boolean", description="Boolean" }, { name="bricks", description="Bricks" }, { name="iqnoise", description="IQ Noise" }, { name="perlin", description="Perlin noise" }, - { name="transform", description="Transform" } + { name="boolean", description="Boolean" }, + { name="transform", description="Transform" }, + { name="colorize", description="Colorize" }, + { name="blend", description="Blend" } ] func _ready(): @@ -24,11 +28,14 @@ func _on_GraphEdit_popup_request(position): func _on_PopupMenu_id_pressed(id): var node_type = null - node_type = load("res://addons/procedural_material/"+MENU[id].name+".tscn") - if node_type != null: - var node = node_type.instance() - $GraphEdit.add_child(node) - node.set_begin(popup_position) + if MENU[id].has("command"): + call(MENU[id].command) + elif MENU[id].has("name"): + node_type = load("res://addons/procedural_material/"+MENU[id].name+".tscn") + if node_type != null: + var node = node_type.instance() + $GraphEdit.add_child(node) + node.set_begin(popup_position) func _on_GraphEdit_connection_request(from, from_slot, to, to_slot): var disconnect = $GraphEdit.get_source(to, to_slot) @@ -37,6 +44,57 @@ func _on_GraphEdit_connection_request(from, from_slot, to, to_slot): $GraphEdit.connect_node(from, from_slot, to, to_slot) generate_shader(); +func load_texture(): + var dialog = EditorFileDialog.new() + add_child(dialog) + dialog.access = EditorFileDialog.ACCESS_FILESYSTEM + dialog.mode = EditorFileDialog.MODE_OPEN_FILE + dialog.add_filter("*.ptex;Procedural texture file") + dialog.connect("file_selected", self, "load_file") + dialog.popup_centered() + +func load_file(filename): + var file = File.new() + if file.open(filename, File.READ) != OK: + return + var data = file.get_var() + file.close() + $GraphEdit.clear_connections() + for c in $GraphEdit.get_children(): + if c is GraphNode: + $GraphEdit.remove_child(c) + c.free() + for n in data.nodes: + var node_type = load("res://addons/procedural_material/"+n.type+".tscn") + if node_type != null: + var node = node_type.instance() + node.name = n.name + $GraphEdit.add_child(node) + node.deserialize(n) + for c in data.connections: + $GraphEdit.connect_node(c.from, c.from_port, c.to, c.to_port) + generate_shader() + +func save_texture(): + var dialog = EditorFileDialog.new() + add_child(dialog) + dialog.access = EditorFileDialog.ACCESS_FILESYSTEM + dialog.mode = EditorFileDialog.MODE_SAVE_FILE + dialog.add_filter("*.ptex;Procedural texture file") + dialog.connect("file_selected", self, "save_file") + dialog.popup_centered() + +func save_file(filename): + var data = { nodes = [] } + for c in $GraphEdit.get_children(): + if c is GraphNode: + data.nodes.append(c.serialize()) + data.connections = $GraphEdit.get_connection_list() + var file = File.new() + if file.open(filename, File.WRITE) == OK: + file.store_var(data) + file.close() + func generate_shader(): var code = "" var file = File.new() @@ -47,8 +105,9 @@ func generate_shader(): for c in $GraphEdit.get_children(): if c is GraphNode: c.generated = false + c.generated_variants = [] var shader_code = $GraphEdit/Material.get_shader_code("UV") + print("GENERATED SHADER:\n"+shader_code.code) code += shader_code.code - #print(code) $Preview.material.shader.set_code(code) diff --git a/addons/procedural_material/pm_editor.tscn b/addons/procedural_material/pm_editor.tscn index ee3eaad..a24c558 100644 --- a/addons/procedural_material/pm_editor.tscn +++ b/addons/procedural_material/pm_editor.tscn @@ -49,7 +49,7 @@ float bricks(vec2 uv, vec2 count, float offset, float mortar, float bevel) { float slope_y = 1.0/(bevel*count.y); float f3 = fract_y*slope_y-off; float f4 = (1.0-fract_y)*slope_y-off; - return min(min(f1, f2), min(f3, f4)); + return max(0.0, min(1.0, min(min(f1, f2), min(f3, f4)))); } float colored_bricks(vec2 uv, vec2 count, float offset) { @@ -100,11 +100,12 @@ float perlin(vec2 uv, int iterations, float turbulence) { return f/m; } -float Sine_f(vec2 uv) { return sine(uv, 1, 1); } +float Bricks_f(vec2 uv) { return bricks(uv, vec2(4, 8), 0.5, 0.1, 0.1); } void fragment() { - -float Material_f = Sine_f(UV); -COLOR = vec4(Material_f, Material_f, Material_f, 1.0); +float Bricks_0_f = Bricks_f(UV); +vec3 Colorize_rgb = mix(vec3(0.882813,0.134491,0.134491), vec3(0.882813,0.446795,0.062073), Bricks_0_f); +vec3 Material_rgb = Colorize_rgb; +COLOR = vec4(Material_rgb, 1.0); } " _sections_unfolded = [ "Resource" ] @@ -159,7 +160,7 @@ margin_left = 0.0 margin_top = 0.0 margin_right = 84.0 margin_bottom = 43.0 -_sections_unfolded = [ "Anchor", "Margin", "Mouse", "slot" ] +_sections_unfolded = [ "Anchor", "Margin", "Mouse", "Theme", "slot" ] [node name="PopupMenu" type="PopupMenu" parent="GraphEdit" index="1"] @@ -180,7 +181,7 @@ mouse_default_cursor_shape = 0 size_flags_horizontal = 1 size_flags_vertical = 1 popup_exclusive = false -items = [ "Material", null, 0, false, false, 0, 0, null, "", false, "Sine", null, 0, false, false, 1, 0, null, "", false, "Boolean", null, 0, false, false, 2, 0, null, "", false, "Bricks", null, 0, false, false, 3, 0, null, "", false, "IQ Noise", null, 0, false, false, 4, 0, null, "", false, "Perlin noise", null, 0, false, false, 5, 0, null, "", false, "Transform", null, 0, false, false, 6, 0, null, "", false ] +items = [ "Load texture", null, 0, false, false, 0, 0, null, "", false, "Save texture", null, 0, false, false, 1, 0, null, "", false, "Sine", null, 0, false, false, 2, 0, null, "", false, "Bricks", null, 0, false, false, 3, 0, null, "", false, "IQ Noise", null, 0, false, false, 4, 0, null, "", false, "Perlin noise", null, 0, false, false, 5, 0, null, "", false, "Boolean", null, 0, false, false, 6, 0, null, "", false, "Transform", null, 0, false, false, 7, 0, null, "", false, "Colorize", null, 0, false, false, 8, 0, null, "", false, "Blend", null, 0, false, false, 9, 0, null, "", false ] hide_on_state_item_selection = false _sections_unfolded = [ "Rect" ] diff --git a/addons/procedural_material/shader_header.txt b/addons/procedural_material/shader_header.txt index b22a0dc..a2ff33d 100644 --- a/addons/procedural_material/shader_header.txt +++ b/addons/procedural_material/shader_header.txt @@ -41,7 +41,7 @@ float bricks(vec2 uv, vec2 count, float offset, float mortar, float bevel) { float slope_y = 1.0/(bevel*count.y); float f3 = fract_y*slope_y-off; float f4 = (1.0-fract_y)*slope_y-off; - return min(min(f1, f2), min(f3, f4)); + return max(0.0, min(1.0, min(min(f1, f2), min(f3, f4)))); } float colored_bricks(vec2 uv, vec2 count, float offset) { diff --git a/addons/procedural_material/sine.gd b/addons/procedural_material/sine.gd index 154b54a..1d73db1 100644 --- a/addons/procedural_material/sine.gd +++ b/addons/procedural_material/sine.gd @@ -6,6 +6,7 @@ var sharpness = 1.0 func _ready(): set_slot(0, false, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1)) + initialize_properties([ $waves, $sharpness ]) func get_shader_code(uv): var rv = { defs="", code="", rgb=null, f=null } @@ -22,3 +23,6 @@ func _on_Count_text_changed(new_text): func _on_Sharpness_text_changed(new_text): sharpness = float(new_text) get_parent().get_parent().generate_shader() + +func _get_state_variables(): + return [ "waves", "sharpness" ] diff --git a/addons/procedural_material/sine.tscn b/addons/procedural_material/sine.tscn index 471295b..31621a5 100644 --- a/addons/procedural_material/sine.tscn +++ b/addons/procedural_material/sine.tscn @@ -43,7 +43,7 @@ slot/1/right_color = Color( 1, 1, 1, 1 ) script = ExtResource( 1 ) _sections_unfolded = [ "Theme" ] -[node name="Count" type="LineEdit" parent="." index="0"] +[node name="waves" type="LineEdit" parent="." index="0"] anchor_left = 0.0 anchor_top = 0.0 @@ -69,7 +69,7 @@ caret_blink_speed = 0.65 caret_position = 0 _sections_unfolded = [ "Caret", "Placeholder" ] -[node name="Sharpness" type="LineEdit" parent="." index="1"] +[node name="sharpness" type="LineEdit" parent="." index="1"] anchor_left = 0.0 anchor_top = 0.0 @@ -97,8 +97,8 @@ _sections_unfolded = [ "Caret", "Placeholder" ] [connection signal="close_request" from="." to="." method="queue_free"] -[connection signal="text_changed" from="Count" to="." method="_on_Count_text_changed"] +[connection signal="text_changed" from="waves" to="." method="_on_Count_text_changed"] -[connection signal="text_changed" from="Sharpness" to="." method="_on_Sharpness_text_changed"] +[connection signal="text_changed" from="sharpness" to="." method="_on_Sharpness_text_changed"] diff --git a/addons/procedural_material/transform.gd b/addons/procedural_material/transform.gd index 6b379a7..6910457 100644 --- a/addons/procedural_material/transform.gd +++ b/addons/procedural_material/transform.gd @@ -5,9 +5,10 @@ var angle = 0.0 func _ready(): set_slot(0, true, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1)) + initialize_properties([ $rotate ]) func get_shader_code(uv): - var rv = { defs="", code="", uv=null, rgb=null, f=null } + var rv = { defs="", code="", uv=null } var src = get_source() if src == null: return rv @@ -15,9 +16,12 @@ func get_shader_code(uv): var src_code = src.get_shader_code(rv.uv) if !generated: rv.defs = src_code.defs+"vec2 "+name+"_uv(vec2 uv) { return rotate(uv, "+str(angle)+"); }\n" + rv.code = src_code.code; generated = true - rv.f = src_code.f - rv.rgb = src_code.rgb + if src_code.has("f"): + rv.f = src_code.f + if src_code.has("rgb"): + rv.rgb = src_code.rgb return rv func _on_Rotate_text_changed(new_text): diff --git a/addons/procedural_material/transform.tscn b/addons/procedural_material/transform.tscn index 4051a4d..8142a38 100644 --- a/addons/procedural_material/transform.tscn +++ b/addons/procedural_material/transform.tscn @@ -29,7 +29,7 @@ resizable = false selected = false comment = false overlay = 0 -slot/0/left_enabled = false +slot/0/left_enabled = true slot/0/left_type = 0 slot/0/left_color = Color( 0.5, 0.5, 1, 1 ) slot/0/right_enabled = true @@ -38,7 +38,7 @@ slot/0/right_color = Color( 0.5, 0.5, 1, 1 ) script = ExtResource( 1 ) _sections_unfolded = [ "Theme" ] -[node name="Rotate" type="LineEdit" parent="." index="0"] +[node name="rotate" type="LineEdit" parent="." index="0"] anchor_left = 0.0 anchor_top = 0.0 @@ -66,6 +66,6 @@ _sections_unfolded = [ "Caret", "Placeholder" ] [connection signal="close_request" from="." to="." method="queue_free"] -[connection signal="text_changed" from="Rotate" to="." method="_on_Rotate_text_changed"] +[connection signal="text_changed" from="rotate" to="." method="_on_Rotate_text_changed"] diff --git a/default_env.tres b/default_env.tres index 98f26a7..ad86b72 100644 --- a/default_env.tres +++ b/default_env.tres @@ -1,5 +1,101 @@ [gd_resource type="Environment" load_steps=2 format=2] + [sub_resource type="ProceduralSky" id=1] + +radiance_size = 4 +sky_top_color = Color( 0.0470588, 0.454902, 0.976471, 1 ) +sky_horizon_color = Color( 0.556863, 0.823529, 0.909804, 1 ) +sky_curve = 0.25 +sky_energy = 1.0 +ground_bottom_color = Color( 0.101961, 0.145098, 0.188235, 1 ) +ground_horizon_color = Color( 0.482353, 0.788235, 0.952941, 1 ) +ground_curve = 0.01 +ground_energy = 1.0 +sun_color = Color( 1, 1, 1, 1 ) +sun_latitude = 35.0 +sun_longitude = 0.0 +sun_angle_min = 1.0 +sun_angle_max = 100.0 +sun_curve = 0.05 +sun_energy = 16.0 +texture_size = 2 + [resource] + background_mode = 2 background_sky = SubResource( 1 ) +background_sky_custom_fov = 0.0 +background_color = Color( 0, 0, 0, 1 ) +background_energy = 1.0 +background_canvas_max_layer = 0 +ambient_light_color = Color( 0, 0, 0, 1 ) +ambient_light_energy = 1.0 +ambient_light_sky_contribution = 1.0 +fog_enabled = false +fog_color = Color( 0.5, 0.6, 0.7, 1 ) +fog_sun_color = Color( 1, 0.9, 0.7, 1 ) +fog_sun_amount = 0.0 +fog_depth_enabled = true +fog_depth_begin = 10.0 +fog_depth_curve = 1.0 +fog_transmit_enabled = false +fog_transmit_curve = 1.0 +fog_height_enabled = false +fog_height_min = 0.0 +fog_height_max = 100.0 +fog_height_curve = 1.0 +tonemap_mode = 0 +tonemap_exposure = 1.0 +tonemap_white = 1.0 +auto_exposure_enabled = false +auto_exposure_scale = 0.4 +auto_exposure_min_luma = 0.05 +auto_exposure_max_luma = 8.0 +auto_exposure_speed = 0.5 +ss_reflections_enabled = false +ss_reflections_max_steps = 64 +ss_reflections_fade_in = 0.15 +ss_reflections_fade_out = 2.0 +ss_reflections_depth_tolerance = 0.2 +ss_reflections_roughness = true +ssao_enabled = false +ssao_radius = 1.0 +ssao_intensity = 1.0 +ssao_radius2 = 0.0 +ssao_intensity2 = 1.0 +ssao_bias = 0.01 +ssao_light_affect = 0.0 +ssao_color = Color( 0, 0, 0, 1 ) +ssao_quality = 0 +ssao_blur = 3 +ssao_edge_sharpness = 4.0 +dof_blur_far_enabled = false +dof_blur_far_distance = 10.0 +dof_blur_far_transition = 5.0 +dof_blur_far_amount = 0.1 +dof_blur_far_quality = 1 +dof_blur_near_enabled = false +dof_blur_near_distance = 2.0 +dof_blur_near_transition = 1.0 +dof_blur_near_amount = 0.1 +dof_blur_near_quality = 1 +glow_enabled = false +glow_levels/1 = false +glow_levels/2 = false +glow_levels/3 = true +glow_levels/4 = false +glow_levels/5 = true +glow_levels/6 = false +glow_levels/7 = false +glow_intensity = 0.8 +glow_strength = 1.0 +glow_bloom = 0.0 +glow_blend_mode = 2 +glow_hdr_threshold = 1.0 +glow_hdr_scale = 2.0 +glow_bicubic_upscale = false +adjustment_enabled = false +adjustment_brightness = 1.0 +adjustment_contrast = 1.0 +adjustment_saturation = 1.0 + diff --git a/examples/bricks.ptex b/examples/bricks.ptex new file mode 100644 index 0000000..81f0368 Binary files /dev/null and b/examples/bricks.ptex differ diff --git a/project.godot b/project.godot index 9dcf3ce..cf597f6 100644 --- a/project.godot +++ b/project.godot @@ -11,6 +11,7 @@ config_version=3 [application] config/name="Procedural textures addon" +run/main_scene="res://addons/procedural_material/pm_editor.tscn" config/icon="res://icon.png" [editor_plugins]