Started optimizing 2D preview

float parameters don't trigger shader regeneration anymore
This commit is contained in:
RodZill4 2020-03-13 07:50:04 +01:00
parent 59c9e3b7b1
commit 455dcc7fde
13 changed files with 82 additions and 63 deletions

View File

@ -110,12 +110,19 @@ func get_parameter_def(param_name : String) -> Dictionary:
return {} return {}
func get_parameter(n : String): func get_parameter(n : String):
if parameters.has(n):
return parameters[n] return parameters[n]
else:
return get_parameter_def(n).default
func set_parameter(n : String, v) -> void: func set_parameter(n : String, v) -> void:
parameters[n] = v parameters[n] = v
source_changed(0) source_changed(0)
emit_signal("parameter_changed", 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)
func notify_output_change(output_index : int) -> void: func notify_output_change(output_index : int) -> void:
var targets = get_targets(output_index) var targets = get_targets(output_index)
@ -159,7 +166,7 @@ func get_input_shader(input_index : int) -> Dictionary:
func get_shader(output_index : int, context) -> Dictionary: func get_shader(output_index : int, context) -> Dictionary:
return get_shader_code("UV", output_index, context) return get_shader_code("UV", output_index, context)
func generate_preview_shader(src_code, type) -> String: static func generate_preview_shader(src_code, type, main_fct = "void fragment() { COLOR = preview_2d(UV); }") -> String:
var code var code
code = "shader_type canvas_item;\n" code = "shader_type canvas_item;\n"
code += "render_mode blend_disabled;\n" code += "render_mode blend_disabled;\n"
@ -182,6 +189,7 @@ func generate_preview_shader(src_code, type) -> String:
shader_code += preview_code shader_code += preview_code
#print("GENERATED SHADER:\n"+shader_code) #print("GENERATED SHADER:\n"+shader_code)
code += shader_code code += shader_code
code += main_fct
return code return code
func render(output_index : int, size : int, preview : bool = false) -> Object: func render(output_index : int, size : int, preview : bool = false) -> Object:

View File

@ -188,7 +188,7 @@ func subst(string : String, context : MMGenContext, uv : String = "") -> Diction
var value = parameters[p.name] var value = parameters[p.name]
var value_string = null var value_string = null
if p.type == "float": if p.type == "float":
value_string = "%.9f" % value value_string = "p_%s_%s" % [ genname, p.name ]
elif p.type == "size": elif p.type == "size":
value_string = "%.9f" % pow(2, value) value_string = "%.9f" % pow(2, value)
elif p.type == "enum": elif p.type == "enum":
@ -247,7 +247,9 @@ func _get_shader_code(uv : String, output_index : int, context : MMGenContext) -
if !context.has_variant(self): if !context.has_variant(self):
# Generate functions for gradients # Generate functions for gradients
for p in shader_model.parameters: for p in shader_model.parameters:
if p.type == "gradient": if p.type == "float":
rv.defs += "uniform float p_%s_%s = %.9f;\n" % [ genname, p.name, parameters[p.name] ]
elif p.type == "gradient":
var g = parameters[p.name] var g = parameters[p.name]
if !(g is MMGradient): if !(g is MMGradient):
g = MMGradient.new() g = MMGradient.new()

View File

@ -39,7 +39,7 @@ func get_input_defs() -> Array:
func get_output_defs() -> Array: func get_output_defs() -> Array:
var rv : Array = [] var rv : Array = []
for o in range(parameters.outputs): for o in range(get_parameter("outputs")):
var n = PoolByteArray([65+o]).get_string_from_ascii() var n = PoolByteArray([65+o]).get_string_from_ascii()
rv.push_back({ name=n, type="any" }) rv.push_back({ name=n, type="any" })
return rv return rv

View File

@ -1,5 +1,4 @@
void fragment() { vec4 preview_2d(vec2 uv) {
vec2 uv = UV;
$(code) $(code)
COLOR = vec4(vec3($(value)), 1.0); return vec4(vec3($(value)), 1.0);
} }

View File

