Merge pull request #101 from RodZill4/dev-optimize

Optimized UI by avoiding shader regeneration whenever possible
This commit is contained in:
Rodz Labs 2020-03-28 10:01:40 +01:00 committed by GitHub
commit dc59af0c4e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 1098 additions and 1413 deletions

View File

@ -6,8 +6,7 @@ class_name MMGenBase
Base class for texture generators, that defines their API Base class for texture generators, that defines their API
""" """
signal parameter_changed signal parameter_changed(n, v)
signal output_changed(index)
class InputPort: class InputPort:
var generator : MMGenBase = null var generator : MMGenBase = null
@ -93,8 +92,8 @@ func init_parameters() -> void:
func set_position(p) -> void: func set_position(p) -> void:
position = p position = p
if has_randomness() and !is_seed_locked(): if has_randomness() and !is_seed_locked() and is_inside_tree():
source_changed(0) get_tree().call_group("preview", "on_float_parameters_changed", { "seed_o"+str(get_instance_id()): get_seed() })
func get_type() -> String: func get_type() -> String:
return "generic" return "generic"
@ -113,21 +112,60 @@ func get_parameter_def(param_name : String) -> Dictionary:
return {} return {}
func get_parameter(n : String): func get_parameter(n : String):
return parameters[n] if parameters.has(n):
return parameters[n]
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: func set_parameter(n : String, v) -> void:
var old_value = parameters[n] if parameters.has(n) else null
parameters[n] = v parameters[n] = v
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"):
if parameter_def.type == "float":
var parameter_name = "p_o"+str(get_instance_id())+"_"+n
get_tree().call_group("preview", "on_float_parameters_changed", { parameter_name:v })
return
elif parameter_def.type == "color":
var parameter_changes = {}
for f in [ "r", "g", "b", "a" ]:
var parameter_name = "p_o"+str(get_instance_id())+"_"+n+"_"+f
parameter_changes[parameter_name] = v[f]
get_tree().call_group("preview", "on_float_parameters_changed", parameter_changes)
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")
var parameter_changes = {}
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 ]
parameter_changes[parameter_name] = v.points[i][f]
get_tree().call_group("preview", "on_float_parameters_changed", parameter_changes)
return
source_changed(0)
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)
for target in targets: for target in targets:
target.generator.source_changed(target.input_index) target.generator.source_changed(target.input_index)
emit_signal("output_changed", output_index) emit_signal("parameter_changed", "__output_changed__", output_index)
func source_changed(__) -> void: func source_changed(input_index : int) -> void:
emit_signal("parameter_changed", "__input_changed__", 0) emit_signal("parameter_changed", "__input_changed__", input_index)
for i in range(get_output_defs().size()): for i in range(get_output_defs().size()):
notify_output_change(i) notify_output_change(i)
@ -162,7 +200,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"
@ -185,6 +223,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

@ -7,11 +7,16 @@ Texture generator buffers, that render their input in a specific resolution and
This is useful when using generators that sample their inputs several times (such as convolutions) This is useful when using generators that sample their inputs several times (such as convolutions)
""" """
var updated : bool = false var material : ShaderMaterial = null
var updating : bool = false
var update_again : bool = false
func _ready() -> void: func _ready() -> void:
material = ShaderMaterial.new()
material.shader = Shader.new()
if !parameters.has("size"): if !parameters.has("size"):
parameters.size = 9 parameters.size = 9
add_to_group("preview")
func get_type() -> String: func get_type() -> String:
return "buffer" return "buffer"
@ -31,24 +36,56 @@ func get_input_defs() -> Array:
func get_output_defs() -> Array: func get_output_defs() -> Array:
return [ { type="rgba" }, { type="rgba" } ] return [ { type="rgba" }, { type="rgba" } ]
func source_changed(input_port_index : int) -> void: func source_changed(_input_port_index : int) -> void:
updated = false call_deferred("update_shader")
.source_changed(input_port_index)
func _get_shader_code(uv : String, output_index : int, context : MMGenContext) -> Dictionary: func update_shader() -> void:
var source = get_source(0) var context : MMGenContext = MMGenContext.new()
if source != null and !updated: var source = {}
var result = source.generator.render(source.output_index, pow(2, parameters.size)) var source_output = get_source(0)
while result is GDScriptFunctionState: if source_output != null:
result = yield(result, "completed") source = source_output.generator.get_shader_code("uv", source_output.output_index, context)
result.copy_to_texture(texture) while source is GDScriptFunctionState:
result.release() source = yield(source, "completed")
texture.flags = Texture.FLAG_MIPMAPS if source.empty():
updated = true source = { defs="", code="", textures={}, rgba="vec4(0.0)" }
var rv = ._get_shader_code_lod(uv, output_index, context, 0 if output_index == 0 else parameters.lod) material.shader.code = mm_renderer.generate_shader(source)
while rv is GDScriptFunctionState: if source.has("textures"):
rv = yield(rv, "completed") for k in source.textures.keys():
return rv material.set_shader_param(k, source.textures[k])
update_buffer()
func on_float_parameters_changed(parameter_changes : Dictionary) -> void:
var do_update : bool = false
for n in parameter_changes.keys():
for p in VisualServer.shader_get_param_list(material.shader.get_rid()):
if p.name == n:
material.set_shader_param(n, parameter_changes[n])
do_update = true
break
if do_update:
update_buffer()
func on_texture_changed(n : String) -> void:
for p in VisualServer.shader_get_param_list(material.shader.get_rid()):
if p.name == n:
update_buffer()
return
func update_buffer() -> void:
update_again = true
if !updating:
updating = true
while update_again:
update_again = false
var result = mm_renderer.render_material(material, pow(2, get_parameter("size")))
while result is GDScriptFunctionState:
result = yield(result, "completed")
if !update_again:
result.copy_to_texture(texture)
result.release()
updating = false
get_tree().call_group("preview", "on_texture_changed", "o%s_tex" % str(get_instance_id()))
func _serialize(data: Dictionary) -> Dictionary: func _serialize(data: Dictionary) -> Dictionary:
data.type = "buffer" data.type = "buffer"

View File

