From 825d98e0feb616a39c985c440ef560545c5ef443 Mon Sep 17 00:00:00 2001 From: RodZill4 Date: Thu, 10 Oct 2019 07:42:38 +0200 Subject: [PATCH] Added main code section to shader generators --- addons/material_maker/engine/gen_context.gd | 8 ++-- addons/material_maker/engine/gen_shader.gd | 26 +++++++++++-- addons/material_maker/nodes/bricks.mmg | 2 +- .../widgets/node_editor/node_editor.gd | 20 ++++++---- .../widgets/node_editor/node_editor.tscn | 38 ++++++++++++------- 5 files changed, 66 insertions(+), 28 deletions(-) diff --git a/addons/material_maker/engine/gen_context.gd b/addons/material_maker/engine/gen_context.gd index 2845d75..8f313be 100644 --- a/addons/material_maker/engine/gen_context.gd +++ b/addons/material_maker/engine/gen_context.gd @@ -11,12 +11,12 @@ func _init(r : MMGenRenderer): func has_variant(generator): return variants.has(generator) -func get_variant(generator, uv): +func get_variant(generator, variant): var rv = -1 if variants.has(generator): - rv = variants[generator].find(uv) + rv = variants[generator].find(variant) if rv == -1: - variants[generator].push_back(uv) + variants[generator].push_back(variant) else: - variants[generator] = [uv] + variants[generator] = [variant] return rv diff --git a/addons/material_maker/engine/gen_shader.gd b/addons/material_maker/engine/gen_shader.gd index b610d6e..ebb9703 100644 --- a/addons/material_maker/engine/gen_shader.gd +++ b/addons/material_maker/engine/gen_shader.gd @@ -134,6 +134,9 @@ func subst(string, context, uv = ""): var required_code = "" var required_textures = {} string = replace_variable(string, "name", genname) + if uv != "": + var genname_uv = genname+"_"+str(context.get_variant(self, uv)) + string = replace_variable(string, "name_uv", genname_uv) var tmp_string = replace_variable(string, "seed", str(get_seed())) if tmp_string != string: string = tmp_string @@ -196,12 +199,10 @@ func _get_shader_code(uv : String, output_index : int, context : MMGenContext): var genname = "o"+str(get_instance_id()) var output_info = [ { field="rgba", type="vec4" }, { field="rgb", type="vec3" }, { field="f", type="float" } ] var rv = { globals=[], defs="", code="", textures={} } - var variant_string = uv+","+str(output_index) if shader_model != null and shader_model.has("outputs") and shader_model.outputs.size() > output_index: var output = shader_model.outputs[output_index] - rv.defs = "" if shader_model.has("instance") && !context.has_variant(self): - var subst_output = subst(shader_model.instance, context, uv) + var subst_output = subst(shader_model.instance, context, "") while subst_output is GDScriptFunctionState: subst_output = yield(subst_output, "completed") rv.defs += subst_output.string @@ -214,6 +215,25 @@ func _get_shader_code(uv : String, output_index : int, context : MMGenContext): g = MMGradient.new() g.deserialize(parameters[p.name]) rv.defs += g.get_shader(genname+"__"+p.name+"_gradient_fct") + # Add inline code + if shader_model.has("code"): + var variant_index = context.get_variant(self, uv) + if variant_index == -1: + variant_index = context.get_variant(self, uv) + var subst_code = subst(shader_model.code, context, uv) + while subst_code is GDScriptFunctionState: + subst_code = yield(subst_code, "completed") + # Add global definitions + for d in subst_code.globals: + if rv.globals.find(d) == -1: + rv.globals.push_back(d) + # Add generated definitions + rv.defs += subst_code.defs + # Add generated code + rv.code += subst_code.code + rv.code += subst_code.string + # Add output_code + var variant_string = uv+","+str(output_index) var variant_index = context.get_variant(self, variant_string) if variant_index == -1: variant_index = context.get_variant(self, variant_string) diff --git a/addons/material_maker/nodes/bricks.mmg b/addons/material_maker/nodes/bricks.mmg index c007f04..252ea56 100644 --- a/addons/material_maker/nodes/bricks.mmg +++ b/addons/material_maker/nodes/bricks.mmg @@ -1 +1 @@ -{"name":"bricks","node_position":{"x":0,"y":0},"parameters":{"bevel":0.1,"columns":3,"mortar":0.1,"pattern":0,"repeat":1,"row_offset":0.5,"rows":6},"shader_model":{"global":"\n\t\tvec3 brick(vec2 uv, vec2 bmin, vec2 bmax, float mortar, float bevel) {\n\t\t\tfloat color = 0.5;\n\t\t\tvec2 c1 = (uv-bmin-vec2(mortar))/bevel;\n\t\t\tvec2 c2 = (bmax-uv-vec2(mortar))/bevel;\n\t\t\tvec2 c = min(c1, c2);\n\t\t\tcolor = clamp(min(c.x, c.y), 0.0, 1.0);\n\t\t\treturn vec3(color, mod(bmin, vec2(1.0, 1.0)));\n\t\t}\n\n\t\tvec3 bricks_rb(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {\n\t\t\tcount *= repeat;\n\t\t\tmortar /= max(count.x, count.y);\n\t\t\tbevel /= max(count.x, count.y);\n\t\t\tfloat x_offset = offset*step(0.5, fract(uv.y*count.y*0.5));\n\t\t\tvec2 bmin = floor(vec2(uv.x*count.x-x_offset, uv.y*count.y));\n\t\t\tbmin.x += x_offset;\n\t\t\tbmin /= count;\n\t\t\treturn brick(uv, bmin, bmin+vec2(1.0)/count, mortar, bevel);\n\t\t}\n\n\t\tvec3 bricks_rb2(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {\n\t\t\tcount *= repeat;\n\t\t\tmortar /= max(2.0*count.x, count.y);\n\t\t\tbevel /= max(2.0*count.x, count.y);\n\t\t\tfloat x_offset = offset*step(0.5, fract(uv.y*count.y*0.5));\n\t\t\tcount.x = count.x*(1.0+step(0.5, fract(uv.y*count.y*0.5)));\n\t\t\tvec2 bmin = floor(vec2(uv.x*count.x-x_offset, uv.y*count.y));\n\t\t\tbmin.x += x_offset;\n\t\t\tbmin /= count;\n\t\t\treturn brick(uv, bmin, bmin+vec2(1.0)/count, mortar, bevel);\n\t\t}\n\n\t\tvec3 bricks_hb(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {\n\t\t\tfloat pc = count.x+count.y;\n\t\t\tfloat c = pc*repeat;\n\t\t\tmortar /= c;\n\t\t\tbevel /= c;\n\t\t\tvec2 corner = floor(uv*c);\n\t\t\tfloat cdiff = mod(corner.x-corner.y, pc);\n\t\t\tif (cdiff < count.x) {\n\t\t\t\treturn brick(uv, (corner-vec2(cdiff, 0.0))/c, (corner-vec2(cdiff, 0.0)+vec2(count.x, 1.0))/c, mortar, bevel);\n\t\t\t} else {\n\t\t\t\treturn brick(uv, (corner-vec2(0.0, pc-cdiff-1.0))/c, (corner-vec2(0.0, pc-cdiff-1.0)+vec2(1.0, count.y))/c, mortar, bevel);\n\t\t\t}\n\t\t}\n\n\t\tvec3 bricks_bw(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {\n\t\t\tvec2 c = 2.0*count*repeat;\n\t\t\tfloat mc = max(c.x, c.y);\n\t\t\tmortar /= mc;\n\t\t\tbevel /= mc;\n\t\t\tvec2 corner1 = floor(uv*c);\n\t\t\tvec2 corner2 = count*floor(repeat*2.0*uv);\n\t\t\tfloat cdiff = mod(dot(floor(repeat*2.0*uv), vec2(1.0)), 2.0);\n\t\t\tvec2 corner;\n\t\t\tvec2 size;\n\t\t\tif (cdiff == 0.0) {\n\t\t\t\tcorner = vec2(corner1.x, corner2.y);\n\t\t\t\tsize = vec2(1.0, count.y);\n\t\t\t} else {\n\t\t\t\tcorner = vec2(corner2.x, corner1.y);\n\t\t\t\tsize = vec2(count.x, 1.0);\n\t\t\t}\n\t\t\treturn brick(uv, corner/c, (corner+size)/c, mortar, bevel);\n\t\t}\n\n\t\tvec3 bricks_sb(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {\n\t\t\tvec2 c = (count+vec2(1.0))*repeat;\n\t\t\tfloat mc = max(c.x, c.y);\n\t\t\tmortar /= mc;\n\t\t\tbevel /= mc;\n\t\t\tvec2 corner1 = floor(uv*c);\n\t\t\tvec2 corner2 = (count+vec2(1.0))*floor(repeat*uv);\n\t\t\tvec2 rcorner = corner1 - corner2;\n\t\t\tvec2 corner;\n\t\t\tvec2 size;\n\t\t\tif (rcorner.x == 0.0 && rcorner.y < count.y) {\n\t\t\t\tcorner = corner2;\n\t\t\t\tsize = vec2(1.0, count.y);\n\t\t\t} else if (rcorner.y == 0.0) {\n\t\t\t\tcorner = corner2+vec2(1.0, 0.0);\n\t\t\t\tsize = vec2(count.x, 1.0);\n\t\t\t} else if (rcorner.x == count.x) {\n\t\t\t\tcorner = corner2+vec2(count.x, 1.0);\n\t\t\t\tsize = vec2(1.0, count.y);\n\t\t\t} else if (rcorner.y == count.y) {\n\t\t\t\tcorner = corner2+vec2(0.0, count.y);\n\t\t\t\tsize = vec2(count.x, 1.0);\n\t\t\t} else {\n\t\t\t\tcorner = corner2+vec2(1.0);\n\t\t\t\tsize = vec2(count.x-1.0, count.y-1.0);\n\t\t\t}\n\t\t\treturn brick(uv, corner/c, (corner+size)/c, mortar, bevel);\n\t\t}","include":["noise"],"instance":"\n\t\tvec3 $(name)_xyz(vec2 uv) {\n\t\t\treturn bricks_$(pattern)(uv, vec2($(columns), $(rows)), $(repeat), $(row_offset), $(mortar), max(0.001, $(bevel)));\n\t\t}","name":"Bricks","outputs":[{"f":"$(name)_xyz($(uv)).x"},{"rgb":"rand3($(name)_xyz($(uv)).yz+vec2($(seed)))"}],"parameters":[{"default":0,"label":"","name":"pattern","type":"enum","values":[{"name":"Running bond","value":"rb"},{"name":"Running bond (2)","value":"rb2"},{"name":"HerringBone","value":"hb"},{"name":"Basket weave","value":"bw"},{"name":"Spanish bond","value":"sb"}]},{"default":1,"label":"Repeat:","max":8,"min":1,"name":"repeat","step":1,"type":"float","widget":"spinbox"},{"default":6,"label":"Rows:","max":64,"min":1,"name":"rows","step":1,"type":"float","widget":"spinbox"},{"default":3,"label":"Columns:","max":64,"min":1,"name":"columns","step":1,"type":"float","widget":"spinbox"},{"default":0.5,"label":"Offset:","max":1,"min":0,"name":"row_offset","type":"float"},{"default":0.1,"label":"Mortar:","max":0.5,"min":0,"name":"mortar","type":"float"},{"default":0.1,"label":"Bevel:","max":0.5,"min":0,"name":"bevel","type":"float"}]}} \ No newline at end of file +{"name":"bricks","node_position":{"x":0,"y":0},"parameters":{"bevel":0.1,"columns":3,"mortar":0.1,"pattern":0,"repeat":1,"row_offset":0.5,"rows":6},"shader_model":{"code":"vec3 $(name_uv) = $(name)_xyz($(uv));\n","global":"vec3 brick(vec2 uv, vec2 bmin, vec2 bmax, float mortar, float bevel) {\n\tfloat color = 0.5;\n\tvec2 c1 = (uv-bmin-vec2(mortar))/bevel;\n\tvec2 c2 = (bmax-uv-vec2(mortar))/bevel;\n\tvec2 c = min(c1, c2);\n\tcolor = clamp(min(c.x, c.y), 0.0, 1.0);\n\treturn vec3(color, mod(bmin, vec2(1.0, 1.0)));\n}\n\nvec3 bricks_rb(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {\n\tcount *= repeat;\n\tmortar /= max(count.x, count.y);\n\tbevel /= max(count.x, count.y);\n\tfloat x_offset = offset*step(0.5, fract(uv.y*count.y*0.5));\n\tvec2 bmin = floor(vec2(uv.x*count.x-x_offset, uv.y*count.y));\n\tbmin.x += x_offset;\n\tbmin /= count;\n\treturn brick(uv, bmin, bmin+vec2(1.0)/count, mortar, bevel);\n}\n\nvec3 bricks_rb2(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {\n\tcount *= repeat;\n\tmortar /= max(2.0*count.x, count.y);\n\tbevel /= max(2.0*count.x, count.y);\n\tfloat x_offset = offset*step(0.5, fract(uv.y*count.y*0.5));\n\tcount.x = count.x*(1.0+step(0.5, fract(uv.y*count.y*0.5)));\n\tvec2 bmin = floor(vec2(uv.x*count.x-x_offset, uv.y*count.y));\n\tbmin.x += x_offset;\n\tbmin /= count;\n\treturn brick(uv, bmin, bmin+vec2(1.0)/count, mortar, bevel);\n}\n\nvec3 bricks_hb(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {\n\tfloat pc = count.x+count.y;\n\tfloat c = pc*repeat;\n\tmortar /= c;\n\tbevel /= c;\n\tvec2 corner = floor(uv*c);\n\tfloat cdiff = mod(corner.x-corner.y, pc);\n\tif (cdiff < count.x) {\n\t\treturn brick(uv, (corner-vec2(cdiff, 0.0))/c, (corner-vec2(cdiff, 0.0)+vec2(count.x, 1.0))/c, mortar, bevel);\n\t} else {\n\t\treturn brick(uv, (corner-vec2(0.0, pc-cdiff-1.0))/c, (corner-vec2(0.0, pc-cdiff-1.0)+vec2(1.0, count.y))/c, mortar, bevel);\n\t}\n}\n\nvec3 bricks_bw(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {\n\tvec2 c = 2.0*count*repeat;\n\tfloat mc = max(c.x, c.y);\n\tmortar /= mc;\n\tbevel /= mc;\n\tvec2 corner1 = floor(uv*c);\n\tvec2 corner2 = count*floor(repeat*2.0*uv);\n\tfloat cdiff = mod(dot(floor(repeat*2.0*uv), vec2(1.0)), 2.0);\n\tvec2 corner;\n\tvec2 size;\n\tif (cdiff == 0.0) {\n\t\tcorner = vec2(corner1.x, corner2.y);\n\t\tsize = vec2(1.0, count.y);\n\t} else {\n\t\tcorner = vec2(corner2.x, corner1.y);\n\t\tsize = vec2(count.x, 1.0);\n\t}\n\treturn brick(uv, corner/c, (corner+size)/c, mortar, bevel);\n}\n\nvec3 bricks_sb(vec2 uv, vec2 count, float repeat, float offset, float mortar, float bevel) {\n\tvec2 c = (count+vec2(1.0))*repeat;\n\tfloat mc = max(c.x, c.y);\n\tmortar /= mc;\n\tbevel /= mc;\n\tvec2 corner1 = floor(uv*c);\n\tvec2 corner2 = (count+vec2(1.0))*floor(repeat*uv);\n\tvec2 rcorner = corner1 - corner2;\n\tvec2 corner;\n\tvec2 size;\n\tif (rcorner.x == 0.0 && rcorner.y < count.y) {\n\t\tcorner = corner2;\n\t\tsize = vec2(1.0, count.y);\n\t} else if (rcorner.y == 0.0) {\n\t\tcorner = corner2+vec2(1.0, 0.0);\n\t\tsize = vec2(count.x, 1.0);\n\t} else if (rcorner.x == count.x) {\n\t\tcorner = corner2+vec2(count.x, 1.0);\n\t\tsize = vec2(1.0, count.y);\n\t} else if (rcorner.y == count.y) {\n\t\tcorner = corner2+vec2(0.0, count.y);\n\t\tsize = vec2(count.x, 1.0);\n\t} else {\n\t\tcorner = corner2+vec2(1.0);\n\t\tsize = vec2(count.x-1.0, count.y-1.0);\n\t}\n\treturn brick(uv, corner/c, (corner+size)/c, mortar, bevel);\n}","inputs":[],"instance":"vec3 $(name)_xyz(vec2 uv) {\n return bricks_$(pattern)(uv, vec2($(columns), $(rows)), $(repeat), $(row_offset), $(mortar), max(0.001, $(bevel)));\n}","name":"Bricks","outputs":[{"f":"$(name_uv).x","type":"f"},{"rgb":"rand3($(name_uv).yz+vec2($(seed)))","type":"rgb"}],"parameters":[{"default":0,"label":"","name":"pattern","type":"enum","values":[{"name":"Running bond","value":"rb"},{"name":"Running bond (2)","value":"rb2"},{"name":"HerringBone","value":"hb"},{"name":"Basket weave","value":"bw"},{"name":"Spanish bond","value":"sb"}]},{"default":1,"label":"Repeat:","max":8,"min":1,"name":"repeat","step":1,"type":"float","widget":"spinbox"},{"default":6,"label":"Rows:","max":64,"min":1,"name":"rows","step":1,"type":"float","widget":"spinbox"},{"default":3,"label":"Columns:","max":64,"min":1,"name":"columns","step":1,"type":"float","widget":"spinbox"},{"default":0.5,"label":"Offset:","max":1,"min":0,"name":"row_offset","step":0,"type":"float"},{"default":0.1,"label":"Mortar:","max":0.5,"min":0,"name":"mortar","step":0,"type":"float"},{"default":0.1,"label":"Bevel:","max":0.5,"min":0,"name":"bevel","step":0,"type":"float"}]},"type":"shader"} \ No newline at end of file diff --git a/addons/material_maker/widgets/node_editor/node_editor.gd b/addons/material_maker/widgets/node_editor/node_editor.gd index 01866c3..57d1d99 100644 --- a/addons/material_maker/widgets/node_editor/node_editor.gd +++ b/addons/material_maker/widgets/node_editor/node_editor.gd @@ -3,7 +3,9 @@ extends WindowDialog var model_data = null -onready var global_editor : TextEdit = $Sizer/Tabs/Global +onready var main_code_editor : TextEdit = $"Sizer/Tabs/Main Code" +onready var instance_functions_editor : TextEdit = $"Sizer/Tabs/Instance Functions" +onready var global_functions_editor : TextEdit = $"Sizer/Tabs/Global Functions" const ParameterEditor = preload("res://addons/material_maker/widgets/node_editor/parameter.tscn") const InputEditor = preload("res://addons/material_maker/widgets/node_editor/input.tscn") @@ -12,8 +14,9 @@ const OutputEditor = preload("res://addons/material_maker/widgets/node_editor/ou signal node_changed func _ready(): - global_editor.add_color_region("//", "", Color(0, 0.5, 0), true) - + main_code_editor.add_color_region("//", "", Color(0, 0.5, 0), true) + instance_functions_editor.add_color_region("//", "", Color(0, 0.5, 0), true) + global_functions_editor.add_color_region("//", "", Color(0, 0.5, 0), true) func add_item(parent, scene): var object = scene.instance() @@ -34,15 +37,18 @@ func set_model_data(data): for o in data.outputs: add_item($Sizer/Tabs/Outputs/Outputs/Sizer, OutputEditor).set_model_data(o) if data.has("global"): - $Sizer/Tabs/Global.text = data.global + global_functions_editor.text = data.global if data.has("instance"): - $Sizer/Tabs/Instance.text = data.instance + instance_functions_editor.text = data.instance + if data.has("code"): + main_code_editor.text = data.code func get_model_data(): var data = { name=$Sizer/Tabs/General/Name/Name.text, - global=$Sizer/Tabs/Global.text, - instance=$Sizer/Tabs/Instance.text, + global=global_functions_editor.text, + instance=instance_functions_editor.text, + code=main_code_editor.text } data.parameters = [] for p in $Sizer/Tabs/General/Parameters/Sizer.get_children(): diff --git a/addons/material_maker/widgets/node_editor/node_editor.tscn b/addons/material_maker/widgets/node_editor/node_editor.tscn index bda376b..7343708 100644 --- a/addons/material_maker/widgets/node_editor/node_editor.tscn +++ b/addons/material_maker/widgets/node_editor/node_editor.tscn @@ -146,7 +146,31 @@ size_flags_horizontal = 0 icon = SubResource( 1 ) flat = true -[node name="Global" type="TextEdit" parent="Sizer/Tabs"] +[node name="Main Code" type="TextEdit" parent="Sizer/Tabs"] +visible = false +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 32.0 +margin_right = -4.0 +margin_bottom = -4.0 +mouse_default_cursor_shape = 0 +syntax_highlighting = true +show_line_numbers = true + +[node name="Instance Functions" type="TextEdit" parent="Sizer/Tabs"] +visible = false +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 4.0 +margin_top = 32.0 +margin_right = -4.0 +margin_bottom = -4.0 +mouse_default_cursor_shape = 0 +syntax_highlighting = true +show_line_numbers = true + +[node name="Global Functions" type="TextEdit" parent="Sizer/Tabs"] visible = false anchor_right = 1.0 anchor_bottom = 1.0 @@ -160,18 +184,6 @@ custom_colors/brace_mismatch_color = Color( 1, 0, 0, 1 ) syntax_highlighting = true show_line_numbers = true -[node name="Instance" type="TextEdit" parent="Sizer/Tabs"] -visible = false -anchor_right = 1.0 -anchor_bottom = 1.0 -margin_left = 4.0 -margin_top = 32.0 -margin_right = -4.0 -margin_bottom = -4.0 -mouse_default_cursor_shape = 0 -syntax_highlighting = true -show_line_numbers = true - [node name="HBoxContainer" type="HBoxContainer" parent="Sizer"] margin_left = 307.0 margin_top = 378.0