@ -1,5 +1,4 @@
void fragment() { vec4 preview_2d(vec2 uv) {
vec2 uv = UV;
$(code) $(code)
COLOR = vec4($(value), 1.0); return vec4($(value), 1.0);
} }

View File

@ -1,5 +1,4 @@
void fragment() { vec4 preview_2d(vec2 uv) {
vec2 uv = UV;
$(code) $(code)
COLOR = $(value); return $(value);
} }

View File

@ -1,10 +1,9 @@
void fragment() { vec4 preview_2d(vec2 uv) {
vec2 uv = UV;
$(code) $(code)
float d = $(value); float d = $(value);
vec3 col = vec3(cos(d*min(256, preview_size))); vec3 col = vec3(cos(d*min(256, preview_size)));
col *= clamp(1.0-d*d, 0.0, 1.0); col *= clamp(1.0-d*d, 0.0, 1.0);
col *= vec3(1.0, vec2(step(-0.015, d))); col *= vec3(1.0, vec2(step(-0.015, d)));
col *= vec3(vec2(step(d, 0.015)), 1.0); col *= vec3(vec2(step(d, 0.015)), 1.0);
COLOR = vec4(col, 1.0); return vec4(col, 1.0);
} }

View File

@ -20,8 +20,8 @@ vec3 normal(vec3 p) {
return normalize(n); return normalize(n);
} }
void fragment() { vec4 preview_2d(vec2 uv) {
vec2 uv = UV-vec2(0.5); uv -= vec2(0.5);
vec3 p = vec3(uv, 2.0-raymarch(vec3(uv, 2.0), vec3(0.0, 0.0, -1.0))); vec3 p = vec3(uv, 2.0-raymarch(vec3(uv, 2.0), vec3(0.0, 0.0, -1.0)));
vec3 n = normal(p); vec3 n = normal(p);
vec3 l = vec3(5.0, 5.0, 10.0); vec3 l = vec3(5.0, 5.0, 10.0);
@ -29,5 +29,5 @@ void fragment() {
float o = step(p.z, 0.001); float o = step(p.z, 0.001);
float shadow = 1.0-0.75*step(raymarch(l, -ld), length(l-p)-0.01); float shadow = 1.0-0.75*step(raymarch(l, -ld), length(l-p)-0.01);
float light = 0.3+0.7*dot(n, ld)*shadow; float light = 0.3+0.7*dot(n, ld)*shadow;
COLOR = vec4(vec3(0.8+0.2*o, 0.8+0.2*o, 1.0)*light, 1.0); return vec4(vec3(0.8+0.2*o, 0.8+0.2*o, 1.0)*light, 1.0);
} }

View File

@ -31,8 +31,8 @@ vec3 rm_color(float c) {
return 1.0 * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), 1.0); return 1.0 * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), 1.0);
} }
void fragment() { vec4 preview_2d(vec2 uv) {
vec2 uv = UV-vec2(0.5); uv -= vec2(0.5);
vec2 rm = raymarch(vec3(uv, 2.0), vec3(0.0, 0.0, -1.0)); vec2 rm = raymarch(vec3(uv, 2.0), vec3(0.0, 0.0, -1.0));
vec3 p = vec3(uv, 2.0-rm.x); vec3 p = vec3(uv, 2.0-rm.x);
vec3 n = normal(p); vec3 n = normal(p);
@ -41,5 +41,5 @@ void fragment() {
float o = step(p.z, 0.001); float o = step(p.z, 0.001);
float shadow = 1.0-0.75*step(raymarch(l, -ld).x, length(l-p)-0.01); float shadow = 1.0-0.75*step(raymarch(l, -ld).x, length(l-p)-0.01);
float light = 0.3+0.7*dot(n, ld)*shadow; float light = 0.3+0.7*dot(n, ld)*shadow;
COLOR = vec4(mix(rm_color(fract(rm.y)), vec3(0.9), o)*light, 1.0); return vec4(mix(rm_color(fract(rm.y)), vec3(0.9), o)*light, 1.0);
} }

View File

@ -24,8 +24,8 @@ vec3 normal(vec3 p) {
return normalize(n); return normalize(n);
} }
void fragment() { vec4 preview_2d(vec2 uv) {
vec2 uv = UV-vec2(0.5); vec2 uv -= vec2(0.5);
vec3 p = vec3(uv, 2.0-raymarch(vec3(uv, 2.0), vec3(0.0, 0.0, -1.0))); vec3 p = vec3(uv, 2.0-raymarch(vec3(uv, 2.0), vec3(0.0, 0.0, -1.0)));
vec3 n = normal(p); vec3 n = normal(p);
vec3 l = vec3(5.0, 5.0, 10.0); vec3 l = vec3(5.0, 5.0, 10.0);
@ -33,5 +33,5 @@ void fragment() {
float o = step(p.z, 0.001); float o = step(p.z, 0.001);
float shadow = 1.0-0.75*step(raymarch(l, -ld), length(l-p)-0.01); float shadow = 1.0-0.75*step(raymarch(l, -ld), length(l-p)-0.01);
float light = 0.3+0.7*dot(n, ld)*shadow; float light = 0.3+0.7*dot(n, ld)*shadow;
COLOR = vec4(calcColor(vec4(p, 0.0))*light, 1.0); return vec4(calcColor(vec4(p, 0.0))*light, 1.0);
} }

View File

@ -583,33 +583,33 @@ func update_preview_2d(node = null) -> void:
node = n node = n
break break
if node != null: if node != null:
var result = node.generator.render(0, 1024, true) preview_2d.set_generator(node.generator)
while result is GDScriptFunctionState: preview_2d_background.set_generator(node.generator)
result = yield(result, "completed")
var tex = ImageTexture.new()
result.copy_to_texture(tex)
result.release()
preview_2d.set_preview_texture(tex)
preview_2d_background.set_preview_texture(tex)
else: else:
preview_2d.set_preview_texture(null) preview_2d.set_generator(null)
preview_2d_background.set_preview_texture(null) preview_2d_background.set_generator(null)
func update_preview_3d(previews : Array) -> void: func update_preview_3d(previews : Array) -> void:
var visible_previews = []
for p in previews:
if p.is_visible_in_tree():
visible_previews.push_back(p)
if visible_previews.empty():
return
var graph_edit : MMGraphEdit = get_current_graph_edit() var graph_edit : MMGraphEdit = get_current_graph_edit()
if graph_edit != null and graph_edit.top_generator != null and graph_edit.top_generator.has_node("Material"): if graph_edit != null and graph_edit.top_generator != null and graph_edit.top_generator.has_node("Material"):
var gen_material = graph_edit.top_generator.get_node("Material") var gen_material = graph_edit.top_generator.get_node("Material")
var status = gen_material.render_textures() var status = gen_material.render_textures()
while status is GDScriptFunctionState: while status is GDScriptFunctionState:
status = yield(status, "completed") status = yield(status, "completed")
for p in previews: for p in visible_previews:
gen_material.update_materials(p.get_materials()) gen_material.update_materials(p.get_materials())
var selected_node = null var selected_node = null
func on_selected_node_change(node) -> void: func on_selected_node_change(node) -> void:
if node != selected_node: if node != selected_node:
selected_node = node selected_node = node
preview_2d.setup_controls(node.generator if node != null else null) preview_2d.set_generator(node.generator if node != null else null)
update_preview_2d(node) update_preview_2d(node)
func _on_Projects_tab_changed(tab) -> void: func _on_Projects_tab_changed(tab) -> void:

View File

@ -1,24 +1,39 @@
extends ColorRect extends ColorRect
var generator = null export(String, MULTILINE) var shader : String = ""
func set_preview_texture(tex: Texture) -> void: var generator : MMGenBase = null
material.set_shader_param("tex", tex)
func on_resized() -> void: func set_generator(g : MMGenBase) -> void:
material.set_shader_param("size", rect_size) if generator != null and is_instance_valid(generator):
setup_controls(generator) generator.disconnect("float_param_changed", self, "on_float_param_changed")
var source = { defs="", code="", textures={}, type="f", f="1.0" }
func setup_controls(g : MMGenBase) -> void:
if is_instance_valid(g): if is_instance_valid(g):
generator = g generator = g
var param_defs : Array = generator.get_parameter_defs() var param_defs : Array = generator.get_parameter_defs()
for c in get_children(): for c in get_children():
c.setup_control(generator, param_defs) c.setup_control(generator, param_defs)
generator.connect("float_param_changed", self, "on_float_param_changed")
var gen_output_defs = generator.get_output_defs()
if ! gen_output_defs.empty():
var context : MMGenContext = MMGenContext.new()
source = generator.get_shader_code("uv", 0, context)
while source is GDScriptFunctionState:
source = yield(source, "completed")
if source.empty():
source = { defs="", code="", textures={}, type="f", f="1.0" }
else: else:
g = null g = null
for c in get_children(): for c in get_children():
c.setup_control(generator, []) c.setup_control(generator, [])
material.shader.code = MMGenBase.generate_preview_shader(source, source.type, shader)
func on_float_parameter_changed(n : String, v : float) -> void:
material.set_shader_param(n, v)
func on_resized() -> void:
material.set_shader_param("size", rect_size)
set_generator(generator)
func value_to_pos(value : Vector2) -> Vector2: func value_to_pos(value : Vector2) -> Vector2:
return rect_size*0.5+value*min(rect_size.x, rect_size.y)/1.2 return rect_size*0.5+value*min(rect_size.x, rect_size.y)/1.2

View File

@ -3,28 +3,14 @@
[ext_resource path="res://material_maker/preview/preview_2d.gd" type="Script" id=1] [ext_resource path="res://material_maker/preview/preview_2d.gd" type="Script" id=1]
[sub_resource type="Shader" id=1] [sub_resource type="Shader" id=1]
code = "shader_type canvas_item;
uniform sampler2D tex;
uniform vec2 size;
void fragment() {
float ms = max(size.x, size.y);
vec2 uv = fract(0.5+1.2*(UV-vec2(0.5))*ms/size.yx);
float is = min(size.x, size.y)/1.2;
vec2 m2 = min(fract(uv), 1.0-fract(uv));
vec4 image = texture(tex, uv);
vec3 image_with_background = mix(vec3(mod(floor(uv.x*32.0)+floor(uv.y*32.0), 2.0)), image.xyz, image.a);
float lines_color = 0.5*(cos(5.0*TIME+100.0*(uv.x+uv.y))+1.0);
COLOR = vec4(mix(image_with_background, vec3(lines_color), step(is*min(m2.x, m2.y), 1.0)), 1.0);
}"
[sub_resource type="ShaderMaterial" id=2] [sub_resource type="ShaderMaterial" id=2]
resource_local_to_scene = true resource_local_to_scene = true
shader = SubResource( 1 ) shader = SubResource( 1 )
shader_param/size = Vector2( 585, 492 )
[node name="Preview2D" type="ColorRect"] [node name="Preview2D" type="ColorRect" groups=[
"preview",
]]
material = SubResource( 2 ) material = SubResource( 2 )
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
@ -39,4 +25,16 @@ script = ExtResource( 1 )
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
shader = "uniform vec2 size;
void fragment() {
float ms = max(size.x, size.y);
vec2 uv = fract(0.5+1.2*(UV-vec2(0.5))*ms/size.yx);
float is = min(size.x, size.y)/1.2;
vec2 m2 = min(fract(uv), 1.0-fract(uv));
vec4 image = preview_2d(uv);
vec3 image_with_background = mix(vec3(mod(floor(uv.x*32.0)+floor(uv.y*32.0), 2.0)), image.xyz, image.a);
float lines_color = 0.5*(cos(5.0*TIME+100.0*(uv.x+uv.y))+1.0);
COLOR = vec4(mix(image_with_background, vec3(lines_color), step(is*min(m2.x, m2.y), 1.0)), 1.0);
}"
[connection signal="resized" from="." to="." method="on_resized"] [connection signal="resized" from="." to="." method="on_resized"]