@ -5,7 +5,12 @@ class_name MMGenMaterial
var export_paths = {} var export_paths = {}
var material : SpatialMaterial var material : SpatialMaterial
var shader_materials = {}
var need_update = {}
var need_render = {}
var generated_textures = {} var generated_textures = {}
var updating : bool = false
var update_again : bool = false
const TEXTURE_LIST = [ const TEXTURE_LIST = [
{ port=0, texture="albedo", sources=[0] }, { port=0, texture="albedo", sources=[0] },
@ -38,7 +43,12 @@ const TEXTURE_SIZE_DEFAULT = 10 # 1024x1024
func _ready() -> void: func _ready() -> void:
for t in TEXTURE_LIST: for t in TEXTURE_LIST:
generated_textures[t.texture] = null generated_textures[t.texture] = null
need_update[t.texture] = true
need_render[t.texture] = true
shader_materials[t.texture] = ShaderMaterial.new()
shader_materials[t.texture].shader = Shader.new()
material = SpatialMaterial.new() material = SpatialMaterial.new()
add_to_group("preview")
func can_be_deleted() -> bool: func can_be_deleted() -> bool:
return false return false
@ -74,34 +84,86 @@ func set_parameter(p, v) -> void:
func source_changed(input_index : int) -> void: func source_changed(input_index : int) -> void:
for t in TEXTURE_LIST: for t in TEXTURE_LIST:
if t.has("sources") and t.sources.find(input_index) != -1: if t.has("sources") and t.sources.find(input_index) != -1:
generated_textures[t.texture] = null need_update[t.texture] = true
update_preview() update_preview()
func render_textures() -> void: func render_textures() -> void:
for t in TEXTURE_LIST: for t in TEXTURE_LIST:
var texture = null
var result var result
if t.has("port"): if t.has("port"):
if generated_textures[t.texture] != null: if !need_update[t.texture]:
continue continue
result = render(t.port, get_image_size()) var context : MMGenContext = MMGenContext.new()
var source = get_shader_code("uv", t.port, context)
while source is GDScriptFunctionState:
source = yield(source, "completed")
if source.empty():
source = { defs="", code="", textures={}, rgba="vec4(0.0)" }
shader_materials[t.texture].shader.code = mm_renderer.generate_shader(source)
if source.has("textures"):
for k in source.textures.keys():
shader_materials[t.texture].set_shader_param(k, source.textures[k])
result = mm_renderer.render_material(shader_materials[t.texture], get_image_size(), false)
else: else:
generated_textures[t.texture] = null generated_textures[t.texture] = null
need_update[t.texture] = false
continue continue
while result is GDScriptFunctionState: while result is GDScriptFunctionState:
result = yield(result, "completed") result = yield(result, "completed")
texture = ImageTexture.new() if generated_textures[t.texture] == null:
generated_textures[t.texture] = ImageTexture.new()
var texture = generated_textures[t.texture]
result.copy_to_texture(texture) result.copy_to_texture(texture)
result.release() result.release()
# To work, this must be set after calling `copy_to_texture()` # To work, this must be set after calling `copy_to_texture()`
texture.flags |= ImageTexture.FLAG_ANISOTROPIC_FILTER texture.flags |= ImageTexture.FLAG_ANISOTROPIC_FILTER
# Disable filtering for small textures, as they're considered to be used # Disable filtering for small textures, as they're considered to be used
# for a pixel art style # for a pixel art style
if texture.get_size().x <= 128: if texture.get_size().x <= 128:
texture.flags ^= ImageTexture.FLAG_FILTER texture.flags ^= ImageTexture.FLAG_FILTER
need_update[t.texture] = false
generated_textures[t.texture] = texture func on_float_parameters_changed(parameter_changes : Dictionary) -> void:
var do_update : bool = false
for t in TEXTURE_LIST:
if generated_textures[t.texture] != null:
for n in parameter_changes.keys():
for p in VisualServer.shader_get_param_list(shader_materials[t.texture].shader.get_rid()):
if p.name == n:
shader_materials[t.texture].set_shader_param(n, parameter_changes[n])
need_render[t.texture] = true
do_update = true
break
if do_update:
update_textures()
func on_texture_changed(n : String) -> void:
var do_update : bool = false
for t in TEXTURE_LIST:
if generated_textures[t.texture] != null:
for p in VisualServer.shader_get_param_list(shader_materials[t.texture].shader.get_rid()):
if p.name == n:
need_render[t.texture] = true
do_update = true
break
if do_update:
update_textures()
func update_textures() -> void:
update_again = true
if !updating:
var image_size = get_image_size()
updating = true
while update_again:
update_again = false
for t in TEXTURE_LIST:
if need_render[t.texture]:
var result = mm_renderer.render_material(shader_materials[t.texture], image_size, false)
while result is GDScriptFunctionState:
result = yield(result, "completed")
result.copy_to_texture(generated_textures[t.texture])
result.release()
updating = false
func update_materials(material_list) -> void: func update_materials(material_list) -> void:
render_textures() render_textures()

View File

@ -18,9 +18,11 @@ func toggle_editable() -> bool:
func is_editable() -> bool: func is_editable() -> bool:
return editable return editable
func has_randomness() -> bool: func has_randomness() -> bool:
return uses_seed return uses_seed
func get_type() -> String: func get_type() -> String:
return "shader" return "shader"
@ -70,6 +72,7 @@ func set_shader_model(data: Dictionary) -> void:
if shader_model.has("instance"): if shader_model.has("instance"):
if shader_model.instance.find("$seed") != -1 or shader_model.instance.find("$(seed)") != -1: if shader_model.instance.find("$seed") != -1 or shader_model.instance.find("$(seed)") != -1:
uses_seed = true uses_seed = true
source_changed(0)
func find_keyword_call(string, keyword): func find_keyword_call(string, keyword):
var search_string = "$%s(" % keyword var search_string = "$%s(" % keyword
@ -178,7 +181,7 @@ func subst(string : String, context : MMGenContext, uv : String = "") -> Diction
if uv != "": if uv != "":
var genname_uv = genname+"_"+str(context.get_variant(self, uv)) var genname_uv = genname+"_"+str(context.get_variant(self, uv))
string = replace_variable(string, "name_uv", genname_uv) string = replace_variable(string, "name_uv", genname_uv)
var tmp_string = replace_variable(string, "seed", str(get_seed())) var tmp_string = replace_variable(string, "seed", "seed_"+genname)
if tmp_string != string: if tmp_string != string:
string = tmp_string string = tmp_string
if shader_model.has("parameters") and typeof(shader_model.parameters) == TYPE_ARRAY: if shader_model.has("parameters") and typeof(shader_model.parameters) == TYPE_ARRAY:
@ -188,7 +191,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":
@ -196,9 +199,9 @@ func subst(string : String, context : MMGenContext, uv : String = "") -> Diction
value = 0 value = 0
value_string = p.values[value].value value_string = p.values[value].value
elif p.type == "color": elif p.type == "color":
value_string = "vec4(%.9f, %.9f, %.9f, %.9f)" % [ value.r, value.g, value.b, value.a ] value_string = "vec4(p_%s_%s_r, p_%s_%s_g, p_%s_%s_b, p_%s_%s_a)" % [ genname, p.name, genname, p.name, genname, p.name, genname, p.name ]
elif p.type == "gradient": elif p.type == "gradient":
value_string = genname+"_p_"+p.name+"_gradient_fct" value_string = genname+"_"+p.name+"_gradient_fct"
elif p.type == "boolean": elif p.type == "boolean":
value_string = "true" if value else "false" value_string = "true" if value else "false"
else: else:
@ -246,13 +249,25 @@ func _get_shader_code(uv : String, output_index : int, context : MMGenContext) -
var output = shader_model.outputs[output_index] var output = shader_model.outputs[output_index]
if !context.has_variant(self): if !context.has_variant(self):
# Generate functions for gradients # Generate functions for gradients
if has_randomness():
rv.defs += "uniform int seed_%s = %d;\n" % [ genname, get_seed() ]
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 == "color":
rv.defs += "uniform float p_%s_%s_r = %.9f;\n" % [ genname, p.name, parameters[p.name].r ]
rv.defs += "uniform float p_%s_%s_g = %.9f;\n" % [ genname, p.name, parameters[p.name].g ]
rv.defs += "uniform float p_%s_%s_b = %.9f;\n" % [ genname, p.name, parameters[p.name].b ]
rv.defs += "uniform float p_%s_%s_a = %.9f;\n" % [ genname, p.name, parameters[p.name].a ]
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()
g.deserialize(parameters[p.name]) 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 # Generate functions for inputs
if shader_model.has("inputs"): if shader_model.has("inputs"):
for i in range(shader_model.inputs.size()): for i in range(shader_model.inputs.size()):

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
@ -73,6 +73,9 @@ func set_parameter(p, v) -> void:
parent.reconnect_outputs(self, outputs_changes) parent.reconnect_outputs(self, outputs_changes)
.set_parameter(p, v) .set_parameter(p, v)
emit_signal("parameter_changed", "__update_all__", null) emit_signal("parameter_changed", "__update_all__", null)
if p == "source":
for i in range(int(parameters.outputs)):
notify_output_change(i)
# get the list of outputs that depend on the input whose index is passed as parameter # get the list of outputs that depend on the input whose index is passed as parameter
func follow_input(input_index : int) -> Array: func follow_input(input_index : int) -> Array:
@ -89,7 +92,7 @@ func _get_shader_code(uv : String, output_index : int, context : MMGenContext) -
while rv is GDScriptFunctionState: while rv is GDScriptFunctionState:
rv = yield(rv, "completed") rv = yield(rv, "completed")
return rv return rv
return { globals=[], defs="", code="", textures={} } return { globals=[], defs="", code="", textures={}, type="f", f="0.0" }
func _serialize(data: Dictionary) -> Dictionary: func _serialize(data: Dictionary) -> Dictionary:
return data return data

View File

@ -5,19 +5,24 @@ class_name MMGenRenderer
export(String) var debug_path = "" export(String) var debug_path = ""
var debug_file_index : int = 0 var debug_file_index : int = 0
var common_shader : String
var rendering : bool = false var rendering : bool = false
signal done signal done
func _ready() -> void: func _ready() -> void:
$ColorRect.material = $ColorRect.material.duplicate(true) $ColorRect.material = $ColorRect.material.duplicate(true)
var file = File.new()
file.open("res://addons/material_maker/common.shader", File.READ)
common_shader = file.get_as_text()
static func generate_shader(src_code) -> String: func generate_shader(src_code) -> 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"
var file = File.new() code += common_shader
file.open("res://addons/material_maker/common.shader", File.READ)
code += file.get_as_text()
code += "\n" code += "\n"
if src_code.has("textures"): if src_code.has("textures"):
for t in src_code.textures.keys(): for t in src_code.textures.keys():
@ -38,52 +43,28 @@ static func generate_shader(src_code) -> String:
code += shader_code code += shader_code
return code return code
static func generate_combined_shader(red_code, green_code, blue_code) -> String:
var code
code = "shader_type canvas_item;\n"
code += "render_mode blend_disabled;\n"
var file = File.new()
file.open("res://addons/material_maker/common.shader", File.READ)
code += file.get_as_text()
code += "\n"
var globals = []
var textures = {}
var output = []
for c in [ red_code, green_code, blue_code ]:
if c.has("textures"):
for t in c.textures.keys():
textures[t] = c.textures[t]
if c.has("globals"):
for g in c.globals:
if globals.find(g) == -1:
globals.push_back(g)
if c.has("f"):
output.push_back(c.f)
else:
output.push_back("1.0")
for t in textures.keys():
code += "uniform sampler2D "+t+";\n"
for g in globals:
code += g
var shader_code = ""
shader_code += red_code.defs
shader_code += green_code.defs
shader_code += blue_code.defs
shader_code += "void fragment() {\n"
shader_code += red_code.code
shader_code += green_code.code
shader_code += blue_code.code
shader_code += "COLOR = vec4("+output[0]+", "+output[1]+", "+output[2]+", 1.0);\n"
shader_code += "}\n"
#print("GENERATED COMBINED SHADER:\n"+shader_code)
code += shader_code
return code
func setup_material(shader_material, textures, shader_code) -> void: func setup_material(shader_material, textures, shader_code) -> void:
for k in textures.keys(): for k in textures.keys():
shader_material.set_shader_param(k+"_tex", textures[k]) shader_material.set_shader_param(k+"_tex", textures[k])
shader_material.shader.code = shader_code shader_material.shader.code = shader_code
func render_material(material, render_size, with_hdr = true) -> Object:
while rendering:
yield(self, "done")
rendering = true
var shader_material = $ColorRect.material
size = Vector2(render_size, render_size)
$ColorRect.rect_position = Vector2(0, 0)
$ColorRect.rect_size = size
$ColorRect.material = material
hdr = with_hdr
render_target_update_mode = Viewport.UPDATE_ONCE
update_worlds()
yield(get_tree(), "idle_frame")
yield(get_tree(), "idle_frame")
$ColorRect.material = shader_material
return self
func render_shader(shader, textures, render_size) -> Object: func render_shader(shader, textures, render_size) -> Object:
if debug_path != null and debug_path != "": if debug_path != null and debug_path != "":
var file_name = debug_path+str(debug_file_index)+".shader" var file_name = debug_path+str(debug_file_index)+".shader"
@ -126,4 +107,5 @@ func save_to_file(fn : String) -> void:
func release() -> void: func release() -> void:
rendering = false rendering = false
hdr = false
emit_signal("done") emit_signal("done")

View File

@ -18,7 +18,6 @@ own_world = true
transparent_bg = true transparent_bg = true
hdr = false hdr = false
keep_3d_linear = true keep_3d_linear = true
usage = 0
render_target_v_flip = true render_target_v_flip = true
render_target_update_mode = 1 render_target_update_mode = 1
gui_disable_input = true gui_disable_input = true

View File

@ -22,7 +22,7 @@
"type": "f" "type": "f"
}, },
{ {
"rgb": "rand3(fract($(name_uv)_center.zw/vec2($sx, $sy))+vec2($seed))", "rgb": "rand3(fract($(name_uv)_center.zw/vec2($sx, $sy))+vec2(float($seed)))",
"type": "rgb" "type": "rgb"
}, },
{ {

View File

@ -29,7 +29,7 @@
"type": "f" "type": "f"
}, },
{ {
"rgb": "rand3(fract($(name_uv)_rect.xy)+rand2(vec2($seed)))", "rgb": "rand3(fract($(name_uv)_rect.xy)+rand2(vec2(float($seed))))",
"type": "rgb" "type": "rgb"
}, },
{ {

View File

@ -13,7 +13,7 @@
}, },
"shader_model": { "shader_model": {
"code": "", "code": "",
"global": "float fbm_value(vec2 coord, vec2 size, float seed) {\n\tvec2 o = floor(coord)+rand2(vec2(float(seed), 1.0-float(seed)))+size;\n\tvec2 f = fract(coord);\n\tfloat p00 = rand(mod(o, size));\n\tfloat p01 = rand(mod(o + vec2(0.0, 1.0), size));\n\tfloat p10 = rand(mod(o + vec2(1.0, 0.0), size));\n\tfloat p11 = rand(mod(o + vec2(1.0, 1.0), size));\n\tvec2 t = f * f * (3.0 - 2.0 * f);\n\treturn mix(mix(p00, p10, t.x), mix(p01, p11, t.x), t.y);\n}\n\nfloat fbm_perlin(vec2 coord, vec2 size, float seed) {\n\tvec2 o = floor(coord)+rand2(vec2(float(seed), 1.0-float(seed)))+size;\n\tvec2 f = fract(coord);\n\tfloat a00 = rand(mod(o, size)) * 6.28318530718;\n\tfloat a01 = rand(mod(o + vec2(0.0, 1.0), size)) * 6.28318530718;\n\tfloat a10 = rand(mod(o + vec2(1.0, 0.0), size)) * 6.28318530718;\n\tfloat a11 = rand(mod(o + vec2(1.0, 1.0), size)) * 6.28318530718;\n\tvec2 v00 = vec2(cos(a00), sin(a00));\n\tvec2 v01 = vec2(cos(a01), sin(a01));\n\tvec2 v10 = vec2(cos(a10), sin(a10));\n\tvec2 v11 = vec2(cos(a11), sin(a11));\n\tfloat p00 = dot(v00, f);\n\tfloat p01 = dot(v01, f - vec2(0.0, 1.0));\n\tfloat p10 = dot(v10, f - vec2(1.0, 0.0));\n\tfloat p11 = dot(v11, f - vec2(1.0, 1.0));\n\tvec2 t = f * f * (3.0 - 2.0 * f);\n\treturn 0.5 + mix(mix(p00, p10, t.x), mix(p01, p11, t.x), t.y);\n}\n\nfloat fbm_cellular(vec2 coord, vec2 size, float seed) {\n\tvec2 o = floor(coord)+rand2(vec2(float(seed), 1.0-float(seed)))+size;\n\tvec2 f = fract(coord);\n\tfloat min_dist = 2.0;\n\tfor(float x = -1.0; x <= 1.0; x++) {\n\t\tfor(float y = -1.0; y <= 1.0; y++) {\n\t\t\tvec2 node = rand2(mod(o + vec2(x, y), size)) + vec2(x, y);\n\t\t\tfloat dist = sqrt((f - node).x * (f - node).x + (f - node).y * (f - node).y);\n\t\t\tmin_dist = min(min_dist, dist);\n\t\t}\n\t}\n\treturn min_dist;\n}\n", "global": "float fbm_value(vec2 coord, vec2 size, float seed) {\n\tvec2 o = floor(coord)+rand2(vec2(float(seed), 1.0-float(seed)))+size;\n\tvec2 f = fract(coord);\n\tfloat p00 = rand(mod(o, size));\n\tfloat p01 = rand(mod(o + vec2(0.0, 1.0), size));\n\tfloat p10 = rand(mod(o + vec2(1.0, 0.0), size));\n\tfloat p11 = rand(mod(o + vec2(1.0, 1.0), size));\n\tvec2 t = f * f * (3.0 - 2.0 * f);\n\treturn mix(mix(p00, p10, t.x), mix(p01, p11, t.x), t.y);\n}\n\nfloat fbm_perlin(vec2 coord, vec2 size, float seed) {\n\tvec2 o = floor(coord)+rand2(vec2(float(seed), 1.0-float(seed)))+size;\n\tvec2 f = fract(coord);\n\tfloat a00 = rand(mod(o, size)) * 6.28318530718;\n\tfloat a01 = rand(mod(o + vec2(0.0, 1.0), size)) * 6.28318530718;\n\tfloat a10 = rand(mod(o + vec2(1.0, 0.0), size)) * 6.28318530718;\n\tfloat a11 = rand(mod(o + vec2(1.0, 1.0), size)) * 6.28318530718;\n\tvec2 v00 = vec2(cos(a00), sin(a00));\n\tvec2 v01 = vec2(cos(a01), sin(a01));\n\tvec2 v10 = vec2(cos(a10), sin(a10));\n\tvec2 v11 = vec2(cos(a11), sin(a11));\n\tfloat p00 = dot(v00, f);\n\tfloat p01 = dot(v01, f - vec2(0.0, 1.0));\n\tfloat p10 = dot(v10, f - vec2(1.0, 0.0));\n\tfloat p11 = dot(v11, f - vec2(1.0, 1.0));\n\tvec2 t = f * f * (3.0 - 2.0 * f);\n\treturn 0.5 + mix(mix(p00, p10, t.x), mix(p01, p11, t.x), t.y);\n}\n\nfloat fbm_cellular(vec2 coord, vec2 size, float seed) {\n\tvec2 o = floor(coord)+rand2(vec2(float(seed), 1.0-float(seed)))+size;\n\tvec2 f = fract(coord);\n\tfloat min_dist = 2.0;\n\tfor(float x = -1.0; x <= 1.0; x++) {\n\t\tfor(float y = -1.0; y <= 1.0; y++) {\n\t\t\tvec2 node = rand2(mod(o + vec2(x, y), size)) + vec2(x, y);\n\t\t\tfloat dist = sqrt((f - node).x * (f - node).x + (f - node).y * (f - node).y);\n\t\t\tmin_dist = min(min_dist, dist);\n\t\t}\n\t}\n\treturn min_dist;\n}\n\nfloat fbm_cellular2(vec2 coord, vec2 size, float seed) {\n\tvec2 o = floor(coord)+rand2(vec2(float(seed), 1.0-float(seed)))+size;\n\tvec2 f = fract(coord);\n\tfloat min_dist1 = 2.0;\n\tfloat min_dist2 = 2.0;\n\tfor(float x = -1.0; x <= 1.0; x++) {\n\t\tfor(float y = -1.0; y <= 1.0; y++) {\n\t\t\tvec2 node = rand2(mod(o + vec2(x, y), size)) + vec2(x, y);\n\t\t\tfloat dist = sqrt((f - node).x * (f - node).x + (f - node).y * (f - node).y);\n\t\t\tif (min_dist1 > dist) {\n\t\t\t\tmin_dist2 = min_dist1;\n\t\t\t\tmin_dist1 = dist;\n\t\t\t} else if (min_dist2 > dist) {\n\t\t\t\tmin_dist2 = dist;\n\t\t\t}\n\t\t}\n\t}\n\treturn min_dist2-min_dist1;\n}\n\nfloat fbm_cellular3(vec2 coord, vec2 size, float seed) {\n\tvec2 o = floor(coord)+rand2(vec2(float(seed), 1.0-float(seed)))+size;\n\tvec2 f = fract(coord);\n\tfloat min_dist = 2.0;\n\tfor(float x = -1.0; x <= 1.0; x++) {\n\t\tfor(float y = -1.0; y <= 1.0; y++) {\n\t\t\tvec2 node = rand2(mod(o + vec2(x, y), size))*0.5 + vec2(x, y);\n\t\t\tfloat dist = abs((f - node).x) + abs((f - node).y);\n\t\t\tmin_dist = min(min_dist, dist);\n\t\t}\n\t}\n\treturn min_dist;\n}\n\nfloat fbm_cellular4(vec2 coord, vec2 size, float seed) {\n\tvec2 o = floor(coord)+rand2(vec2(float(seed), 1.0-float(seed)))+size;\n\tvec2 f = fract(coord);\n\tfloat min_dist1 = 2.0;\n\tfloat min_dist2 = 2.0;\n\tfor(float x = -1.0; x <= 1.0; x++) {\n\t\tfor(float y = -1.0; y <= 1.0; y++) {\n\t\t\tvec2 node = rand2(mod(o + vec2(x, y), size))*0.5 + vec2(x, y);\n\t\t\tfloat dist = abs((f - node).x) + abs((f - node).y);\n\t\t\tif (min_dist1 > dist) {\n\t\t\t\tmin_dist2 = min_dist1;\n\t\t\t\tmin_dist1 = dist;\n\t\t\t} else if (min_dist2 > dist) {\n\t\t\t\tmin_dist2 = dist;\n\t\t\t}\n\t\t}\n\t}\n\treturn min_dist2-min_dist1;\n}\n\nfloat fbm_cellular5(vec2 coord, vec2 size, float seed) {\n\tvec2 o = floor(coord)+rand2(vec2(float(seed), 1.0-float(seed)))+size;\n\tvec2 f = fract(coord);\n\tfloat min_dist = 2.0;\n\tfor(float x = -1.0; x <= 1.0; x++) {\n\t\tfor(float y = -1.0; y <= 1.0; y++) {\n\t\t\tvec2 node = rand2(mod(o + vec2(x, y), size)) + vec2(x, y);\n\t\t\tfloat dist = max(abs((f - node).x), abs((f - node).y));\n\t\t\tmin_dist = min(min_dist, dist);\n\t\t}\n\t}\n\treturn min_dist;\n}\n\nfloat fbm_cellular6(vec2 coord, vec2 size, float seed) {\n\tvec2 o = floor(coord)+rand2(vec2(float(seed), 1.0-float(seed)))+size;\n\tvec2 f = fract(coord);\n\tfloat min_dist1 = 2.0;\n\tfloat min_dist2 = 2.0;\n\tfor(float x = -1.0; x <= 1.0; x++) {\n\t\tfor(float y = -1.0; y <= 1.0; y++) {\n\t\t\tvec2 node = rand2(mod(o + vec2(x, y), size)) + vec2(x, y);\n\t\t\tfloat dist = max(abs((f - node).x), abs((f - node).y));\n\t\t\tif (min_dist1 > dist) {\n\t\t\t\tmin_dist2 = min_dist1;\n\t\t\t\tmin_dist1 = dist;\n\t\t\t} else if (min_dist2 > dist) {\n\t\t\t\tmin_dist2 = dist;\n\t\t\t}\n\t\t}\n\t}\n\treturn min_dist2-min_dist1;\n}\n",
"inputs": [ "inputs": [
], ],
@ -21,13 +21,13 @@
"name": "FBM", "name": "FBM",
"outputs": [ "outputs": [
{ {
"f": "$(name)_fbm($(uv), vec2($(scale_x), $(scale_y)), int($(iterations)), $(persistence), $(seed))", "f": "$(name)_fbm($(uv), vec2($(scale_x), $(scale_y)), int($(iterations)), $(persistence), float($(seed)))",
"type": "f" "type": "f"
} }
], ],
"parameters": [ "parameters": [
{ {
"default": 2, "default": 7,
"label": "Noise", "label": "Noise",
"name": "noise", "name": "noise",
"type": "enum", "type": "enum",
@ -43,6 +43,26 @@
{ {
"name": "Cellular", "name": "Cellular",
"value": "cellular" "value": "cellular"
},
{
"name": "Cellular2",
"value": "cellular2"
},
{
"name": "Cellular3",
"value": "cellular3"
},
{
"name": "Cellular4",
"value": "cellular4"
},
{
"name": "Cellular5",
"value": "cellular5"
},
{
"name": "Cellular6",
"value": "cellular6"
} }
] ]
}, },

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); 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

@ -5,7 +5,6 @@
"y": 0 "y": 0
}, },
"parameters": { "parameters": {
"Randomness": 0.5,
"angle": -1, "angle": -1,
"layers": 5, "layers": 5,
"length": 0.25, "length": 0.25,
@ -23,12 +22,13 @@
"name": "Scratches", "name": "Scratches",
"outputs": [ "outputs": [
{ {
"f": "scratches($uv, int($layers), vec2($length, $width), $waviness, $angle, $randomness, vec2($seed, 0.0))", "f": "scratches($uv, int($layers), vec2($length, $width), $waviness, $angle, $randomness, vec2(float($seed), 0.0))",
"type": "f" "type": "f"
} }
], ],
"parameters": [ "parameters": [
{ {
"control": "None",
"default": 0.25, "default": 0.25,
"label": "Length", "label": "Length",
"max": 1, "max": 1,
@ -38,6 +38,7 @@
"type": "float" "type": "float"
}, },
{ {
"control": "None",
"default": 0.5, "default": 0.5,
"label": "Width", "label": "Width",
"max": 1, "max": 1,
@ -47,6 +48,7 @@
"type": "float" "type": "float"
}, },
{ {
"control": "None",
"default": 4, "default": 4,
"label": "Layers", "label": "Layers",
"max": 10, "max": 10,
@ -56,6 +58,7 @@
"type": "float" "type": "float"
}, },
{ {
"control": "None",
"default": 0.5, "default": 0.5,
"label": "Waviness", "label": "Waviness",
"max": 1, "max": 1,
@ -65,6 +68,7 @@
"type": "float" "type": "float"
}, },
{ {
"control": "None",
"default": 0, "default": 0,
"label": "Angle", "label": "Angle",
"max": 180, "max": 180,
@ -74,6 +78,7 @@
"type": "float" "type": "float"
}, },
{ {
"control": "None",
"default": 0.5, "default": 0.5,
"label": "Randomness", "label": "Randomness",
"max": 1, "max": 1,

View File

@ -5,14 +5,9 @@
"y": 0 "y": 0
}, },
"parameters": { "parameters": {
"a": 0,
"r": 0.3, "r": 0.3,
"rx": 3, "rx": 3,
"ry": 3, "ry": 3
"s": 0.3,
"x": 0.35,
"y": 0,
"z": 0
}, },
"shader_model": { "shader_model": {
"code": "", "code": "",
@ -29,7 +24,7 @@
"name": "Repeat", "name": "Repeat",
"outputs": [ "outputs": [
{ {
"sdf3dc": "$in(repeat($uv, vec3(1.0/$rx, 1.0/$ry, 0.0), $seed, $r))", "sdf3dc": "$in(repeat($uv, vec3(1.0/$rx, 1.0/$ry, 0.0), float($seed), $r))",
"type": "sdf3dc" "type": "sdf3dc"
} }
], ],

View File

@ -33,7 +33,7 @@
"name": "Splatter", "name": "Splatter",
"outputs": [ "outputs": [
{ {
"f": "splatter_$(name)($uv, int($count), vec2($seed))", "f": "splatter_$(name)($uv, int($count), vec2(float($seed)))",
"type": "f" "type": "f"
} }
], ],

View File

@ -33,7 +33,7 @@
"name": "Color Splatter", "name": "Color Splatter",
"outputs": [ "outputs": [
{ {
"rgba": "splatter_$(name)($uv, int($count), vec2($seed))", "rgba": "splatter_$(name)($uv, int($count), vec2(float($seed)))",
"type": "rgba" "type": "rgba"
} }
], ],

View File

@ -22,7 +22,7 @@
"name": "TEX3D FBM", "name": "TEX3D FBM",
"outputs": [ "outputs": [
{ {
"tex3d": "vec3($(name)_fbm($(uv).xyz, vec3($(scale_x), $(scale_y), $(scale_z)), int($(iterations)), $(persistence), $(seed)))", "tex3d": "vec3($(name)_fbm($(uv).xyz, vec3($(scale_x), $(scale_y), $(scale_z)), int($(iterations)), $(persistence), float($(seed))))",
"type": "tex3d" "type": "tex3d"
} }
], ],

View File

@ -15,7 +15,7 @@
}, },
"shader_model": { "shader_model": {
"code": "", "code": "",
"global": "float wave3d_constant(float x) {\n\treturn 1.0;\n}\n\nfloat wave3d_sine(float x) {\n\treturn 0.5-0.5*cos(3.14159265359*2.0*x);\n}\n\nfloat wave3d_triangle(float x) {\n\tx = fract(x);\n\treturn min(2.0*x, 2.0-2.0*x);\n}\n\nfloat wave3d_sawtooth(float x) {\n\treturn fract(x);\n}\n\nfloat wave3d_square(float x) {\n\treturn (fract(x) < 0.5) ? 0.0 : 1.0;\n}\n\nfloat wave3d_bounce(float x) {\n\tx = 2.0*(fract(x)-0.5);\n\treturn sqrt(1.0-x*x);\n}\n\nfloat mix3d_mul(float x, float y, float z) {\n\treturn x*y*z;\n}\n\nfloat mix3d_add(float x, float y, float z) {\n\treturn min(x+y+z, 1.0);\n}\n\nfloat mix3d_max(float x, float y, float z) {\n\treturn max(max(x, y), z);\n}\n\nfloat mix_min(float x, float y, float z) {\n\treturn min(min(x, y), z);\n}\n\nfloat mix3d_xor(float x, float y, float z) {\n\tfloat xy = min(x+y, 2.0-x-y);\n\treturn min(xy+z, 2.0-xy-z);\n}\n\nfloat mix3d_pow(float x, float y, float z) {\n\treturn pow(pow(x, y), z);\n}", "global": "float wave3d_constant(float x) {\n\treturn 1.0;\n}\n\nfloat wave3d_sine(float x) {\n\treturn 0.5-0.5*cos(3.14159265359*2.0*x);\n}\n\nfloat wave3d_triangle(float x) {\n\tx = fract(x);\n\treturn min(2.0*x, 2.0-2.0*x);\n}\n\nfloat wave3d_sawtooth(float x) {\n\treturn fract(x);\n}\n\nfloat wave3d_square(float x) {\n\treturn (fract(x) < 0.5) ? 0.0 : 1.0;\n}\n\nfloat wave3d_bounce(float x) {\n\tx = 2.0*(fract(x)-0.5);\n\treturn sqrt(1.0-x*x);\n}\n\nfloat mix3d_mul(float x, float y, float z) {\n\treturn x*y*z;\n}\n\nfloat mix3d_add(float x, float y, float z) {\n\treturn min(x+y+z, 1.0);\n}\n\nfloat mix3d_max(float x, float y, float z) {\n\treturn max(max(x, y), z);\n}\n\nfloat mix3d_min(float x, float y, float z) {\n\treturn min(min(x, y), z);\n}\n\nfloat mix3d_xor(float x, float y, float z) {\n\tfloat xy = min(x+y, 2.0-x-y);\n\treturn min(xy+z, 2.0-xy-z);\n}\n\nfloat mix3d_pow(float x, float y, float z) {\n\treturn pow(pow(x, y), z);\n}",
"inputs": [ "inputs": [
], ],

View File

@ -36,7 +36,7 @@
"name": "Tiler", "name": "Tiler",
"outputs": [ "outputs": [
{ {
"f": "tiler_$(name)($uv, vec2($tx, $ty), int($overlap), vec2($seed))", "f": "tiler_$(name)($uv, vec2($tx, $ty), int($overlap), vec2(float($seed)))",
"type": "f" "type": "f"
} }
], ],

View File

@ -36,7 +36,7 @@
"name": "Color Tiler", "name": "Color Tiler",
"outputs": [ "outputs": [
{ {
"rgba": "tiler_$(name)($uv, vec2($tx, $ty), int($overlap), vec2($seed))", "rgba": "tiler_$(name)($uv, vec2($tx, $ty), int($overlap), vec2(float($seed)))",
"type": "rgba" "type": "rgba"
} }
], ],

View File

@ -33,6 +33,9 @@ func add_point(v, c) -> void:
func sort() -> void: func sort() -> void:
if !sorted: if !sorted:
points.sort_custom(CustomSorter, "compare") 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 sorted = true
func get_color(x) -> Color: func get_color(x) -> Color:
@ -52,69 +55,81 @@ func get_color(x) -> Color:
else: else:
return Color(0.0, 0.0, 0.0, 1.0) 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 # get_color_in_shader
func gcis(color) -> String: func gcis(color) -> String:
return "vec4(%.9f,%.9f,%.9f,%.9f)" % [color.r, color.g, color.b, color.a] 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: func get_shader(name) -> String:
sort() sort()
var shader var shader
shader = "vec4 "+name+"(float x) {\n" shader = "vec4 "+name+"_gradient_fct(float x) {\n"
match interpolation: match interpolation:
0: 0:
if points.size() > 0: if points.size() > 0:
shader += " if (x < %.9f) {\n" % (0.5*(points[0].v + points[1].v)) shader += " if (x < 0.5*(%s+%s)) {\n" % [ pv(name, 0), pv(name, 1) ]
shader += " return "+gcis(points[0].c)+";\n" shader += " return "+pc(name, 0)+";\n"
var s = points.size()-1 var s = points.size()-1
for i in range(s): for i in range(1, s):
if points[i+1].v-points[i].v > 0: shader += " } else if (x < 0.5*(%s+%s)) {\n" % [ pv(name, i), pv(name, i+1) ]
shader += " } else if (x < %.9f) {\n" % (0.5*(points[i].v + points[i+1].v)) shader += " return "+pc(name, i)+";\n"
shader += " return "+gcis(points[i].c)+";\n"
shader += " }\n" shader += " }\n"
shader += " return "+gcis(points[s].c)+";\n" shader += " return "+pc(name, s)+";\n"
else: else:
shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n" shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n"
1, 2: 1, 2:
if points.size() > 0: if points.size() > 0:
shader += " if (x < %.9f) {\n" % points[0].v shader += " if (x < %s) {\n" % pv(name, 0)
shader += " return "+gcis(points[0].c)+";\n" shader += " return "+pc(name, 0)+";\n"
var s = points.size()-1 var s = points.size()-1
for i in range(s): for i in range(s):
var p1mp0 = points[i+1].v-points[i].v shader += " } else if (x < %s) {\n" % pv(name, i+1)
if p1mp0 > 0: var function = "(" if interpolation == 1 else "0.5-0.5*cos(3.14159265359*"
shader += " } else if (x < %.9f) {\n" % points[i+1].v 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) ]
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 += " }\n" shader += " }\n"
shader += " return "+gcis(points[s].c)+";\n" shader += " return "+pc(name, s)+";\n"
else: else:
shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n" shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n"
3: 3:
if points.size() > 0: if points.size() > 0:
shader += " if (x < %.9f) {\n" % points[0].v shader += " if (x < %s) {\n" % pv(name, 0)
shader += " return "+gcis(points[0].c)+";\n" shader += " return "+pc(name, 0)+";\n"
var s = points.size()-1 var s = points.size()-1
for i in range(s): for i in range(s):
var p1mp0 = points[i+1].v-points[i].v shader += " } else if (x < %s) {\n" % pv(name, i+1)
if p1mp0 > 0: var dx : String = "(x-%s)/(%s-%s)" % [ pv(name, i), pv(name, i+1), pv(name, i) ]
shader += " } else if (x < %.9f) {\n" % points[i+1].v var b : String = "mix(%s, %s, %s)" % [ pc(name, i), pc(name, i+1), dx ]
var dx : String = "(x-%.9f)/%.9f" % [ points[i].v, p1mp0 ] if i > 0:
var b : String = "mix(%s, %s, %s)" % [ gcis(points[i].c), gcis(points[i+1].c), dx ] 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 > 0 and points[i-1].v < points[i].v: if i < s-1:
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 ] 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) ]
if i < s-1 and points[i+1].v < points[i+2].v: var ac : String = "mix("+a+", "+c+", 0.5-0.5*cos(3.14159265359*"+dx+"))"
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 0.5*("+b+" + "+ac+");\n"
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"
else: 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 += " }\n"
shader += " return "+gcis(points[s].c)+";\n" shader += " return "+pc(name, s)+";\n"
else: else:
shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n" shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n"
_: _:

View File

@ -1,34 +1,82 @@
{ {
"connections": [ "connections": [
{ {
"from": "graph", "from": "colorize_2",
"from_port": 0,
"to": "blend",
"to_port": 0
},
{
"from": "colorize",
"from_port": 0,
"to": "blend",
"to_port": 1
},
{
"from": "beehive_2",
"from_port": 0,
"to": "colorize_2",
"to_port": 0
},
{
"from": "beehive_2",
"from_port": 1,
"to": "colorize",
"to_port": 0
},
{
"from": "blend",
"from_port": 0,
"to": "colorize_5",
"to_port": 0
},
{
"from": "blend",
"from_port": 0,
"to": "colorize_4",
"to_port": 0
},
{
"from": "blend",
"from_port": 0,
"to": "normal_map",
"to_port": 0
},
{
"from": "blend",
"from_port": 0,
"to": "colorize_3",
"to_port": 0
},
{
"from": "colorize_5",
"from_port": 0,
"to": "Material",
"to_port": 0
},
{
"from": "uniform_greyscale",
"from_port": 0,
"to": "Material",
"to_port": 1
},
{
"from": "colorize_4",
"from_port": 0,
"to": "Material",
"to_port": 2
},
{
"from": "normal_map",
"from_port": 0, "from_port": 0,
"to": "Material", "to": "Material",
"to_port": 4 "to_port": 4
}, },
{ {
"from": "graph", "from": "colorize_3",
"from_port": 1, "from_port": 0,
"to": "Material", "to": "Material",
"to_port": 6 "to_port": 6
},
{
"from": "graph",
"from_port": 2,
"to": "Material",
"to_port": 1
},
{
"from": "graph",
"from_port": 3,
"to": "Material",
"to_port": 2
},
{
"from": "graph",
"from_port": 4,
"to": "Material",
"to_port": 0
} }
], ],
"label": "Graph", "label": "Graph",
@ -39,6 +87,9 @@
}, },
"nodes": [ "nodes": [
{ {
"export_paths": {
},
"name": "Material", "name": "Material",
"node_position": { "node_position": {
"x": -28, "x": -28,
@ -52,477 +103,237 @@
"r": 1, "r": 1,
"type": "Color" "type": "Color"
}, },
"ao_light_affect": 1, "ao": 1,
"depth_scale": 0.2, "depth_scale": 0.2,
"emission_energy": 1, "emission_energy": 1,
"metallic": 1, "metallic": 1,
"normal_scale": 1, "normal": 1,
"roughness": 1, "roughness": 1,
"size": 11, "size": 11,
"subsurf_scatter_strength": 0 "sss": 0
}, },
"type": "material" "type": "material"
}, },
{ {
"connections": [ "name": "colorize",
{
"from": "normal_map",
"from_port": 0,
"to": "gen_outputs",
"to_port": 0
},
{
"from": "graph",
"from_port": 0,
"to": "normal_map",
"to_port": 0
},
{
"from": "graph",
"from_port": 0,
"to": "colorize_3",
"to_port": 0
},
{
"from": "colorize_3",
"from_port": 0,
"to": "gen_outputs",
"to_port": 1
},
{
"from": "uniform_greyscale",
"from_port": 0,
"to": "gen_outputs",
"to_port": 2
},
{
"from": "colorize_4",
"from_port": 0,
"to": "gen_outputs",
"to_port": 3
},
{
"from": "colorize_5",
"from_port": 0,
"to": "gen_outputs",
"to_port": 4
},
{
"from": "graph",
"from_port": 0,
"to": "colorize_5",
"to_port": 0
},
{
"from": "graph",
"from_port": 0,
"to": "colorize_4",
"to_port": 0
}
],
"label": "Graph",
"name": "graph",
"node_position": { "node_position": {
"x": -353.865601, "x": -591.193665,
"y": 6.860606 "y": 41.163864
}, },
"nodes": [
{
"name": "colorize_5",
"node_position": {
"x": -240.009644,
"y": -136
},
"parameters": {
"gradient": {
"interpolation": 1,
"points": [
{
"a": 1,
"b": 0,
"g": 0.068034,
"pos": 0,
"r": 0.098958
},
{
"a": 1,
"b": 0,
"g": 0.6875,
"pos": 0.881818,
"r": 1
}
],
"type": "Gradient"
}
},
"type": "colorize"
},
{
"name": "colorize_4",
"node_position": {
"x": -245.009644,
"y": 15
},
"parameters": {
"gradient": {
"interpolation": 1,
"points": [
{
"a": 1,
"b": 0.65625,
"g": 0.65625,
"pos": 0.518182,
"r": 0.65625
},
{
"a": 1,
"b": 0,
"g": 0,
"pos": 0.890909,
"r": 0
}
],
"type": "Gradient"
}
},
"type": "colorize"
},
{
"name": "uniform_greyscale",
"node_position": {
"x": -246.009644,
"y": -55.5
},
"parameters": {
"color": 0.16
},
"type": "uniform_greyscale"
},
{
"name": "colorize_3",
"node_position": {
"x": -244.009644,
"y": 233.5
},
"parameters": {
"gradient": {
"interpolation": 1,
"points": [
{
"a": 1,
"b": 1,
"g": 1,
"pos": 0,
"r": 1
},
{
"a": 1,
"b": 0,
"g": 0,
"pos": 1,
"r": 0
}
],
"type": "Gradient"
}
},
"type": "colorize"
},
{
"name": "normal_map",
"node_position": {
"x": -235.009644,
"y": 96
},
"parameters": {
"param0": 11,
"param1": 1.02,
"param2": 0,
"param4": 1
},
"type": "normal_map"
},
{
"name": "gen_inputs",
"node_position": {
"x": -802.009644,
"y": 6.860606
},
"parameters": {
},
"ports": [
],
"type": "ios"
},
{
"name": "gen_outputs",
"node_position": {
"x": 64.990356,
"y": 6.860606
},
"parameters": {
},
"ports": [
{
"name": "port0",
"type": "rgba"
},
{
"name": "port1",
"type": "rgba"
},
{
"name": "port2",
"type": "f"
},
{
"name": "port3",
"type": "rgba"
},
{
"name": "port4",
"type": "rgba"
}
],
"type": "ios"
},
{
"name": "gen_parameters",
"node_position": {
"x": -553.865601,
"y": -452.254547
},
"parameters": {
},
"type": "remote",
"widgets": [
]
},
{
"connections": [
{
"from": "colorize_2",
"from_port": 0,
"to": "blend",
"to_port": 0
},
{
"from": "colorize",
"from_port": 0,
"to": "blend",
"to_port": 1
},
{
"from": "blend",
"from_port": 0,
"to": "gen_outputs",
"to_port": 0
},
{
"from": "blend",
"from_port": 0,
"to": "gen_outputs",
"to_port": 0
},
{
"from": "blend",
"from_port": 0,
"to": "gen_outputs",
"to_port": 0
},
{
"from": "blend",
"from_port": 0,
"to": "gen_outputs",
"to_port": 0
},
{
"from": "beehive_2",
"from_port": 0,
"to": "colorize_2",
"to_port": 0
},
{
"from": "beehive_2",
"from_port": 1,
"to": "colorize",
"to_port": 0
}
],
"label": "Graph",
"name": "graph",
"node_position": {
"x": -514.685547,
"y": 2.186363
},
"nodes": [
{
"name": "colorize",
"node_position": {
"x": -510.5,
"y": 45
},
"parameters": {
"gradient": {
"interpolation": 1,
"points": [
{
"a": 1,
"b": 0,
"g": 0,
"pos": 0,
"r": 0
},
{
"a": 1,
"b": 0.225431,
"g": 0.225431,
"pos": 0.583818,
"r": 0.225431
},
{
"a": 1,
"b": 0.96875,
"g": 0.96875,
"pos": 0.672727,
"r": 0.96875
}
],
"type": "Gradient"
}
},
"type": "colorize"
},
{
"name": "colorize_2",
"node_position": {
"x": -510.5,
"y": -26
},
"parameters": {
"gradient": {
"interpolation": 1,
"points": [
{
"a": 1,
"b": 1,
"g": 1,
"pos": 0,
"r": 1
},
{
"a": 1,
"b": 0.947917,
"g": 0.947917,
"pos": 0.049912,
"r": 0.947917
},
{
"a": 1,
"b": 0.115584,
"g": 0.115584,
"pos": 0.106977,
"r": 0.115584
},
{
"a": 1,
"b": 0,
"g": 0,
"pos": 0.290909,
"r": 0
}
],
"type": "Gradient"
}
},
"type": "colorize"
},
{
"name": "blend",
"node_position": {
"x": -523.009644,
"y": 117
},
"parameters": {
"amount": 1,
"blend_type": 9
},
"seed_value": -12215,
"type": "blend"
},
{
"name": "beehive_2",
"node_position": {
"x": -514.732483,
"y": -127.254547
},
"parameters": {
"sx": 20,
"sy": 12
},
"type": "beehive"
},
{
"name": "gen_inputs",
"node_position": {
"x": -823.009644,
"y": 2.186363
},
"parameters": {
},
"ports": [
],
"type": "ios"
},
{
"name": "gen_outputs",
"node_position": {
"x": -210.5,
"y": 2.186363
},
"parameters": {
},
"ports": [
{
"name": "port0",
"type": "rgba"
}
],
"type": "ios"
},
{
"name": "gen_parameters",
"node_position": {
"x": -714.685547,
"y": -427.254547
},
"parameters": {
},
"type": "remote",
"widgets": [
]
}
],
"parameters": {
},
"type": "graph"
}
],
"parameters": { "parameters": {
"gradient": {
"interpolation": 1,
"points": [
{
"a": 1,
"b": 0,
"g": 0,
"pos": 0,
"r": 0
},
{
"a": 1,
"b": 0.225431,
"g": 0.225431,
"pos": 0.583818,
"r": 0.225431
},
{
"a": 1,
"b": 0.96875,
"g": 0.96875,
"pos": 0.672727,
"r": 0.96875
}
],
"type": "Gradient"
}
}, },
"type": "graph" "type": "colorize"
},
{
"name": "colorize_2",
"node_position": {
"x": -591.193665,
"y": -29.836136
},
"parameters": {
"gradient": {
"interpolation": 1,
"points": [
{
"a": 1,
"b": 1,
"g": 1,
"pos": 0,
"r": 1
},
{
"a": 1,
"b": 0.947917,
"g": 0.947917,
"pos": 0.049912,
"r": 0.947917
},
{
"a": 1,
"b": 0.115584,
"g": 0.115584,
"pos": 0.106977,
"r": 0.115584
},
{
"a": 1,
"b": 0,
"g": 0,
"pos": 0.290909,
"r": 0
}
],
"type": "Gradient"
}
},
"type": "colorize"
},
{
"name": "blend",
"node_position": {
"x": -603.703308,
"y": 113.163872
},
"parameters": {
"amount": 1,
"blend_type": 9
},
"seed_value": -12215,
"type": "blend"
},
{
"name": "normal_map",
"node_position": {
"x": -270.375671,
"y": 88.194351
},
"parameters": {
"param0": 11,
"param1": 1.02,
"param2": 0,
"param4": 1
},
"type": "normal_map"
},
{
"name": "colorize_3",
"node_position": {
"x": -279.375671,
"y": 225.694351
},
"parameters": {
"gradient": {
"interpolation": 1,
"points": [
{
"a": 1,
"b": 1,
"g": 1,
"pos": 0,
"r": 1
},
{
"a": 1,
"b": 0,
"g": 0,
"pos": 1,
"r": 0
}
],
"type": "Gradient"
}
},
"type": "colorize"
},
{
"name": "uniform_greyscale",
"node_position": {
"x": -281.375671,
"y": -63.305649
},
"parameters": {
"color": 0.16
},
"type": "uniform_greyscale"
},
{
"name": "colorize_4",
"node_position": {
"x": -280.375671,
"y": 7.194351
},
"parameters": {
"gradient": {
"interpolation": 1,
"points": [
{
"a": 1,
"b": 0.65625,
"g": 0.65625,
"pos": 0.518182,
"r": 0.65625
},
{
"a": 1,
"b": 0,
"g": 0,
"pos": 0.890909,
"r": 0
}
],
"type": "Gradient"
}
},
"type": "colorize"
},
{
"name": "colorize_5",
"node_position": {
"x": -275.375671,
"y": -143.805649
},
"parameters": {
"gradient": {
"interpolation": 1,
"points": [
{
"a": 1,
"b": 0,
"g": 0.068034,
"pos": 0,
"r": 0.098958
},
{
"a": 1,
"b": 0,
"g": 0.6875,
"pos": 0.881818,
"r": 1
}
],
"type": "Gradient"
}
},
"type": "colorize"
},
{
"name": "beehive_2",
"node_position": {
"x": -595.426147,
"y": -131.090683
},
"parameters": {
"sx": 20,
"sy": 12
},
"type": "beehive"
} }
], ],
"parameters": { "parameters": {

View File

@ -1,23 +1,5 @@
{ {
"connections": [ "connections": [
{
"from": "bricks",
"from_port": 2,
"to": "transform",
"to_port": 1
},
{
"from": "bricks",
"from_port": 3,
"to": "transform",
"to_port": 2
},
{
"from": "bricks",
"from_port": 0,
"to": "blend",
"to_port": 1
},
{ {
"from": "transform", "from": "transform",
"from_port": 0, "from_port": 0,
@ -30,12 +12,6 @@
"to": "transform", "to": "transform",
"to_port": 0 "to_port": 0
}, },
{
"from": "bricks",
"from_port": 1,
"to": "transform",
"to_port": 3
},
{ {
"from": "blend", "from": "blend",
"from_port": 0, "from_port": 0,
@ -59,6 +35,30 @@
"from_port": 0, "from_port": 0,
"to": "Material", "to": "Material",
"to_port": 4 "to_port": 4
},
{
"from": "bricks_2",
"from_port": 2,
"to": "transform",
"to_port": 1
},
{
"from": "bricks_2",
"from_port": 3,
"to": "transform",
"to_port": 2
},
{
"from": "bricks_2",
"from_port": 0,
"to": "blend",
"to_port": 1
},
{
"from": "bricks_2",
"from_port": 1,
"to": "transform",
"to_port": 3
} }
], ],
"label": "Graph", "label": "Graph",
@ -69,6 +69,9 @@
}, },
"nodes": [ "nodes": [
{ {
"export_paths": {
},
"name": "Material", "name": "Material",
"node_position": { "node_position": {
"x": 70, "x": 70,
@ -82,148 +85,17 @@
"r": 1, "r": 1,
"type": "Color" "type": "Color"
}, },
"ao_light_affect": 1, "ao": 1,
"depth_scale": 1, "depth_scale": 1,
"emission_energy": 1, "emission_energy": 1,
"metallic": 1, "metallic": 1,
"normal_scale": 1, "normal": 1,
"roughness": 1, "roughness": 1,
"size": 11, "size": 11,
"subsurf_scatter_strength": 0 "sss": 0
}, },
"type": "material" "type": "material"
}, },
{
"name": "bricks",
"node_position": {
"x": -549.5,
"y": -120.5
},
"parameters": {
"bevel": 0.1,
"columns": 3,
"mortar": 0.1,
"pattern": 0,
"repeat": 1,
"row_offset": 0.5,
"rows": 6
},
"shader_model": {
"code": "vec4 $(name_uv) = $(name)_xyzw($(uv));\n",
"global": "vec4 brick(vec2 uv, vec2 bmin, vec2 bmax, float mortar, float bevel) {\n\tfloat color;\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\tvec2 tiled_brick_pos = mod(bmin, vec2(1.0, 1.0));\n\treturn vec4(color, 0.5*(bmin+bmax), tiled_brick_pos.x+7.0*tiled_brick_pos.y);\n}\n\nvec4 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\nvec4 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\nvec4 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\nvec4 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\nvec4 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": "vec4 $(name)_xyzw(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(vec2($(name_uv).w, $(seed)))",
"type": "rgb"
},
{
"f": "$(name_uv).y",
"type": "f"
},
{
"f": "$(name_uv).z",
"type": "f"
}
],
"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"
},
{ {
"name": "blend", "name": "blend",
"node_position": { "node_position": {
@ -311,7 +183,7 @@
"y": 165.542206 "y": 165.542206
}, },
"parameters": { "parameters": {
"size": 4
}, },
"size": { "size": {
"x": 280, "x": 280,
@ -328,15 +200,31 @@
"y": -40.645294 "y": -40.645294
}, },
"parameters": { "parameters": {
"amount": 0.5,
"param0": 11, "param0": 11,
"param1": 0.995, "param1": 0.995,
"param2": 0, "param2": 0,
"param3": 0, "param4": 1
"param4": 1,
"size": 4
}, },
"type": "normal_map" "type": "normal_map"
},
{
"name": "bricks_2",
"node_position": {
"x": -528.086548,
"y": -114.154938
},
"parameters": {
"bevel": 0.1,
"columns": 3,
"corner": 0,
"mortar": 0.1,
"pattern": 0,
"repeat": 1,
"round": 0,
"row_offset": 0.5,
"rows": 6
},
"type": "bricks"
} }
], ],
"parameters": { "parameters": {

View File

@ -255,6 +255,9 @@
}, },
"nodes": [ "nodes": [
{ {
"export_paths": {
},
"name": "Material", "name": "Material",
"node_position": { "node_position": {
"x": 424, "x": 424,
@ -268,14 +271,14 @@
"r": 1, "r": 1,
"type": "Color" "type": "Color"
}, },
"ao_light_affect": 0.95, "ao": 1,
"depth_scale": 0, "depth_scale": 0,
"emission_energy": 1, "emission_energy": 1,
"metallic": 1, "metallic": 1,
"normal_scale": 1, "normal": 1,
"roughness": 1, "roughness": 1,
"size": 11, "size": 11,
"subsurf_scatter_strength": 0 "sss": 0
}, },
"type": "material" "type": "material"
}, },
@ -286,7 +289,7 @@
"y": 34.016663 "y": 34.016663
}, },
"parameters": { "parameters": {
"steps": 6
}, },
"type": "invert" "type": "invert"
}, },
@ -328,21 +331,21 @@
"to_port": 0 "to_port": 0
}, },
{ {
"from": "_2_2_2_2", "from": "blend",
"from_port": 0, "from_port": 0,
"to": "gen_outputs", "to": "mwf_create_map",
"to_port": 0 "to_port": 0
}, },
{ {
"from": "bricks", "from": "bricks",
"from_port": 1, "from_port": 1,
"to": "_2_2_2_2", "to": "mwf_create_map",
"to_port": 1 "to_port": 1
}, },
{ {
"from": "blend", "from": "mwf_create_map",
"from_port": 0, "from_port": 0,
"to": "_2_2_2_2", "to": "gen_outputs",
"to_port": 0 "to_port": 0
} }
], ],
@ -371,7 +374,7 @@
"y": -369.233337 "y": -369.233337
}, },
"parameters": { "parameters": {
"steps": 6
}, },
"type": "invert" "type": "invert"
}, },
@ -484,67 +487,6 @@
} }
] ]
}, },
{
"name": "_2_2_2_2",
"node_position": {
"x": -467.634766,
"y": -373.905029
},
"parameters": {
"angle": 0,
"height": 1
},
"seed_value": -41854,
"shader_model": {
"code": "",
"global": "",
"inputs": [
{
"default": "0.0",
"label": "",
"name": "in",
"type": "f"
},
{
"default": "0.0",
"label": "",
"name": "rand",
"type": "f"
}
],
"instance": "",
"name": "Create Map",
"outputs": [
{
"rgb": "vec3($height*$in($uv), $angle*0.01745329251, rand(vec2($seed.0+$rand($uv))))",
"type": "rgb"
}
],
"parameters": [
{
"control": "None",
"default": 1,
"label": "Height",
"max": 1,
"min": 0,
"name": "height",
"step": 0.01,
"type": "float"
},
{
"control": "None",
"default": 0,
"label": "Angle",
"max": 180,
"min": -180,
"name": "angle",
"step": 0.1,
"type": "float"
}
]
},
"type": "shader"
},
{ {
"name": "uniform_greyscale_2", "name": "uniform_greyscale_2",
"node_position": { "node_position": {
@ -555,6 +497,18 @@
"color": 1 "color": 1
}, },
"type": "uniform_greyscale" "type": "uniform_greyscale"
},
{
"name": "mwf_create_map",
"node_position": {
"x": -497.801086,
"y": -339.560547
},
"parameters": {
"angle": 0,
"height": 1
},
"type": "mwf_create_map"
} }
], ],
"parameters": { "parameters": {
@ -609,14 +563,7 @@
"y": -230.983337 "y": -230.983337
}, },
"parameters": { "parameters": {
"color": {
"a": 1,
"b": 1,
"g": 1,
"r": 1,
"type": "Color"
},
"name": 0
}, },
"type": "combine" "type": "combine"
}, },
@ -1108,14 +1055,7 @@
"y": 39.197388 "y": 39.197388
}, },
"parameters": { "parameters": {
"color": {
"a": 1,
"b": 1,
"g": 1,
"r": 1,
"type": "Color"
},
"name": 0
}, },
"type": "combine" "type": "combine"
}, },
@ -1137,13 +1077,10 @@
"y": 186.780701 "y": 186.780701
}, },
"parameters": { "parameters": {
"amount": 0.5,
"param0": 11, "param0": 11,
"param1": 2, "param1": 2,
"param2": 0, "param2": 0,
"param3": 0, "param4": 0
"param4": 0,
"size": 4
}, },
"type": "normal_map" "type": "normal_map"
}, },
@ -1171,7 +1108,6 @@
"y": 149.637848 "y": 149.637848
}, },
"parameters": { "parameters": {
"Randomness": 0.5,
"angle": -1, "angle": -1,
"layers": 10, "layers": 10,
"length": 0.05, "length": 0.05,
@ -1784,14 +1720,7 @@
"y": 39.197388 "y": 39.197388
}, },
"parameters": { "parameters": {
"color": {
"a": 1,
"b": 1,
"g": 1,
"r": 1,
"type": "Color"
},
"name": 0
}, },
"type": "combine" "type": "combine"
}, },
@ -1813,13 +1742,10 @@
"y": 186.780701 "y": 186.780701
}, },
"parameters": { "parameters": {
"amount": 0.5,
"param0": 11, "param0": 11,
"param1": 2, "param1": 2,
"param2": 0, "param2": 0,
"param3": 0, "param4": 0
"param4": 0,
"size": 4
}, },
"type": "normal_map" "type": "normal_map"
}, },
@ -1847,7 +1773,6 @@
"y": 149.637848 "y": 149.637848
}, },
"parameters": { "parameters": {
"Randomness": 0.5,
"angle": -1, "angle": -1,
"layers": 10, "layers": 10,
"length": 0.05, "length": 0.05,
@ -2129,7 +2054,6 @@
}, },
"parameters": { "parameters": {
"param0": 1, "param0": 1,
"param1": 10,
"param2": 1 "param2": 1
}, },
"type": "mwf_output" "type": "mwf_output"

