From 80f8071d7b6c630609e150c6fcb78ca5e72dbf22 Mon Sep 17 00:00:00 2001 From: Rodolphe Suescun Date: Sun, 20 Oct 2019 17:28:06 +0200 Subject: [PATCH] Started updating convolution for computed matrices --- .../material_maker/engine/gen_convolution.gd | 150 +++++++++++++++--- addons/material_maker/engine/gen_switch.gd | 6 + test_blur.ptex | 1 + 3 files changed, 138 insertions(+), 19 deletions(-) create mode 100644 test_blur.ptex diff --git a/addons/material_maker/engine/gen_convolution.gd b/addons/material_maker/engine/gen_convolution.gd index a77c801..f71cb76 100644 --- a/addons/material_maker/engine/gen_convolution.gd +++ b/addons/material_maker/engine/gen_convolution.gd @@ -5,7 +5,7 @@ class_name MMGenConvolution var convolution_params : Dictionary = {} func get_type(): - return "shader" + return "convolution" func get_type_name(): if convolution_params.has("name"): @@ -13,7 +13,11 @@ func get_type_name(): return .get_type_name() func get_parameter_defs(): - return [ { name="size", type="size", first=4, last=11, default=4 } ] + var rv : Array = [ { name="size", type="size", first=4, last=11, default=4 } ] + if convolution_params.has("parameters"): + for p in convolution_params.parameters: + rv.push_back(p) + return rv func get_input_defs(): return [ { name="in", type=convolution_params.input_type } ] @@ -35,27 +39,135 @@ func _get_shader_code(uv : String, output_index : int, context : MMGenContext): var variant_index = context.get_variant(self, uv) if variant_index == -1: variant_index = context.get_variant(self, uv) - rv.code += "%s %s_%d = %s;\n" % [ types[convolution_params.output_type].type, genname, variant_index, types[convolution_params.output_type].init ] + # Calculate matrix + var errors = 0 + var sum = [ 0.0, 0.0, 0.0, 0.0 ] + var matrix = [] + var expr : Expression = null + var expr_variables : PoolStringArray + var expr_values : Array + var expr_variables_x_index : int + if convolution_params.has("matrix_function"): + expr = Expression.new() + expr_variables = PoolStringArray(["size"]) + expr_values = [ pow(2, 4+parameters.size) ] + if convolution_params.has("parameters"): + for p in convolution_params.parameters: + expr_variables.push_back(p.name) + if parameters.has(p.name): + expr_values.push_back(parameters[p.name]) + elif p.has("default"): + expr_values.push_back(p.default) + else: + expr_values.push_back(0) + errors += 1 + print("No value for "+p.name) + expr_variables_x_index = expr_variables.size() + expr_variables.push_back("x") + expr_values.push_back(0) + expr_variables.push_back("y") + expr_values.push_back(0) + var error = expr.parse(convolution_params.matrix_function, expr_variables) + if error != OK: + print("Error in expression: "+expr.get_error_text()) + return for dy in range(-convolution_params.y, convolution_params.y+1): + var line = [] for dx in range(-convolution_params.x, convolution_params.x+1): - var coef = convolution_params.matrix[dy+convolution_params.y][dx+convolution_params.x] + var coef = 0.0 + if convolution_params.has("matrix"): + coef = convolution_params.matrix[dy+convolution_params.y][dx+convolution_params.x] + elif expr != null: + expr_values[expr_variables_x_index] = dx + expr_values[expr_variables_x_index+1] = dy + coef = expr.execute(expr_values) if typeof(coef) == TYPE_INT: coef = float(coef) - if typeof(coef) == TYPE_REAL: - coef = Vector3(coef, coef, coef) - if typeof(coef) == TYPE_ARRAY: - coef = Vector3(coef[0], coef[1], coef[2]) - var coef_str = "vec3(%.9f,%.9f,%.9f)" % [ coef.x, coef.y, coef.z ] - var uv_str = "((%s)+vec2(%.9f,%.9f))" % [ uv, dx*epsilon, dy*epsilon ] - var src_code = source.generator.get_shader_code(uv_str, source.output_index, context) - while src_code is GDScriptFunctionState: - src_code = yield(src_code, "completed") - rv.defs += src_code.defs - rv.code += src_code.code - rv.code += "%s_%d += %s*%s;\n" % [ genname, variant_index, coef_str, src_code[convolution_params.input_type] ] - for t in src_code.textures.keys(): - rv.textures[t] = src_code.textures[t] - rv.rgb = "%s_%d" % [ genname, variant_index ] + match convolution_params.output_type: + "f": + if typeof(coef) == TYPE_REAL or convolution_params.input_type == "f": + sum[0] += coef + else: + errors += 1 + "rgb": + if typeof(coef) == TYPE_REAL: + sum[0] += coef + sum[1] += coef + sum[2] += coef + if convolution_params.input_type == "f": + coef = "vec3(%.9f)" % [ coef ] + elif convolution_params.input_type == "rgb": + coef = "%.9f" % coef + else: + errors += 1 + if typeof(coef) == TYPE_ARRAY and coef.size() == 3: + if convolution_params.input_type == "f" or convolution_params.input_type == "rgb": + sum[0] += coef[0] + sum[1] += coef[1] + sum[2] += coef[2] + coef = "vec3(%.9f,%.9f,%.9f)" % [ coef[0], coef[1], coef[2] ] + else: + errors += 1 + "rgba": + if typeof(coef) == TYPE_REAL: + sum[0] += coef + sum[1] += coef + sum[2] += coef + sum[3] += coef + if convolution_params.input_type == "f": + coef = "vec4(%.9f)" % [ coef ] + if convolution_params.input_type == "rgba": + coef = "%.9f" % coef + else: + errors += 1 + if typeof(coef) == TYPE_ARRAY and coef.size() == 3: + if convolution_params.input_type == "f" or convolution_params.input_type == "rgba": + sum[0] += coef[0] + sum[1] += coef[1] + sum[2] += coef[2] + sum[3] += coef[3] + coef = "vec4(%.9f,%.9f,%.9f,%.9f)" % [ coef[0], coef[1], coef[2], coef[3] ] + else: + errors += 1 + line.push_back(coef) + matrix.push_back(line) + # Generate code + rv.code += "%s %s_%d = %s;\n" % [ types[convolution_params.output_type].type, genname, variant_index, types[convolution_params.output_type].init ] + if errors > 0: + pass + else: + for dy in range(-convolution_params.y, convolution_params.y+1): + var line = matrix[dy+convolution_params.y] + for dx in range(-convolution_params.x, convolution_params.x+1): + var coef = line[dx+convolution_params.x] + var uv_str = "((%s)+vec2(%.9f,%.9f))" % [ uv, dx*epsilon, dy*epsilon ] + var src_code = source.generator.get_shader_code(uv_str, source.output_index, context) + while src_code is GDScriptFunctionState: + src_code = yield(src_code, "completed") + # Add global definitions + for d in src_code.globals: + if rv.globals.find(d) == -1: + rv.globals.push_back(d) + # Add generated definitions + rv.defs += src_code.defs + # Add generated code + rv.code += src_code.code + rv.code += "%s_%d += %s*%s;\n" % [ genname, variant_index, coef, src_code[convolution_params.input_type] ] + for t in src_code.textures.keys(): + rv.textures[t] = src_code.textures[t] + # normalize + if false: + var sum_str : String + var count : float = float((2*convolution_params.x+1) / (2*convolution_params.y+1)) + match convolution_params.output_type: + "f": + sum_str = "%.9f" % [ sum[0] / count ] + "rgb": + sum_str = "vec3(%.9f, %.9f, %.9f)" % [ sum[0] / count, sum[1] / count, sum[2] / count ] + "rgba": + sum_str = "vec4(%.9f, %.9f, %.9f, %.9f)" % [ sum[0] / count, sum[1] / count, sum[2] / count, sum[3] / count ] + rv.code += "%s_%d /= %s;\n" % [ genname, variant_index, sum_str ] + rv[convolution_params.output_type] = "%s_%d" % [ genname, variant_index ] return rv func _serialize(data): diff --git a/addons/material_maker/engine/gen_switch.gd b/addons/material_maker/engine/gen_switch.gd index b1e16f7..2ba815c 100644 --- a/addons/material_maker/engine/gen_switch.gd +++ b/addons/material_maker/engine/gen_switch.gd @@ -48,6 +48,12 @@ func set_parameter(p, v): .set_parameter(p, v) emit_signal("parameter_changed", "__update_all__", null) + +# get the list of outputs that depend on the input whose index is passed as parameter +func follow_input(input_index : int) -> Array: + return [ OutputPort.new(self, input_index % int(parameters.outputs)) ] + + func source_changed(input_index : int): notify_output_change(input_index % int(parameters.outputs)) diff --git a/test_blur.ptex b/test_blur.ptex new file mode 100644 index 0000000..83af679 --- /dev/null +++ b/test_blur.ptex @@ -0,0 +1 @@ +{"connections":[{"from":"bricks","from_port":0,"to":"buffer","to_port":0},{"from":"buffer","from_port":0,"to":"blurx_convolution","to_port":0}],"label":"Graph","name":"49","node_position":{"x":0,"y":0},"nodes":[{"name":"Material","node_position":{"x":0,"y":0},"parameters":{"albedo_color":{"a":1,"b":1,"g":1,"r":1,"type":"Color"},"ao_light_affect":1,"depth_scale":1,"emission_energy":1,"metallic":1,"normal_scale":1,"roughness":1,"size":2},"type":"material"},{"convolution_params":{"input_type":"rgba","matrix_function":"exp(-0.5*(pow(float(x)/float(sigma), 2.0)))/(6.28318530718 *sigma*sigma)","output_type":"rgba","parameters":[{"max":50,"min":0.05,"name":"sigma","type":"float"}],"x":50,"y":0},"name":"blurx_convolution","node_position":{"x":-223.5,"y":-124.5},"parameters":{"size":4},"type":"convolution"},{"name":"bricks","node_position":{"x":-522.25,"y":-158.75},"parameters":{"bevel":0.1,"columns":3,"mortar":0.1,"pattern":0,"repeat":1,"row_offset":0.5,"rows":6},"type":"bricks"},{"name":"buffer","node_position":{"x":-212.25,"y":-189.75},"parameters":{"size":4},"type":"buffer"}],"parameters":{},"type":"graph"} \ No newline at end of file