mirror of
https://github.com/Relintai/material-maker.git
synced 2025-01-13 07:41:14 +01:00
Optimized gradient parameters (passed as floats when possible)
This commit is contained in:
parent
8da80e163c
commit
9ab8820598
@ -114,15 +114,38 @@ func get_parameter(n : String):
|
||||
else:
|
||||
return get_parameter_def(n).default
|
||||
|
||||
class CustomGradientSorter:
|
||||
static func compare(a, b) -> bool:
|
||||
return a.pos < b.pos
|
||||
|
||||
func set_parameter(n : String, v) -> void:
|
||||
var old_value = parameters[n] if parameters.has(n) else null
|
||||
parameters[n] = v
|
||||
emit_signal("parameter_changed", n, v)
|
||||
if is_inside_tree():
|
||||
var parameter_def : Dictionary = get_parameter_def(n)
|
||||
if parameter_def.has("type") and parameter_def.type == "float":
|
||||
get_tree().call_group("preview", "on_float_parameter_changed", "p_o%s_%s" % [ str(get_instance_id()), n ], v)
|
||||
else:
|
||||
source_changed(0)
|
||||
if parameter_def.has("type"):
|
||||
if parameter_def.type == "float":
|
||||
var parameter_name = "p_o%s_%s" % [ str(get_instance_id()), n ]
|
||||
get_tree().call_group("preview", "on_float_parameter_changed", parameter_name, v)
|
||||
return
|
||||
elif parameter_def.type == "gradient":
|
||||
if v.interpolation == old_value.interpolation && v.points.size() == old_value.points.size():
|
||||
# convert from old format
|
||||
for i in range(old_value.points.size()):
|
||||
if old_value.points[i].has("v"):
|
||||
var old = old_value.points[i]
|
||||
old_value.points[i] = { pos=old.v, r=old.c.r, g=old.c.g, b=old.c.b, a=old.c.a }
|
||||
old_value.points.sort_custom(CustomGradientSorter, "compare")
|
||||
v.points.sort_custom(CustomGradientSorter, "compare")
|
||||
for i in range(old_value.points.size()):
|
||||
for f in [ "pos", "r", "g", "b", "a" ]:
|
||||
if v.points[i][f] != old_value.points[i][f]:
|
||||
var parameter_name = "p_o%s_%s_%d_%s" % [ str(get_instance_id()), n, i, f ]
|
||||
get_tree().call_group("preview", "on_float_parameter_changed", parameter_name, v.points[i][f])
|
||||
return
|
||||
print("regenerating shader")
|
||||
source_changed(0)
|
||||
|
||||
func notify_output_change(output_index : int) -> void:
|
||||
var targets = get_targets(output_index)
|
||||
|
@ -200,7 +200,7 @@ func subst(string : String, context : MMGenContext, uv : String = "") -> Diction
|
||||
elif p.type == "color":
|
||||
value_string = "vec4(%.9f, %.9f, %.9f, %.9f)" % [ value.r, value.g, value.b, value.a ]
|
||||
elif p.type == "gradient":
|
||||
value_string = genname+"_p_"+p.name+"_gradient_fct"
|
||||
value_string = genname+"_"+p.name+"_gradient_fct"
|
||||
elif p.type == "boolean":
|
||||
value_string = "true" if value else "false"
|
||||
else:
|
||||
@ -258,7 +258,10 @@ func _get_shader_code(uv : String, output_index : int, context : MMGenContext) -
|
||||
if !(g is MMGradient):
|
||||
g = MMGradient.new()
|
||||
g.deserialize(parameters[p.name])
|
||||
rv.defs += g.get_shader(genname+"_p_"+p.name+"_gradient_fct")
|
||||
var params = g.get_shader_params(genname+"_"+p.name)
|
||||
for sp in params.keys():
|
||||
rv.defs += "uniform float "+sp+" = "+str(params[sp])+";\n"
|
||||
rv.defs += g.get_shader(genname+"_"+p.name)
|
||||
# Generate functions for inputs
|
||||
if shader_model.has("inputs"):
|
||||
for i in range(shader_model.inputs.size()):
|
||||
|
@ -33,6 +33,9 @@ func add_point(v, c) -> void:
|
||||
func sort() -> void:
|
||||
if !sorted:
|
||||
points.sort_custom(CustomSorter, "compare")
|
||||
for i in range(points.size()-1):
|
||||
if points[i].v+0.0000005 >= points[i+1].v:
|
||||
points[i+1].v = points[i].v+0.000001
|
||||
sorted = true
|
||||
|
||||
func get_color(x) -> Color:
|
||||
@ -52,69 +55,81 @@ func get_color(x) -> Color:
|
||||
else:
|
||||
return Color(0.0, 0.0, 0.0, 1.0)
|
||||
|
||||
func get_shader_params(name) -> Dictionary:
|
||||
sort()
|
||||
var rv = {}
|
||||
for i in range(points.size()):
|
||||
rv["p_"+name+"_"+str(i)+"_pos"] = points[i].v
|
||||
rv["p_"+name+"_"+str(i)+"_r"] = points[i].c.r
|
||||
rv["p_"+name+"_"+str(i)+"_g"] = points[i].c.g
|
||||
rv["p_"+name+"_"+str(i)+"_b"] = points[i].c.b
|
||||
rv["p_"+name+"_"+str(i)+"_a"] = points[i].c.a
|
||||
return rv
|
||||
|
||||
# get_color_in_shader
|
||||
func gcis(color) -> String:
|
||||
return "vec4(%.9f,%.9f,%.9f,%.9f)" % [color.r, color.g, color.b, color.a]
|
||||
|
||||
func pv(name : String, i : int) -> String:
|
||||
return "p_"+name+"_"+str(i)+"_pos"
|
||||
|
||||
func pc(name : String, i : int) -> String:
|
||||
return "vec4(p_"+name+"_"+str(i)+"_r,p_"+name+"_"+str(i)+"_g,p_"+name+"_"+str(i)+"_b,p_"+name+"_"+str(i)+"_a)"
|
||||
|
||||
func get_shader(name) -> String:
|
||||
sort()
|
||||
var shader
|
||||
shader = "vec4 "+name+"(float x) {\n"
|
||||
shader = "vec4 "+name+"_gradient_fct(float x) {\n"
|
||||
match interpolation:
|
||||
0:
|
||||
if points.size() > 0:
|
||||
shader += " if (x < %.9f) {\n" % (0.5*(points[0].v + points[1].v))
|
||||
shader += " return "+gcis(points[0].c)+";\n"
|
||||
shader += " if (x < 0.5*(%s+%s)) {\n" % [ pv(name, 0), pv(name, 1) ]
|
||||
shader += " return "+pc(name, 0)+";\n"
|
||||
var s = points.size()-1
|
||||
for i in range(s):
|
||||
if points[i+1].v-points[i].v > 0:
|
||||
shader += " } else if (x < %.9f) {\n" % (0.5*(points[i].v + points[i+1].v))
|
||||
shader += " return "+gcis(points[i].c)+";\n"
|
||||
for i in range(1, s):
|
||||
shader += " } else if (x < 0.5*(%s+%s)) {\n" % [ pv(name, i), pv(name, i+1) ]
|
||||
shader += " return "+pc(name, i)+";\n"
|
||||
shader += " }\n"
|
||||
shader += " return "+gcis(points[s].c)+";\n"
|
||||
shader += " return "+pc(name, s)+";\n"
|
||||
else:
|
||||
shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n"
|
||||
1, 2:
|
||||
if points.size() > 0:
|
||||
shader += " if (x < %.9f) {\n" % points[0].v
|
||||
shader += " return "+gcis(points[0].c)+";\n"
|
||||
shader += " if (x < %s) {\n" % pv(name, 0)
|
||||
shader += " return "+pc(name, 0)+";\n"
|
||||
var s = points.size()-1
|
||||
for i in range(s):
|
||||
var p1mp0 = points[i+1].v-points[i].v
|
||||
if p1mp0 > 0:
|
||||
shader += " } else if (x < %.9f) {\n" % points[i+1].v
|
||||
var function = "(" if interpolation == 1 else "0.5-0.5*cos(3.14159265359*"
|
||||
shader += " return mix(%s, %s, %s(x-%.9f)/%.9f));\n" % [ gcis(points[i].c), gcis(points[i+1].c), function, points[i].v, p1mp0 ]
|
||||
shader += " } else if (x < %s) {\n" % pv(name, i+1)
|
||||
var function = "(" if interpolation == 1 else "0.5-0.5*cos(3.14159265359*"
|
||||
shader += " return mix(%s, %s, %s(x-%s)/(%s-%s)));\n" % [ pc(name, i), pc(name, i+1), function, pv(name, i), pv(name, i+1), pv(name, i) ]
|
||||
shader += " }\n"
|
||||
shader += " return "+gcis(points[s].c)+";\n"
|
||||
shader += " return "+pc(name, s)+";\n"
|
||||
else:
|
||||
shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n"
|
||||
3:
|
||||
if points.size() > 0:
|
||||
shader += " if (x < %.9f) {\n" % points[0].v
|
||||
shader += " return "+gcis(points[0].c)+";\n"
|
||||
shader += " if (x < %s) {\n" % pv(name, 0)
|
||||
shader += " return "+pc(name, 0)+";\n"
|
||||
var s = points.size()-1
|
||||
for i in range(s):
|
||||
var p1mp0 = points[i+1].v-points[i].v
|
||||
if p1mp0 > 0:
|
||||
shader += " } else if (x < %.9f) {\n" % points[i+1].v
|
||||
var dx : String = "(x-%.9f)/%.9f" % [ points[i].v, p1mp0 ]
|
||||
var b : String = "mix(%s, %s, %s)" % [ gcis(points[i].c), gcis(points[i+1].c), dx ]
|
||||
if i > 0 and points[i-1].v < points[i].v:
|
||||
var a : String = "mix(%s, %s, (x-%.9f)/%.9f)" % [ gcis(points[i-1].c), gcis(points[i].c), points[i-1].v, points[i].v-points[i-1].v ]
|
||||
if i < s-1 and points[i+1].v < points[i+2].v:
|
||||
var c : String = "mix(%s, %s, (x-%.9f)/%.9f)" % [ gcis(points[i+1].c), gcis(points[i+2].c), points[i+1].v, points[i+2].v-points[i+1].v ]
|
||||
var ac : String = "mix("+a+", "+c+", 0.5-0.5*cos(3.14159265359*"+dx+"))"
|
||||
shader += " return 0.5*("+b+" + "+ac+");\n"
|
||||
else:
|
||||
shader += " return mix("+a+", "+b+", 0.5+0.5*"+dx+");\n"
|
||||
elif i < s-1 and points[i+1].v < points[i+2].v:
|
||||
var c : String = "mix(%s, %s, (x-%.9f)/%.9f)" % [ gcis(points[i+1].c), gcis(points[i+2].c), points[i+1].v, points[i+2].v-points[i+1].v ]
|
||||
shader += " return mix("+c+", "+b+", 1.0-0.5*"+dx+");\n"
|
||||
shader += " } else if (x < %s) {\n" % pv(name, i+1)
|
||||
var dx : String = "(x-%s)/(%s-%s)" % [ pv(name, i), pv(name, i+1), pv(name, i) ]
|
||||
var b : String = "mix(%s, %s, %s)" % [ pc(name, i), pc(name, i+1), dx ]
|
||||
if i > 0:
|
||||
var a : String = "mix(%s, %s, (x-%s)/(%s-%s))" % [ pc(name, i-1), pc(name, i), pv(name, i-1), pv(name, i), pv(name, i-1) ]
|
||||
if i < s-1:
|
||||
var c : String = "mix(%s, %s, (x-%s)/(%s-%s))" % [ pc(name, i+1), pc(name, i+2), pv(name, i+1), pv(name, i+2), pv(name, i+1) ]
|
||||
var ac : String = "mix("+a+", "+c+", 0.5-0.5*cos(3.14159265359*"+dx+"))"
|
||||
shader += " return 0.5*("+b+" + "+ac+");\n"
|
||||
else:
|
||||
shader += " return "+b+";\n"
|
||||
shader += " return mix("+a+", "+b+", 0.5+0.5*"+dx+");\n"
|
||||
elif i < s-1:
|
||||
var c : String = "mix(%s, %s, (x-%s)/(%s-%s))" % [ pc(name, i+1), pc(name, i+2), pv(name, i+1), pv(name, i+2), pv(name, i+1) ]
|
||||
shader += " return mix("+c+", "+b+", 1.0-0.5*"+dx+");\n"
|
||||
else:
|
||||
shader += " return "+b+";\n"
|
||||
shader += " }\n"
|
||||
shader += " return "+gcis(points[s].c)+";\n"
|
||||
shader += " return "+pc(name, s)+";\n"
|
||||
else:
|
||||
shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n"
|
||||
_:
|
||||
|
@ -109,7 +109,6 @@ func _on_gradient_changed(new_gradient, variable) -> void:
|
||||
ignore_parameter_change = variable
|
||||
generator.set_parameter(variable, MMType.serialize_value(new_gradient))
|
||||
ignore_parameter_change = ""
|
||||
update_shaders()
|
||||
|
||||
func create_parameter_control(p : Dictionary) -> Control:
|
||||
var control = null
|
||||
|
@ -46,7 +46,7 @@ func on_parameter_changed(n : String, v) -> void:
|
||||
var p = generator.get_parameter_def(n)
|
||||
if p.has("type"):
|
||||
match p.type:
|
||||
"float":
|
||||
"float", "gradient":
|
||||
pass
|
||||
_:
|
||||
set_generator(generator, output)
|
||||
|
@ -147,8 +147,11 @@ func get_gradient_color(x) -> Color:
|
||||
func update_shader() -> void:
|
||||
var shader
|
||||
shader = "shader_type canvas_item;\n"
|
||||
shader += value.get_shader("gradient")
|
||||
shader += "void fragment() { COLOR = gradient(UV.x); }"
|
||||
var params = value.get_shader_params("")
|
||||
for sp in params.keys():
|
||||
shader += "uniform float "+sp+" = "+str(params[sp])+";\n"
|
||||
shader += value.get_shader("")
|
||||
shader += "void fragment() { COLOR = _gradient_fct(UV.x); }"
|
||||
$Gradient.material.shader.set_code(shader)
|
||||
emit_signal("updated", value)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user