View File

@ -153,6 +153,9 @@
}, },
"nodes": [ "nodes": [
{ {
"export_paths": {
},
"name": "Material", "name": "Material",
"node_position": { "node_position": {
"x": 12, "x": 12,
@ -166,14 +169,14 @@
"r": 1, "r": 1,
"type": "Color" "type": "Color"
}, },
"ao_light_affect": 1, "ao": 1,
"depth_scale": 1, "depth_scale": 1,
"emission_energy": 1, "emission_energy": 1,
"metallic": 1, "metallic": 1,
"normal_scale": 1, "normal": 1,
"roughness": 1, "roughness": 1,
"size": 11, "size": 11,
"subsurf_scatter_strength": 0 "sss": 0
}, },
"type": "material" "type": "material"
}, },
@ -2187,7 +2190,7 @@
"parameters": { "parameters": {
"choices": 3, "choices": 3,
"outputs": 4, "outputs": 4,
"source": 0 "source": 2
}, },
"type": "switch" "type": "switch"
}, },

View File

@ -6,30 +6,6 @@
"to": "sdf3d_scale_2", "to": "sdf3d_scale_2",
"to_port": 0 "to_port": 0
}, },
{
"from": "sdf3d_scale_2",
"from_port": 0,
"to": "sdf3d_repeat",
"to_port": 0
},
{
"from": "sdf3d_scale_2",
"from_port": 0,
"to": "sdf3d_repeat_2",
"to_port": 0
},
{
"from": "sdf3d_repeat_2",
"from_port": 0,
"to": "sdf3d_translate_3_2_2",
"to_port": 0
},
{
"from": "sdf3d_repeat",
"from_port": 0,
"to": "sdf3d_boolean",
"to_port": 0
},
{ {
"from": "sdf3d_translate_3_2_2", "from": "sdf3d_translate_3_2_2",
"from_port": 0, "from_port": 0,
@ -401,6 +377,30 @@
"from_port": 2, "from_port": 2,
"to": "mul_detect_2_2", "to": "mul_detect_2_2",
"to_port": 1 "to_port": 1
},
{
"from": "sdf3d_scale_2",
"from_port": 0,
"to": "sdf3d_repeat_3",
"to_port": 0
},
{
"from": "sdf3d_repeat_3",
"from_port": 0,
"to": "sdf3d_boolean",
"to_port": 0
},
{
"from": "sdf3d_scale_2",
"from_port": 0,
"to": "sdf3d_repeat_3_2",
"to_port": 0
},
{
"from": "sdf3d_repeat_3_2",
"from_port": 0,
"to": "sdf3d_translate_3_2_2",
"to_port": 0
} }
], ],
"label": "Graph", "label": "Graph",
@ -411,6 +411,9 @@
}, },
"nodes": [ "nodes": [
{ {
"export_paths": {
},
"name": "Material", "name": "Material",
"node_position": { "node_position": {
"x": 1596.135986, "x": 1596.135986,
@ -424,14 +427,14 @@
"r": 1, "r": 1,
"type": "Color" "type": "Color"
}, },
"ao_light_affect": 1, "ao": 1,
"depth_scale": 0.3, "depth_scale": 0.3,
"emission_energy": 1, "emission_energy": 1,
"metallic": 1, "metallic": 1,
"normal_scale": 1, "normal": 1,
"roughness": 1, "roughness": 1,
"size": 11, "size": 11,
"subsurf_scatter_strength": 0 "sss": 0
}, },
"type": "material" "type": "material"
}, },
@ -562,8 +565,8 @@
"label": "Donut", "label": "Donut",
"name": "graph", "name": "graph",
"node_position": { "node_position": {
"x": -664.759155, "x": -660.759155,
"y": -18.094296 "y": 14.905704
}, },
"nodes": [ "nodes": [
{ {
@ -573,15 +576,7 @@
"y": 249.420105 "y": 249.420105
}, },
"parameters": { "parameters": {
"bevel": 0, "c": 0.31
"c": 0.31,
"cx": 0,
"cy": 0,
"h": 0.08,
"k": 0.15,
"op": 0,
"r": 0.15,
"w": 0.28
}, },
"shader_model": { "shader_model": {
"code": "", "code": "",
@ -624,13 +619,7 @@
"y": 320.541656 "y": 320.541656
}, },
"parameters": { "parameters": {
"bevel": 0, "op": 2
"cx": 0,
"cy": 0,
"h": 0.08,
"op": 2,
"r": 0.3,
"w": 0.28
}, },
"shader_model": { "shader_model": {
"code": "", "code": "",
@ -699,18 +688,13 @@
"name": "sdf3d_repeat", "name": "sdf3d_repeat",
"node_position": { "node_position": {
"x": -768.854126, "x": -768.854126,
"y": 276.291656 "y": 281.291656
}, },
"parameters": { "parameters": {
"a": 0,
"r": 0.51, "r": 0.51,
"rx": 16, "rx": 16,
"ry": 16, "ry": 16,
"rz": 16, "rz": 16
"s": 0.3,
"x": 0.35,
"y": 0,
"z": 0
}, },
"shader_model": { "shader_model": {
"code": "", "code": "",
@ -727,7 +711,7 @@
"name": "Repeat", "name": "Repeat",
"outputs": [ "outputs": [
{ {
"sdf3dc": "$in(sdf3d_repeat($uv, vec3(1.0/$rx, 1.0/$ry, 1.0/$rz), $seed, $r))", "sdf3dc": "$in(sdf3d_repeat($uv, vec3(1.0/$rx, 1.0/$ry, 1.0/$rz), float($seed), $r))",
"type": "sdf3dc" "type": "sdf3dc"
} }
], ],
@ -784,10 +768,7 @@
}, },
"parameters": { "parameters": {
"l": 0.02, "l": 0.02,
"r": 0.01, "r": 0.01
"sx": 0.25,
"sy": 0.25,
"sz": 0.5
}, },
"type": "sdf3d_capsule" "type": "sdf3d_capsule"
}, },
@ -799,10 +780,7 @@
}, },
"parameters": { "parameters": {
"R": 0.3, "R": 0.3,
"r": 0.14, "r": 0.14
"sx": 0.1,
"sy": 0.1,
"sz": 0.02
}, },
"type": "sdf3d_torus" "type": "sdf3d_torus"
}, },
@ -814,10 +792,7 @@
}, },
"parameters": { "parameters": {
"R": 0.3, "R": 0.3,
"r": 0.15, "r": 0.15
"sx": 0.1,
"sy": 0.1,
"sz": 0.02
}, },
"type": "sdf3d_torus" "type": "sdf3d_torus"
}, },
@ -828,13 +803,7 @@
"y": -3.083344 "y": -3.083344
}, },
"parameters": { "parameters": {
"bevel": 0, "op": 0
"cx": 0,
"cy": 0,
"h": 0.08,
"op": 0,
"r": 0.3,
"w": 0.28
}, },
"shader_model": { "shader_model": {
"code": "", "code": "",
@ -893,15 +862,7 @@
"y": -156.583344 "y": -156.583344
}, },
"parameters": { "parameters": {
"bevel": 0, "c": 0.08
"c": 0.08,
"cx": 0,
"cy": 0,
"h": 0.08,
"k": 0.15,
"op": 0,
"r": 0.15,
"w": 0.28
}, },
"shader_model": { "shader_model": {
"code": "", "code": "",
@ -957,15 +918,7 @@
"y": 130.166656 "y": 130.166656
}, },
"parameters": { "parameters": {
"bevel": 0, "c": 0.87
"c": 0.87,
"cx": 0,
"cy": 0,
"h": 0.08,
"k": 0.15,
"op": 0,
"r": 0.15,
"w": 0.28
}, },
"shader_model": { "shader_model": {
"code": "", "code": "",
@ -1008,13 +961,7 @@
"y": 127.920105 "y": 127.920105
}, },
"parameters": { "parameters": {
"bevel": 0, "op": 0
"cx": 0,
"cy": 0,
"h": 0.08,
"op": 0,
"r": 0.3,
"w": 0.28
}, },
"shader_model": { "shader_model": {
"code": "", "code": "",
@ -1117,76 +1064,6 @@
}, },
"type": "graph" "type": "graph"
}, },
{
"name": "sdf3d_repeat",
"node_position": {
"x": -482.202179,
"y": -14.881774
},
"parameters": {
"a": 0,
"r": 0.2,
"rx": 3,
"ry": 3,
"s": 0.3,
"x": 0.35,
"y": 0,
"z": 0
},
"shader_model": {
"code": "",
"global": "vec3 repeat(vec3 p, vec3 r, float seed, float randomness) {\n\tvec3 a = (rand3(floor(mod((p.xy+0.5*r.xy)/r.xy, 1.0/r.xy)+vec2(seed)))-0.5)*6.28*randomness;\n\tp = mod(p+0.5*r,r)-0.5*r;\n\tvec3 rv;\n\tfloat c;\n\tfloat s;\n\tc = cos(a.x);\n\ts = sin(a.x);\n\trv.x = p.x;\n\trv.y = p.y*c+p.z*s;\n\trv.z = -p.y*s+p.z*c;\n\tc = cos(a.y);\n\ts = sin(a.y);\n\tp.x = rv.x*c+rv.z*s;\n\tp.y = rv.y;\n\tp.z = -rv.x*s+rv.z*c;\n\tc = cos(a.z);\n\ts = sin(a.z);\n\trv.x = p.x*c+p.y*s;\n\trv.y = -p.x*s+p.y*c;\n\trv.z = p.z;\n\treturn rv;\n}\n",
"inputs": [
{
"default": "0.0",
"label": "",
"name": "in",
"type": "sdf3dc"
}
],
"instance": "",
"name": "Repeat",
"outputs": [
{
"sdf3dc": "$in(repeat($uv, vec3(1.0/$rx, 1.0/$ry, 0.0), $seed, $r))",
"type": "sdf3dc"
}
],
"parameters": [
{
"control": "None",
"default": 4,
"label": "X",
"max": 32,
"min": 1,
"name": "rx",
"step": 1,
"type": "float"
},
{
"control": "None",
"default": 4,
"label": "Y",
"max": 32,
"min": 1,
"name": "ry",
"step": 1,
"type": "float"
},
{
"control": "None",
"default": 0.5,
"label": "R",
"max": 1,
"min": 0,
"name": "r",
"step": 0.01,
"type": "float"
}
]
},
"type": "shader"
},
{ {
"name": "sdf3d_scale_2", "name": "sdf3d_scale_2",
"node_position": { "node_position": {
@ -1194,11 +1071,7 @@
"y": 66.030228 "y": 66.030228
}, },
"parameters": { "parameters": {
"a": 0, "s": 0.37
"s": 0.37,
"x": 0.35,
"y": 0,
"z": 0
}, },
"shader_model": { "shader_model": {
"code": "vec2 $(name_uv)_in = $in(($uv)/$s);", "code": "vec2 $(name_uv)_in = $in(($uv)/$s);",
@ -1234,86 +1107,16 @@
}, },
"type": "shader" "type": "shader"
}, },
{
"name": "sdf3d_repeat_2",
"node_position": {
"x": -480.202179,
"y": 110.618225
},
"parameters": {
"a": 0,
"r": 0.21,
"rx": 3,
"ry": 3,
"s": 0.3,
"x": 0.35,
"y": 0,
"z": 0
},
"shader_model": {
"code": "",
"global": "vec3 repeat(vec3 p, vec3 r, float seed, float randomness) {\n\tvec3 a = (rand3(floor(mod((p.xy+0.5*r.xy)/r.xy, 1.0/r.xy)+vec2(seed)))-0.5)*6.28*randomness;\n\tp = mod(p+0.5*r,r)-0.5*r;\n\tvec3 rv;\n\tfloat c;\n\tfloat s;\n\tc = cos(a.x);\n\ts = sin(a.x);\n\trv.x = p.x;\n\trv.y = p.y*c+p.z*s;\n\trv.z = -p.y*s+p.z*c;\n\tc = cos(a.y);\n\ts = sin(a.y);\n\tp.x = rv.x*c+rv.z*s;\n\tp.y = rv.y;\n\tp.z = -rv.x*s+rv.z*c;\n\tc = cos(a.z);\n\ts = sin(a.z);\n\trv.x = p.x*c+p.y*s;\n\trv.y = -p.x*s+p.y*c;\n\trv.z = p.z;\n\treturn rv;\n}\n",
"inputs": [
{
"default": "0.0",
"label": "",
"name": "in",
"type": "sdf3dc"
}
],
"instance": "",
"name": "Repeat",
"outputs": [
{
"sdf3dc": "$in(repeat($uv, vec3(1.0/$rx, 1.0/$ry, 0.0), $seed, $r))",
"type": "sdf3dc"
}
],
"parameters": [
{
"control": "None",
"default": 4,
"label": "X",
"max": 32,
"min": 1,
"name": "rx",
"step": 1,
"type": "float"
},
{
"control": "None",
"default": 4,
"label": "Y",
"max": 32,
"min": 1,
"name": "ry",
"step": 1,
"type": "float"
},
{
"control": "None",
"default": 0.5,
"label": "R",
"max": 1,
"min": 0,
"name": "r",
"step": 0.01,
"type": "float"
}
]
},
"type": "shader"
},
{ {
"name": "sdf3d_translate_3_2_2", "name": "sdf3d_translate_3_2_2",
"node_position": { "node_position": {
"x": -479.952209, "x": -478.952209,
"y": 213.034912 "y": 207.034912
}, },
"parameters": { "parameters": {
"x": 0.14, "x": 0.18,
"y": 0.11, "y": 0.11,
"z": 0.2 "z": 0.14
}, },
"shader_model": { "shader_model": {
"code": "", "code": "",
@ -1372,17 +1175,11 @@
{ {
"name": "sdf3d_boolean", "name": "sdf3d_boolean",
"node_position": { "node_position": {
"x": -252.248795, "x": -265.248779,
"y": 76.092621 "y": 76.092621
}, },
"parameters": { "parameters": {
"bevel": 0, "op": 0
"cx": 0,
"cy": 0,
"h": 0.08,
"op": 0,
"r": 0.3,
"w": 0.28
}, },
"shader_model": { "shader_model": {
"code": "", "code": "",
@ -1443,7 +1240,7 @@
"parameters": { "parameters": {
"x": 0, "x": 0,
"y": 0, "y": 0,
"z": 0.1 "z": 0.07
}, },
"shader_model": { "shader_model": {
"code": "", "code": "",
@ -1513,7 +1310,7 @@
"y": -50.802036 "y": -50.802036
}, },
"parameters": { "parameters": {
"size": 4
}, },
"size": { "size": {
"x": 757.167969, "x": 757.167969,
@ -1907,7 +1704,6 @@
}, },
"parameters": { "parameters": {
"param0": 10, "param0": 10,
"param1": 50,
"param2": 4.9 "param2": 4.9
}, },
"type": "remote", "type": "remote",
@ -2069,7 +1865,6 @@
], ],
"parameters": { "parameters": {
"param0": 10, "param0": 10,
"param1": 50,
"param2": 4.9 "param2": 4.9
}, },
"type": "graph" "type": "graph"
@ -2179,7 +1974,6 @@
}, },
"parameters": { "parameters": {
"param0": 0, "param0": 0,
"param1": 10,
"param2": 4.9 "param2": 4.9
}, },
"type": "remote", "type": "remote",
@ -2216,8 +2010,7 @@
}, },
"parameters": { "parameters": {
"brightness": 0, "brightness": 0,
"contrast": 1, "contrast": 1
"steps": 6
}, },
"type": "brightness_contrast" "type": "brightness_contrast"
}, },
@ -2228,20 +2021,16 @@
"y": 544.75 "y": 544.75
}, },
"parameters": { "parameters": {
"amount": 0.5,
"param0": 10, "param0": 10,
"param1": 1.02, "param1": 1.02,
"param2": 0, "param2": 0,
"param3": 0, "param4": 1
"param4": 1,
"size": 4
}, },
"type": "normal_map" "type": "normal_map"
} }
], ],
"parameters": { "parameters": {
"param0": 0, "param0": 0,
"param1": 10,
"param2": 4.9 "param2": 4.9
}, },
"type": "graph" "type": "graph"
@ -2428,7 +2217,7 @@
"y": -50.148132 "y": -50.148132
}, },
"parameters": { "parameters": {
"size": 4
}, },
"size": { "size": {
"x": 255.271576, "x": 255.271576,
@ -2452,7 +2241,7 @@
"y": -373.398132 "y": -373.398132
}, },
"parameters": { "parameters": {
"size": 4
}, },
"size": { "size": {
"x": 464, "x": 464,
@ -2476,7 +2265,7 @@
"y": -289.750183 "y": -289.750183
}, },
"parameters": { "parameters": {
"size": 4
}, },
"size": { "size": {
"x": 743.688171, "x": 743.688171,
@ -2521,6 +2310,32 @@
"v": 0.08 "v": 0.08
}, },
"type": "mul_detect" "type": "mul_detect"
},
{
"name": "sdf3d_repeat_3",
"node_position": {
"x": -479.340515,
"y": 4.22731
},
"parameters": {
"r": 0.2,
"rx": 3,
"ry": 3
},
"type": "sdf3d_repeat"
},
{
"name": "sdf3d_repeat_3_2",
"node_position": {
"x": -479.107727,
"y": 105.348923
},
"parameters": {
"r": 0.2,
"rx": 3,
"ry": 3
},
"type": "sdf3d_repeat"
} }
], ],
"parameters": { "parameters": {

View File

@ -165,6 +165,9 @@
}, },
"nodes": [ "nodes": [
{ {
"export_paths": {
},
"name": "Material", "name": "Material",
"node_position": { "node_position": {
"x": 356, "x": 356,
@ -178,14 +181,14 @@
"r": 1, "r": 1,
"type": "Color" "type": "Color"
}, },
"ao_light_affect": 1, "ao": 1,
"depth_scale": 1, "depth_scale": 1,
"emission_energy": 1, "emission_energy": 1,
"metallic": 1, "metallic": 1,
"normal_scale": 1, "normal": 1,
"roughness": 1, "roughness": 1,
"size": 11, "size": 11,
"subsurf_scatter_strength": 0 "sss": 0
}, },
"type": "material" "type": "material"
}, },
@ -492,18 +495,6 @@
}, },
{ {
"connections": [ "connections": [
{
"from": "sdf3d_scale",
"from_port": 0,
"to": "sdf3d_scale_2",
"to_port": 0
},
{
"from": "sdf3d_scale_2",
"from_port": 0,
"to": "sdf3d_boolean_2",
"to_port": 0
},
{ {
"from": "sdf3d_translate_4", "from": "sdf3d_translate_4",
"from_port": 0, "from_port": 0,
@ -533,6 +524,18 @@
"from_port": 0, "from_port": 0,
"to": "sdf3d_scale", "to": "sdf3d_scale",
"to_port": 0 "to_port": 0
},
{
"from": "sdf3d_scale",
"from_port": 0,
"to": "sdf3d_repeat_2",
"to_port": 0
},
{
"from": "sdf3d_repeat_2",
"from_port": 0,
"to": "sdf3d_boolean_2",
"to_port": 0
} }
], ],
"label": "Skulls", "label": "Skulls",
@ -1319,68 +1322,6 @@
}, },
"type": "sdf3d_boolean" "type": "sdf3d_boolean"
}, },
{
"name": "sdf3d_scale_2",
"node_position": {
"x": -985.183411,
"y": 1271.851807
},
"parameters": {
"r": 0.25,
"rx": 4,
"ry": 4
},
"shader_model": {
"code": "",
"global": "vec3 repeat(vec3 p, vec3 r, float seed, float randomness) {\n\tvec3 a = (rand3(floor(mod((p.xy+0.5*r.xy)/r.xy, 1.0/r.xy)+vec2(seed)))-0.5)*6.28*randomness;\n\tp = mod(p+0.5*r,r)-0.5*r;\n\tvec3 rv;\n\tfloat c;\n\tfloat s;\n\tc = cos(a.x);\n\ts = sin(a.x);\n\trv.x = p.x;\n\trv.y = p.y*c+p.z*s;\n\trv.z = -p.y*s+p.z*c;\n\tc = cos(a.y);\n\ts = sin(a.y);\n\tp.x = rv.x*c+rv.z*s;\n\tp.y = rv.y;\n\tp.z = -rv.x*s+rv.z*c;\n\tc = cos(a.z);\n\ts = sin(a.z);\n\trv.x = p.x*c+p.y*s;\n\trv.y = -p.x*s+p.y*c;\n\trv.z = p.z;\n\treturn rv;\n}\n",
"inputs": [
{
"default": "0.0",
"label": "",
"name": "in",
"type": "sdf3d"
}
],
"instance": "",
"name": "Repeat",
"outputs": [
{
"sdf3d": "$in(repeat($uv, vec3(1.0/$rx, 1.0/$ry, 0.0), $seed, $r))",
"type": "sdf3d"
}
],
"parameters": [
{
"default": 4,
"label": "X",
"max": 32,
"min": 1,
"name": "rx",
"step": 1,
"type": "float"
},
{
"default": 4,
"label": "Y",
"max": 32,
"min": 1,
"name": "ry",
"step": 1,
"type": "float"
},
{
"default": 0.5,
"label": "R",
"max": 1,
"min": 0,
"name": "r",
"step": 0.01,
"type": "float"
}
]
},
"type": "shader"
},
{ {
"name": "sdf3d_repeat", "name": "sdf3d_repeat",
"node_position": { "node_position": {
@ -1438,6 +1379,19 @@
"widgets": [ "widgets": [
] ]
},
{
"name": "sdf3d_repeat_2",
"node_position": {
"x": -986.70166,
"y": 1268.091553
},
"parameters": {
"r": 0.25,
"rx": 4,
"ry": 4
},
"type": "sdf3d_repeat"
} }
], ],
"parameters": { "parameters": {

View File

@ -103,7 +103,7 @@ func update_tab_title() -> void:
if get_parent().has_method("set_tab_title"): if get_parent().has_method("set_tab_title"):
get_parent().set_tab_title(get_index(), title) get_parent().set_tab_title(get_index(), title)
func set_need_save(ns) -> void: func set_need_save(ns = true) -> void:
if ns != need_save: if ns != need_save:
need_save = ns need_save = ns
update_tab_title() update_tab_title()

View File

@ -4898,6 +4898,9 @@
{ {
"collapsed": true, "collapsed": true,
"icon": "miscellaneous_buffer", "icon": "miscellaneous_buffer",
"parameters": {
"size": 9
},
"tree_item": "Miscellaneous/Buffer", "tree_item": "Miscellaneous/Buffer",
"type": "buffer" "type": "buffer"
}, },

View File

@ -15,6 +15,7 @@ onready var projects = $VBoxContainer/Layout/SplitRight/ProjectsPane/Projects
onready var layout = $VBoxContainer/Layout onready var layout = $VBoxContainer/Layout
var library var library
var preview_2d var preview_2d
var histogram
var preview_3d var preview_3d
var hierarchy var hierarchy
@ -131,6 +132,7 @@ func _ready() -> void:
layout.load_panes(config_cache) layout.load_panes(config_cache)
library = layout.get_pane("Library") library = layout.get_pane("Library")
preview_2d = layout.get_pane("Preview2D") preview_2d = layout.get_pane("Preview2D")
histogram = layout.get_pane("Histogram")
preview_3d = layout.get_pane("Preview3D") preview_3d = layout.get_pane("Preview3D")
preview_3d.connect("need_update", self, "update_preview_3d") preview_3d.connect("need_update", self, "update_preview_3d")
hierarchy = layout.get_pane("Hierarchy") hierarchy = layout.get_pane("Hierarchy")
@ -584,17 +586,13 @@ 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: histogram.set_generator(node.generator)
result = yield(result, "completed") preview_2d_background.set_generator(node.generator)
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) histogram.set_generator(null)
preview_2d_background.set_generator(null)
func update_preview_3d(previews : Array) -> void: func update_preview_3d(previews : Array) -> void:
var graph_edit : MMGraphEdit = get_current_graph_edit() var graph_edit : MMGraphEdit = get_current_graph_edit()
@ -610,7 +608,7 @@ 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

@ -2,6 +2,7 @@
[ext_resource path="res://material_maker/main_window.gd" type="Script" id=1] [ext_resource path="res://material_maker/main_window.gd" type="Script" id=1]
[ext_resource path="res://material_maker/main_window_layout.gd" type="Script" id=2] [ext_resource path="res://material_maker/main_window_layout.gd" type="Script" id=2]
[ext_resource path="res://material_maker/preview/preview_2d.tscn" type="PackedScene" id=3]
[ext_resource path="res://material_maker/preview/preview_3d.tscn" type="PackedScene" id=4] [ext_resource path="res://material_maker/preview/preview_3d.tscn" type="PackedScene" id=4]
[ext_resource path="res://material_maker/preview/preview_3d_ui.tscn" type="PackedScene" id=5] [ext_resource path="res://material_maker/preview/preview_3d_ui.tscn" type="PackedScene" id=5]
[ext_resource path="res://material_maker/widgets/tabs.gd" type="Script" id=6] [ext_resource path="res://material_maker/widgets/tabs.gd" type="Script" id=6]
@ -9,27 +10,13 @@
[ext_resource path="res://material_maker/icons/icons.svg" type="Texture" id=8] [ext_resource path="res://material_maker/icons/icons.svg" type="Texture" id=8]
[ext_resource path="res://material_maker/node_factory.gd" type="Script" id=9] [ext_resource path="res://material_maker/node_factory.gd" type="Script" id=9]
[ext_resource path="res://material_maker/theme/default.tres" type="Theme" id=10] [ext_resource path="res://material_maker/theme/default.tres" type="Theme" id=10]
[ext_resource path="res://material_maker/preview/preview_2d.gd" type="Script" id=11]
[sub_resource type="Shader" id=1] [sub_resource type="Shader" id=1]
code = "shader_type canvas_item; resource_local_to_scene = true
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);
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(min(m2.x*size.x, m2.y*size.y), 1.0)), 1.0);
}"
[sub_resource type="ShaderMaterial" id=2] [sub_resource type="ShaderMaterial" id=2]
resource_local_to_scene = true
shader = SubResource( 1 ) shader = SubResource( 1 )
shader_param/size = Vector2( 947, 682 )
[sub_resource type="AtlasTexture" id=3] [sub_resource type="AtlasTexture" id=3]
flags = 4 flags = 4
@ -127,20 +114,11 @@ size_flags_horizontal = 3
size_flags_vertical = 3 size_flags_vertical = 3
size_flags_stretch_ratio = 3.0 size_flags_stretch_ratio = 3.0
[node name="Preview2D" type="ColorRect" parent="VBoxContainer/Layout/SplitRight/ProjectsPane"] [node name="Preview2D" parent="VBoxContainer/Layout/SplitRight/ProjectsPane" instance=ExtResource( 3 )]
visible = false visible = false
material = SubResource( 2 ) material = SubResource( 2 )
anchor_right = 1.0 margin_right = 0.0
anchor_bottom = 1.0 margin_bottom = 0.0
rect_min_size = Vector2( 64, 64 )
rect_clip_content = true
mouse_filter = 1
size_flags_horizontal = 0
size_flags_vertical = 8
script = ExtResource( 11 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Preview3D" parent="VBoxContainer/Layout/SplitRight/ProjectsPane" instance=ExtResource( 4 )] [node name="Preview3D" parent="VBoxContainer/Layout/SplitRight/ProjectsPane" instance=ExtResource( 4 )]
margin_left = 0.0 margin_left = 0.0
@ -269,7 +247,6 @@ script = ExtResource( 9 )
[connection signal="tab_changed" from="VBoxContainer/Layout/Left/Top" to="VBoxContainer/Layout" method="_on_tab_changed"] [connection signal="tab_changed" from="VBoxContainer/Layout/Left/Top" to="VBoxContainer/Layout" method="_on_tab_changed"]
[connection signal="tab_changed" from="VBoxContainer/Layout/Left/Bottom" to="VBoxContainer/Layout" method="_on_tab_changed"] [connection signal="tab_changed" from="VBoxContainer/Layout/Left/Bottom" to="VBoxContainer/Layout" method="_on_tab_changed"]
[connection signal="dragged" from="VBoxContainer/Layout/SplitRight" to="VBoxContainer/Layout" method="_on_Right_dragged"] [connection signal="dragged" from="VBoxContainer/Layout/SplitRight" to="VBoxContainer/Layout" method="_on_Right_dragged"]
[connection signal="resized" from="VBoxContainer/Layout/SplitRight/ProjectsPane/Preview2D" to="VBoxContainer/Layout/SplitRight/ProjectsPane/Preview2D" method="on_resized"]
[connection signal="need_update" from="VBoxContainer/Layout/SplitRight/ProjectsPane/Preview3D" to="." method="update_preview_3d"] [connection signal="need_update" from="VBoxContainer/Layout/SplitRight/ProjectsPane/Preview3D" to="." method="update_preview_3d"]
[connection signal="no_more_tabs" from="VBoxContainer/Layout/SplitRight/ProjectsPane/Projects" to="." method="new_material"] [connection signal="no_more_tabs" from="VBoxContainer/Layout/SplitRight/ProjectsPane/Projects" to="." method="new_material"]
[connection signal="resized" from="VBoxContainer/Layout/SplitRight/ProjectsPane/Projects" to="VBoxContainer/Layout/SplitRight/ProjectsPane/Projects" method="_on_Projects_resized"] [connection signal="resized" from="VBoxContainer/Layout/SplitRight/ProjectsPane/Projects" to="VBoxContainer/Layout/SplitRight/ProjectsPane/Projects" method="_on_Projects_resized"]

View File

@ -10,6 +10,7 @@ const PANES = [
{ name="Library", scene=preload("res://material_maker/library.tscn"), position="TopLeft" }, { name="Library", scene=preload("res://material_maker/library.tscn"), position="TopLeft" },
{ name="Preview2D", scene=preload("res://material_maker/preview/preview_2d_panel.tscn"), position="BottomLeft" }, { name="Preview2D", scene=preload("res://material_maker/preview/preview_2d_panel.tscn"), position="BottomLeft" },
{ name="Preview3D", scene=preload("res://material_maker/preview/preview_3d_panel.tscn"), position="BottomLeft" }, { name="Preview3D", scene=preload("res://material_maker/preview/preview_3d_panel.tscn"), position="BottomLeft" },
{ name="Histogram", scene=preload("res://material_maker/widgets/histogram/histogram.tscn"), position="BottomLeft" },
{ name="Hierarchy", scene=preload("res://material_maker/widgets/graph_tree/hierarchy_pane.tscn"), position="TopRight" } { name="Hierarchy", scene=preload("res://material_maker/widgets/graph_tree/hierarchy_pane.tscn"), position="TopRight" }
] ]

View File

@ -5,7 +5,8 @@ var controls = {}
var ignore_parameter_change = "" var ignore_parameter_change = ""
var output_count = 0 var output_count = 0
var preview : TextureRect var preview : ColorRect
#var preview : TextureRect
var preview_index : int = -1 var preview_index : int = -1
var preview_position : int var preview_position : int
var preview_size : int var preview_size : int
@ -52,7 +53,7 @@ func on_parameter_changed(p, v) -> void:
o.value = gradient o.value = gradient
else: else:
print("unsupported widget "+str(o)) print("unsupported widget "+str(o))
update_shaders() get_parent().set_need_save()
func initialize_properties() -> void: func initialize_properties() -> void:
var parameter_names = [] var parameter_names = []
@ -81,33 +82,29 @@ func initialize_properties() -> void:
else: else:
print("unsupported widget "+str(o)) print("unsupported widget "+str(o))
func update_shaders() -> void:
get_parent().send_changed_signal()
update_preview()
func _on_text_changed(new_text, variable) -> void: func _on_text_changed(new_text, variable) -> void:
ignore_parameter_change = variable ignore_parameter_change = variable
generator.set_parameter(variable, new_text) generator.set_parameter(variable, new_text)
ignore_parameter_change = "" ignore_parameter_change = ""
update_shaders() get_parent().set_need_save()
func _on_value_changed(new_value, variable) -> void: func _on_value_changed(new_value, variable) -> void:
ignore_parameter_change = variable ignore_parameter_change = variable
generator.set_parameter(variable, new_value) generator.set_parameter(variable, new_value)
ignore_parameter_change = "" ignore_parameter_change = ""
update_shaders() get_parent().set_need_save()
func _on_color_changed(new_color, variable) -> void: func _on_color_changed(new_color, variable) -> void:
ignore_parameter_change = variable ignore_parameter_change = variable
generator.set_parameter(variable, new_color) generator.set_parameter(variable, new_color)
ignore_parameter_change = "" ignore_parameter_change = ""
update_shaders() get_parent().set_need_save()
func _on_gradient_changed(new_gradient, variable) -> void: func _on_gradient_changed(new_gradient, variable) -> void:
ignore_parameter_change = variable ignore_parameter_change = variable
generator.set_parameter(variable, MMType.serialize_value(new_gradient)) generator.set_parameter(variable, MMType.serialize_value(new_gradient))
ignore_parameter_change = "" ignore_parameter_change = ""
update_shaders() get_parent().set_need_save()
func create_parameter_control(p : Dictionary) -> Control: func create_parameter_control(p : Dictionary) -> Control:
var control = null var control = null
@ -150,7 +147,8 @@ func save_preview_widget() -> void:
func restore_preview_widget() -> void: func restore_preview_widget() -> void:
if preview == null: if preview == null:
preview = TextureRect.new() preview = preload("res://material_maker/preview/preview_2d.tscn").instance()
preview.shader = "uniform vec2 size;void fragment() {COLOR = preview_2d(UV);}"
preview.visible = false preview.visible = false
preview_position = get_child_count() preview_position = get_child_count()
if preview.visible: if preview.visible:
@ -295,7 +293,7 @@ func edit_generator() -> void:
func update_generator(shader_model) -> void: func update_generator(shader_model) -> void:
generator.set_shader_model(shader_model) generator.set_shader_model(shader_model)
update_node() update_node()
update_shaders() get_parent().set_need_save()
func load_generator() -> void: func load_generator() -> void:
var dialog = FileDialog.new() var dialog = FileDialog.new()
@ -371,14 +369,9 @@ func update_preview(size : int = 0) -> void:
preview_timer.start(0.2) preview_timer.start(0.2)
func do_update_preview() -> void: func do_update_preview() -> void:
var result = generator.render(preview_index, preview_size, true)
while result is GDScriptFunctionState:
result = yield(result, "completed")
if preview.texture == null:
preview.texture = ImageTexture.new()
result.copy_to_texture(preview.texture)
result.release()
if !preview.visible: if !preview.visible:
add_child(preview) add_child(preview)
move_child(preview, preview_position) move_child(preview, preview_position)
preview.visible = true preview.visible = true
preview.set_generator(generator, preview_index)
preview.rect_min_size = Vector2(preview_size, preview_size)

View File

@ -8,3 +8,6 @@ margin_bottom = 29.0
title = "Generic" title = "Generic"
show_close = true show_close = true
script = ExtResource( 1 ) script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}

View File

@ -5,12 +5,6 @@ var fixed_lines : int = 0
func _ready() -> void: func _ready() -> void:
update_node() update_node()
func update_preview_buttons(index : int) -> void:
for i in range(generator.parameters.outputs):
if i != index:
var line = get_child(i)
line.get_child(2).pressed = false
func update_node() -> void: func update_node() -> void:
if generator == null or !generator.parameters.has("outputs") or !generator.parameters.has("choices"): if generator == null or !generator.parameters.has("outputs") or !generator.parameters.has("choices"):
return return
@ -48,7 +42,6 @@ func update_node() -> void:
sizer.add_child(control) sizer.add_child(control)
control.connect("value_changed", self, "_on_value_changed", [ l.name ]) control.connect("value_changed", self, "_on_value_changed", [ l.name ])
controls[l.name] = control controls[l.name] = control
sizer.add_child(preload("res://material_maker/widgets/preview_button.tscn").instance())
add_child(sizer) add_child(sizer)
else: else:
# Keep lines with controls # Keep lines with controls
@ -64,22 +57,12 @@ func update_node() -> void:
var sizer = HBoxContainer.new() var sizer = HBoxContainer.new()
var input_label = Label.new() var input_label = Label.new()
sizer.add_child(input_label) sizer.add_child(input_label)
if get_child_count() < 5:
var space = Control.new()
space.size_flags_horizontal = SIZE_EXPAND | SIZE_FILL
sizer.add_child(space)
var button = preload("res://material_maker/widgets/preview_button.tscn").instance()
sizer.add_child(button)
button.connect("toggled", self, "on_preview_button", [ get_child_count()-1 ])
add_child(sizer) add_child(sizer)
rect_size = Vector2(0, 0) rect_size = Vector2(0, 0)
for i in range(get_child_count()): for i in range(get_child_count()):
var sizer = get_child(i) var sizer = get_child(i)
var has_input = true var has_input = true
var has_output = false var has_output = i < output_count
if i < 5:
has_output = i < output_count
sizer.get_child(sizer.get_child_count()-1).visible = has_output
if i >= input_count: if i >= input_count:
sizer.get_child(0).text = "" sizer.get_child(0).text = ""
has_input = false has_input = false

View File

@ -3,8 +3,6 @@
[ext_resource path="res://material_maker/nodes/switch.gd" type="Script" id=1] [ext_resource path="res://material_maker/nodes/switch.gd" type="Script" id=1]
[ext_resource path="res://material_maker/widgets/preview_button.tscn" type="PackedScene" id=2] [ext_resource path="res://material_maker/widgets/preview_button.tscn" type="PackedScene" id=2]
[sub_resource type="Theme" id=1] [sub_resource type="Theme" id=1]
[node name="Switch" type="GraphNode"] [node name="Switch" type="GraphNode"]
@ -36,6 +34,9 @@ slot/2/right_enabled = false
slot/2/right_type = 0 slot/2/right_type = 0
slot/2/right_color = Color( 1, 1, 1, 1 ) slot/2/right_color = Color( 1, 1, 1, 1 )
script = ExtResource( 1 ) script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="HBox1" type="HBoxContainer" parent="."] [node name="HBox1" type="HBoxContainer" parent="."]
margin_left = 16.0 margin_left = 16.0
@ -69,9 +70,9 @@ margin_bottom = 16.0
[node name="HBox2" type="HBoxContainer" parent="."] [node name="HBox2" type="HBoxContainer" parent="."]
margin_left = 16.0 margin_left = 16.0
margin_top = 40.0 margin_top = 41.0
margin_right = 135.0 margin_right = 135.0
margin_bottom = 56.0 margin_bottom = 57.0
[node name="Label" type="Label" parent="HBox2"] [node name="Label" type="Label" parent="HBox2"]
margin_top = 1.0 margin_top = 1.0
@ -99,9 +100,9 @@ margin_bottom = 16.0
[node name="HBox3" type="HBoxContainer" parent="."] [node name="HBox3" type="HBoxContainer" parent="."]
margin_left = 16.0 margin_left = 16.0
margin_top = 57.0 margin_top = 58.0
margin_right = 135.0 margin_right = 135.0
margin_bottom = 73.0 margin_bottom = 74.0
[node name="Label" type="Label" parent="HBox3"] [node name="Label" type="Label" parent="HBox3"]
margin_top = 1.0 margin_top = 1.0

View File

@ -1,4 +1,4 @@
extends MMGraphNodeBase extends MMGraphNodeGeneric
class Cursor: class Cursor:
extends Control extends Control
@ -69,19 +69,19 @@ func _ready() -> void:
cursor_out_max = Cursor.new(Color(1.0, 1.0, 1.0), 1.0, false) cursor_out_max = Cursor.new(Color(1.0, 1.0, 1.0), 1.0, false)
$Histogram.add_child(cursor_out_max) $Histogram.add_child(cursor_out_max)
func set_generator(g) -> void: func update_node() -> void:
.set_generator(g)
generator.connect("parameter_changed", self, "on_parameter_changed")
_on_Mode_item_selected(0) _on_Mode_item_selected(0)
on_parameter_changed("__input_changed__", 0)
# Preview
restore_preview_widget()
func on_parameter_changed(p, v) -> void: func on_parameter_changed(p, v) -> void:
if p == "__input_changed__": if p == "__input_changed__":
var source = generator.get_source(0) var source = generator.get_source(0)
var result = source.generator.render(source.output_index, 128, true) if source != null:
while result is GDScriptFunctionState: $Histogram.set_generator(source.generator, source.output_index)
result = yield(result, "completed") else:
result.copy_to_texture($Histogram.get_image_texture()) $Histogram.set_generator(null, 0)
result.release()
func get_parameter(n : String) -> float: func get_parameter(n : String) -> float:
var value = generator.get_parameter(n) var value = generator.get_parameter(n)

View File

@ -1,24 +1,66 @@
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) var output : int = 0
func on_resized() -> void: func set_generator(g : MMGenBase, o : int = 0) -> void:
material.set_shader_param("size", rect_size) if is_instance_valid(generator):
setup_controls(generator) generator.disconnect("parameter_changed", self, "on_parameter_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
output = o
generator.connect("parameter_changed", self, "on_parameter_changed")
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)
var gen_output_defs = generator.get_output_defs()
if ! gen_output_defs.empty():
var context : MMGenContext = MMGenContext.new()
source = generator.get_shader_code("uv", output, 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, [])
# Update shader
material.shader.code = MMGenBase.generate_preview_shader(source, source.type, shader)
# Get parameter values from the shader code
var regex = RegEx.new()
regex.compile("uniform\\s+(\\w+)\\s+([\\w_\\d]+)\\s*=\\s*([^;]+);")
for p in regex.search_all(material.shader.code):
material.set_shader_param(p.strings[2], float(p.strings[3]))
# Set texture params
if source.has("textures"):
for k in source.textures.keys():
material.set_shader_param(k, source.textures[k])
func on_parameter_changed(n : String, v) -> void:
if n == "__output_changed__" and output == v:
set_generator(generator, output)
var p = generator.get_parameter_def(n)
if p.has("type"):
match p.type:
"float", "color", "gradient":
pass
_:
set_generator(generator, output)
func on_float_parameters_changed(parameter_changes : Dictionary) -> void:
for n in parameter_changes.keys():
for p in VisualServer.shader_get_param_list(material.shader.get_rid()):
if p.name == n:
material.set_shader_param(n, parameter_changes[n])
break
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,15 @@
[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; resource_local_to_scene = true
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 +26,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"]

View File

@ -1,9 +1,5 @@
extends ViewportContainer extends ViewportContainer
const ENVIRONMENTS = [
"experiment", "lobby", "night", "park", "schelde"
]
const CAMERA_DISTANCE_MIN = 1.0 const CAMERA_DISTANCE_MIN = 1.0
const CAMERA_DISTANCE_MAX = 10.0 const CAMERA_DISTANCE_MAX = 10.0

View File

@ -3,10 +3,11 @@
[ext_resource path="res://material_maker/preview/preview_3d.gd" type="Script" id=1] [ext_resource path="res://material_maker/preview/preview_3d.gd" type="Script" id=1]
[ext_resource path="res://material_maker/preview/preview_3d_scene.tscn" type="PackedScene" id=2] [ext_resource path="res://material_maker/preview/preview_3d_scene.tscn" type="PackedScene" id=2]
[sub_resource type="World" id=1] [sub_resource type="World" id=1]
[node name="Preview3D" type="ViewportContainer"] [node name="Preview3D" type="ViewportContainer" groups=[
"preview",
]]
visible = false visible = false
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0

View File

@ -8,7 +8,9 @@ export var step : float = 0.0 setget set_step
var sliding : bool = false var sliding : bool = false
var start_position : float var start_position : float
var last_position : float
var start_value : float var start_value : float
var modifiers : int
var from_lower_bound : bool = false var from_lower_bound : bool = false
var from_upper_bound : bool = false var from_upper_bound : bool = false
@ -45,28 +47,60 @@ func do_update(update_text : bool = true) -> void:
else: else:
cursor.rect_position.x = 0 cursor.rect_position.x = 0
func get_modifiers(event):
var modifiers = 0
if event.shift:
modifiers |= 1
if event.control:
modifiers |= 2
if event.alt:
modifiers |= 4
return modifiers
func _on_LineEdit_gui_input(event : InputEvent) -> void: func _on_LineEdit_gui_input(event : InputEvent) -> void:
if event is InputEventMouseButton and event.button_index == BUTTON_LEFT: if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
if event.is_pressed(): if event.is_pressed():
start_position = event.position.x last_position = event.position.x
start_position = last_position
start_value = value start_value = value
sliding = true sliding = true
from_lower_bound = value <= min_value from_lower_bound = value <= min_value
from_upper_bound = value >= max_value from_upper_bound = value >= max_value
modifiers = get_modifiers(event)
else: else:
sliding = false sliding = false
elif sliding and event is InputEventMouseMotion and event.button_mask == BUTTON_MASK_LEFT: elif sliding and event is InputEventMouseMotion and event.button_mask == BUTTON_MASK_LEFT:
var delta : float = event.position.x-start_position var new_modifiers = get_modifiers(event)
var v : float = start_value+sign(delta)*pow(abs(delta)*0.005, 2)*abs(max_value - min_value) if new_modifiers != modifiers:
if step != 0: start_position = last_position
v = min_value+floor((v - min_value)/step)*step start_value = value
if !from_lower_bound and v < min_value: modifiers = new_modifiers
v = min_value else:
if !from_upper_bound and v > max_value: last_position = event.position.x
v = max_value var delta : float = last_position-start_position
set_value(v) var current_step = step
select(0, 0) if event.control:
emit_signal("value_changed", value) delta *= 0.2
elif event.shift:
delta *= 5.0
if event.alt:
current_step *= 0.01
var v : float = start_value+sign(delta)*pow(abs(delta)*0.005, 2)*abs(max_value - min_value)
if current_step != 0:
v = min_value+floor((v - min_value)/current_step)*current_step
if !from_lower_bound and v < min_value:
v = min_value
if !from_upper_bound and v > max_value:
v = max_value
set_value(v)
select(0, 0)
emit_signal("value_changed", value)
elif event is InputEventKey and !event.echo:
match event.scancode:
KEY_SHIFT, KEY_CONTROL, KEY_ALT:
start_position = last_position
start_value = value
modifiers = get_modifiers(event)
func _on_LineEdit_text_changed(new_text : String) -> void: func _on_LineEdit_text_changed(new_text : String) -> void:
if new_text.is_valid_float(): if new_text.is_valid_float():

View File

@ -14,6 +14,9 @@ max_length = 20
context_menu_enabled = false context_menu_enabled = false
caret_blink = true caret_blink = true
script = ExtResource( 1 ) script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Slider" type="ColorRect" parent="."] [node name="Slider" type="ColorRect" parent="."]
anchor_top = 1.0 anchor_top = 1.0

View File

@ -147,8 +147,11 @@ func get_gradient_color(x) -> Color:
func update_shader() -> void: func update_shader() -> void:
var shader var shader
shader = "shader_type canvas_item;\n" shader = "shader_type canvas_item;\n"
shader += value.get_shader("gradient") var params = value.get_shader_params("")
shader += "void fragment() { COLOR = gradient(UV.x); }" 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) $Gradient.material.shader.set_code(shader)
emit_signal("updated", value) emit_signal("updated", value)

View File

@ -25,7 +25,7 @@ func update_from_graph_edit(graph_edit) -> void:
update_index += 1 update_index += 1
for g in item_from_gen.keys(): for g in item_from_gen.keys():
if is_instance_valid(g): if is_instance_valid(g):
g.disconnect("output_changed", self, "on_gen_output_changed") g.disconnect("parameter_changed", self, "on_gen_parameter_changed")
item_from_gen = {} item_from_gen = {}
set_column_expand(0, true) set_column_expand(0, true)
columns = preview+1 columns = preview+1
@ -74,7 +74,7 @@ func fill_item(item : TreeItem, generator : MMGenGraph, selected : MMGenGraph, n
item.set_custom_color(0, Color(1, 1, 1)) item.set_custom_color(0, Color(1, 1, 1))
item.set_metadata(0, generator) item.set_metadata(0, generator)
item_from_gen[generator] = item item_from_gen[generator] = item
generator.connect("output_changed", self, "on_gen_output_changed", [ generator ]) generator.connect("parameter_changed", self, "on_gen_parameter_changed", [ generator ])
if preview > 0 and generator.get_output_defs().size() > 0: if preview > 0 and generator.get_output_defs().size() > 0:
for i in range(min(preview, generator.get_output_defs().size())): for i in range(min(preview, generator.get_output_defs().size())):
item.set_icon(i+1, default_texture) item.set_icon(i+1, default_texture)
@ -97,7 +97,11 @@ func on_view_updated(generator) -> void:
if item_from_gen.has(current_generator): if item_from_gen.has(current_generator):
item_from_gen[current_generator].set_custom_color(0, Color(0.5, 0.5, 1)) item_from_gen[current_generator].set_custom_color(0, Color(0.5, 0.5, 1))
func on_gen_output_changed(index, generator) -> void: func on_gen_parameter_changed(param_name : String, index : int, generator) -> void:
if param_name == "__output_changed__":
on_gen_output_changed(index, generator)
func on_gen_output_changed(index : int, generator) -> void:
if item_from_gen.has(generator) and index < preview: if item_from_gen.has(generator) and index < preview:
if !pending_updates.has(generator): if !pending_updates.has(generator):
pending_updates[generator] = [index] pending_updates[generator] = [index]

View File

@ -1,10 +1,89 @@
extends Control extends Control
func update_histogram() -> void: var generator : MMGenBase = null
pass var output : int = 0
var updating : bool = false
var update_again : bool = false
func get_image_texture() -> ImageTexture: func get_image_texture() -> ImageTexture:
return $ViewportImage/ColorRect.material.get_shader_param("tex") return $ViewportImage/ColorRect.material.get_shader_param("tex")
func get_histogram_texture() -> ImageTexture: func get_histogram_texture() -> ImageTexture:
return $Control.material.get_shader_param("tex") return $Control.material.get_shader_param("tex")
func set_generator(g : MMGenBase, o : int = 0) -> void:
if is_instance_valid(generator):
generator.disconnect("parameter_changed", self, "on_parameter_changed")
var source = { defs="", code="", textures={}, type="f", f="1.0" }
if is_instance_valid(g):
generator = g
output = o
generator.connect("parameter_changed", self, "on_parameter_changed")
var param_defs : Array = generator.get_parameter_defs()
var gen_output_defs = generator.get_output_defs()
if ! gen_output_defs.empty():
var context : MMGenContext = MMGenContext.new()
source = generator.get_shader_code("uv", output, context)
while source is GDScriptFunctionState:
source = yield(source, "completed")
if source.empty():
source = { defs="", code="", textures={}, type="f", f="1.0" }
# Update shader
$ViewportImage/ColorRect.material.shader.code = MMGenBase.generate_preview_shader(source, source.type, "uniform vec2 size;void fragment() {COLOR = preview_2d(UV);}")
# Get parameter values from the shader code
var regex = RegEx.new()
regex.compile("uniform\\s+(\\w+)\\s+([\\w_\\d]+)\\s*=\\s*([^;]+);")
for p in regex.search_all($ViewportImage/ColorRect.material.shader.code):
$ViewportImage/ColorRect.material.set_shader_param(p.strings[2], float(p.strings[3]))
# Set texture params
if source.has("textures"):
for k in source.textures.keys():
$ViewportImage/ColorRect.material.set_shader_param(k, source.textures[k])
update_histogram()
func on_parameter_changed(n : String, v) -> void:
if n == "__input_changed__":
set_generator(generator, output)
var p = generator.get_parameter_def(n)
if p.has("type"):
match p.type:
"float", "color", "gradient":
pass
_:
set_generator(generator, output)
func on_float_parameters_changed(parameter_changes : Dictionary) -> void:
var need_update : bool = false
for n in parameter_changes.keys():
for p in VisualServer.shader_get_param_list($ViewportImage/ColorRect.material.shader.get_rid()):
if p.name == n:
$ViewportImage/ColorRect.material.set_shader_param(n, parameter_changes[n])
need_update = true
break
if need_update:
update_histogram()
func update_histogram() -> void:
update_again = true
if !updating && is_visible_in_tree():
updating = true
while update_again:
update_again = false
$ViewportImage.render_target_update_mode = Viewport.UPDATE_ONCE
$ViewportImage.update_worlds()
yield(get_tree(), "idle_frame")
yield(get_tree(), "idle_frame")
$ViewportHistogram1.render_target_update_mode = Viewport.UPDATE_ONCE
$ViewportHistogram1.update_worlds()
yield(get_tree(), "idle_frame")
yield(get_tree(), "idle_frame")
$ViewportHistogram2.render_target_update_mode = Viewport.UPDATE_ONCE
$ViewportHistogram2.update_worlds()
yield(get_tree(), "idle_frame")
yield(get_tree(), "idle_frame")
updating = false
func _on_Histogram_visibility_changed():
if is_visible_in_tree():
update_histogram()

View File

@ -96,7 +96,9 @@ resource_local_to_scene = true
shader = SubResource( 10 ) shader = SubResource( 10 )
shader_param/tex = SubResource( 11 ) shader_param/tex = SubResource( 11 )
[node name="Histogram" type="Control"] [node name="Histogram" type="Control" groups=[
"preview",
]]
margin_right = 64.0 margin_right = 64.0
margin_bottom = 64.0 margin_bottom = 64.0
script = ExtResource( 1 ) script = ExtResource( 1 )
@ -110,7 +112,7 @@ transparent_bg = true
hdr = false hdr = false
usage = 0 usage = 0
render_target_v_flip = true render_target_v_flip = true
render_target_update_mode = 3 render_target_update_mode = 1
[node name="ColorRect" type="ColorRect" parent="ViewportImage"] [node name="ColorRect" type="ColorRect" parent="ViewportImage"]
material = SubResource( 3 ) material = SubResource( 3 )
@ -122,10 +124,10 @@ rect_min_size = Vector2( 256, 256 )
size = Vector2( 128, 128 ) size = Vector2( 128, 128 )
own_world = true own_world = true
transparent_bg = true transparent_bg = true
hdr = false disable_3d = true
usage = 0 keep_3d_linear = true
render_target_v_flip = true render_target_v_flip = true
render_target_update_mode = 3 render_target_update_mode = 1
[node name="ColorRect" type="ColorRect" parent="ViewportHistogram1"] [node name="ColorRect" type="ColorRect" parent="ViewportHistogram1"]
material = SubResource( 6 ) material = SubResource( 6 )
@ -138,7 +140,6 @@ size = Vector2( 128, 2 )
transparent_bg = true transparent_bg = true
disable_3d = true disable_3d = true
keep_3d_linear = true keep_3d_linear = true
usage = 0
render_target_v_flip = true render_target_v_flip = true
render_target_update_mode = 3 render_target_update_mode = 3
@ -155,3 +156,4 @@ anchor_bottom = 1.0
__meta__ = { __meta__ = {
"_edit_use_anchors_": false "_edit_use_anchors_": false
} }
[connection signal="visibility_changed" from="." to="." method="_on_Histogram_visibility_changed"]