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
"""
signal parameter_changed
signal output_changed(index)
signal parameter_changed(n, v)
class InputPort:
var generator : MMGenBase = null
@ -93,8 +92,8 @@ func init_parameters() -> void:
func set_position(p) -> void:
position = p
if has_randomness() and !is_seed_locked():
source_changed(0)
if has_randomness() and !is_seed_locked() and is_inside_tree():
get_tree().call_group("preview", "on_float_parameters_changed", { "seed_o"+str(get_instance_id()): get_seed() })
func get_type() -> String:
return "generic"
@ -113,21 +112,60 @@ func get_parameter_def(param_name : String) -> Dictionary:
return {}
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:
var old_value = parameters[n] if parameters.has(n) else null
parameters[n] = v
source_changed(0)
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:
var targets = get_targets(output_index)
for target in targets:
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:
emit_signal("parameter_changed", "__input_changed__", 0)
func source_changed(input_index : int) -> void:
emit_signal("parameter_changed", "__input_changed__", input_index)
for i in range(get_output_defs().size()):
notify_output_change(i)
@ -162,7 +200,7 @@ func get_input_shader(input_index : int) -> Dictionary:
func get_shader(output_index : int, context) -> Dictionary:
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
code = "shader_type canvas_item;\n"
code += "render_mode blend_disabled;\n"
@ -185,6 +223,7 @@ func generate_preview_shader(src_code, type) -> String:
shader_code += preview_code
#print("GENERATED SHADER:\n"+shader_code)
code += shader_code
code += main_fct
return code
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)
"""
var updated : bool = false
var material : ShaderMaterial = null
var updating : bool = false
var update_again : bool = false
func _ready() -> void:
material = ShaderMaterial.new()
material.shader = Shader.new()
if !parameters.has("size"):
parameters.size = 9
add_to_group("preview")
func get_type() -> String:
return "buffer"
@ -31,24 +36,56 @@ func get_input_defs() -> Array:
func get_output_defs() -> Array:
return [ { type="rgba" }, { type="rgba" } ]
func source_changed(input_port_index : int) -> void:
updated = false
.source_changed(input_port_index)
func source_changed(_input_port_index : int) -> void:
call_deferred("update_shader")
func _get_shader_code(uv : String, output_index : int, context : MMGenContext) -> Dictionary:
var source = get_source(0)
if source != null and !updated:
var result = source.generator.render(source.output_index, pow(2, parameters.size))
while result is GDScriptFunctionState:
result = yield(result, "completed")
result.copy_to_texture(texture)
result.release()
texture.flags = Texture.FLAG_MIPMAPS
updated = true
var rv = ._get_shader_code_lod(uv, output_index, context, 0 if output_index == 0 else parameters.lod)
while rv is GDScriptFunctionState:
rv = yield(rv, "completed")
return rv
func update_shader() -> void:
var context : MMGenContext = MMGenContext.new()
var source = {}
var source_output = get_source(0)
if source_output != null:
source = source_output.generator.get_shader_code("uv", source_output.output_index, context)
while source is GDScriptFunctionState:
source = yield(source, "completed")
if source.empty():
source = { defs="", code="", textures={}, rgba="vec4(0.0)" }
material.shader.code = mm_renderer.generate_shader(source)
if source.has("textures"):
for k in source.textures.keys():
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:
data.type = "buffer"

View File

@ -5,7 +5,12 @@ class_name MMGenMaterial
var export_paths = {}
var material : SpatialMaterial
var shader_materials = {}
var need_update = {}
var need_render = {}
var generated_textures = {}
var updating : bool = false
var update_again : bool = false
const TEXTURE_LIST = [
{ port=0, texture="albedo", sources=[0] },
@ -38,7 +43,12 @@ const TEXTURE_SIZE_DEFAULT = 10 # 1024x1024
func _ready() -> void:
for t in TEXTURE_LIST:
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()
add_to_group("preview")
func can_be_deleted() -> bool:
return false
@ -74,34 +84,86 @@ func set_parameter(p, v) -> void:
func source_changed(input_index : int) -> void:
for t in TEXTURE_LIST:
if t.has("sources") and t.sources.find(input_index) != -1:
generated_textures[t.texture] = null
need_update[t.texture] = true
update_preview()
func render_textures() -> void:
for t in TEXTURE_LIST:
var texture = null
var result
if t.has("port"):
if generated_textures[t.texture] != null:
if !need_update[t.texture]:
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:
generated_textures[t.texture] = null
need_update[t.texture] = false
continue
while result is GDScriptFunctionState:
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.release()
# To work, this must be set after calling `copy_to_texture()`
texture.flags |= ImageTexture.FLAG_ANISOTROPIC_FILTER
# Disable filtering for small textures, as they're considered to be used
# for a pixel art style
if texture.get_size().x <= 128:
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:
render_textures()

View File

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

View File

@ -39,7 +39,7 @@ func get_input_defs() -> Array:
func get_output_defs() -> 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()
rv.push_back({ name=n, type="any" })
return rv
@ -73,6 +73,9 @@ func set_parameter(p, v) -> void:
parent.reconnect_outputs(self, outputs_changes)
.set_parameter(p, v)
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
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:
rv = yield(rv, "completed")
return rv
return { globals=[], defs="", code="", textures={} }
return { globals=[], defs="", code="", textures={}, type="f", f="0.0" }
func _serialize(data: Dictionary) -> Dictionary:
return data

View File

@ -5,19 +5,24 @@ class_name MMGenRenderer
export(String) var debug_path = ""
var debug_file_index : int = 0
var common_shader : String
var rendering : bool = false
signal done
func _ready() -> void:
$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
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 += common_shader
code += "\n"
if src_code.has("textures"):
for t in src_code.textures.keys():
@ -38,52 +43,28 @@ static func generate_shader(src_code) -> String:
code += shader_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:
for k in textures.keys():
shader_material.set_shader_param(k+"_tex", textures[k])
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:
if debug_path != null and debug_path != "":
var file_name = debug_path+str(debug_file_index)+".shader"
@ -126,4 +107,5 @@ func save_to_file(fn : String) -> void:
func release() -> void:
rendering = false
hdr = false
emit_signal("done")

View File

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

View File

@ -22,7 +22,7 @@
"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"
},
{

View File

@ -29,7 +29,7 @@
"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"
},
{

View File

@ -13,7 +13,7 @@
},
"shader_model": {
"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": [
],
@ -21,13 +21,13 @@
"name": "FBM",
"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"
}
],
"parameters": [
{
"default": 2,
"default": 7,
"label": "Noise",
"name": "noise",
"type": "enum",
@ -43,6 +43,26 @@
{
"name": "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() {
vec2 uv = UV;
vec4 preview_2d(vec2 uv) {
$(code)
COLOR = vec4(vec3($(value)), 1.0);
return vec4(vec3($(value)), 1.0);
}

View File

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

View File

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

View File

@ -1,10 +1,9 @@
void fragment() {
vec2 uv = UV;
vec4 preview_2d(vec2 uv) {
$(code)
float d = $(value);
vec3 col = vec3(cos(d*min(256, preview_size)));
col *= clamp(1.0-d*d, 0.0, 1.0);
col *= vec3(1.0, vec2(step(-0.015, d)));
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);
}
void fragment() {
vec2 uv = UV-vec2(0.5);
vec4 preview_2d(vec2 uv) {
uv -= vec2(0.5);
vec3 p = vec3(uv, 2.0-raymarch(vec3(uv, 2.0), vec3(0.0, 0.0, -1.0)));
vec3 n = normal(p);
vec3 l = vec3(5.0, 5.0, 10.0);
@ -29,5 +29,5 @@ void fragment() {
float o = step(p.z, 0.001);
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;
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);
}
void fragment() {
vec2 uv = UV-vec2(0.5);
vec4 preview_2d(vec2 uv) {
uv -= vec2(0.5);
vec2 rm = raymarch(vec3(uv, 2.0), vec3(0.0, 0.0, -1.0));
vec3 p = vec3(uv, 2.0-rm.x);
vec3 n = normal(p);
@ -41,5 +41,5 @@ void fragment() {
float o = step(p.z, 0.001);
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;
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);
}
void fragment() {
vec2 uv = UV-vec2(0.5);
vec4 preview_2d(vec2 uv) {
uv -= vec2(0.5);
vec3 p = vec3(uv, 2.0-raymarch(vec3(uv, 2.0), vec3(0.0, 0.0, -1.0)));
vec3 n = normal(p);
vec3 l = vec3(5.0, 5.0, 10.0);
@ -33,5 +33,5 @@ void fragment() {
float o = step(p.z, 0.001);
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;
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
},
"parameters": {
"Randomness": 0.5,
"angle": -1,
"layers": 5,
"length": 0.25,
@ -23,12 +22,13 @@
"name": "Scratches",
"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"
}
],
"parameters": [
{
"control": "None",
"default": 0.25,
"label": "Length",
"max": 1,
@ -38,6 +38,7 @@
"type": "float"
},
{
"control": "None",
"default": 0.5,
"label": "Width",
"max": 1,
@ -47,6 +48,7 @@
"type": "float"
},
{
"control": "None",
"default": 4,
"label": "Layers",
"max": 10,
@ -56,6 +58,7 @@
"type": "float"
},
{
"control": "None",
"default": 0.5,
"label": "Waviness",
"max": 1,
@ -65,6 +68,7 @@
"type": "float"
},
{
"control": "None",
"default": 0,
"label": "Angle",
"max": 180,
@ -74,6 +78,7 @@
"type": "float"
},
{
"control": "None",
"default": 0.5,
"label": "Randomness",
"max": 1,

View File

@ -5,14 +5,9 @@
"y": 0
},
"parameters": {
"a": 0,
"r": 0.3,
"rx": 3,
"ry": 3,
"s": 0.3,
"x": 0.35,
"y": 0,
"z": 0
"ry": 3
},
"shader_model": {
"code": "",
@ -29,7 +24,7 @@
"name": "Repeat",
"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"
}
],

View File

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

View File

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

View File

@ -22,7 +22,7 @@
"name": "TEX3D FBM",
"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"
}
],

View File

@ -15,7 +15,7 @@
},
"shader_model": {
"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": [
],

View File

@ -36,7 +36,7 @@
"name": "Tiler",
"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"
}
],

View File

@ -36,7 +36,7 @@
"name": "Color Tiler",
"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"
}
],

View File

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

View File

@ -1,34 +1,82 @@
{
"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,
"to": "Material",
"to_port": 4
},
{
"from": "graph",
"from_port": 1,
"from": "colorize_3",
"from_port": 0,
"to": "Material",
"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",
@ -39,6 +87,9 @@
},
"nodes": [
{
"export_paths": {
},
"name": "Material",
"node_position": {
"x": -28,
@ -52,477 +103,237 @@
"r": 1,
"type": "Color"
},
"ao_light_affect": 1,
"ao": 1,
"depth_scale": 0.2,
"emission_energy": 1,
"metallic": 1,
"normal_scale": 1,
"normal": 1,
"roughness": 1,
"size": 11,
"subsurf_scatter_strength": 0
"sss": 0
},
"type": "material"
},
{
"connections": [
{
"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",
"name": "colorize",
"node_position": {
"x": -353.865601,
"y": 6.860606
"x": -591.193665,
"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": {
"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": {

View File

@ -1,23 +1,5 @@
{
"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_port": 0,
@ -30,12 +12,6 @@
"to": "transform",
"to_port": 0
},
{
"from": "bricks",
"from_port": 1,
"to": "transform",
"to_port": 3
},
{
"from": "blend",
"from_port": 0,
@ -59,6 +35,30 @@
"from_port": 0,
"to": "Material",
"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",
@ -69,6 +69,9 @@
},
"nodes": [
{
"export_paths": {
},
"name": "Material",
"node_position": {
"x": 70,
@ -82,148 +85,17 @@
"r": 1,
"type": "Color"
},
"ao_light_affect": 1,
"ao": 1,
"depth_scale": 1,
"emission_energy": 1,
"metallic": 1,
"normal_scale": 1,
"normal": 1,
"roughness": 1,
"size": 11,
"subsurf_scatter_strength": 0
"sss": 0
},
"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",
"node_position": {
@ -311,7 +183,7 @@
"y": 165.542206
},
"parameters": {
"size": 4
},
"size": {
"x": 280,
@ -328,15 +200,31 @@
"y": -40.645294
},
"parameters": {
"amount": 0.5,
"param0": 11,
"param1": 0.995,
"param2": 0,
"param3": 0,
"param4": 1,
"size": 4
"param4": 1
},
"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": {

View File

@ -255,6 +255,9 @@
},
"nodes": [
{
"export_paths": {
},
"name": "Material",
"node_position": {
"x": 424,
@ -268,14 +271,14 @@
"r": 1,
"type": "Color"
},
"ao_light_affect": 0.95,
"ao": 1,
"depth_scale": 0,
"emission_energy": 1,
"metallic": 1,
"normal_scale": 1,
"normal": 1,
"roughness": 1,
"size": 11,
"subsurf_scatter_strength": 0
"sss": 0
},
"type": "material"
},
@ -286,7 +289,7 @@
"y": 34.016663
},
"parameters": {
"steps": 6
},
"type": "invert"
},
@ -328,21 +331,21 @@
"to_port": 0
},
{
"from": "_2_2_2_2",
"from": "blend",
"from_port": 0,
"to": "gen_outputs",
"to": "mwf_create_map",
"to_port": 0
},
{
"from": "bricks",
"from_port": 1,
"to": "_2_2_2_2",
"to": "mwf_create_map",
"to_port": 1
},
{
"from": "blend",
"from": "mwf_create_map",
"from_port": 0,
"to": "_2_2_2_2",
"to": "gen_outputs",
"to_port": 0
}
],
@ -371,7 +374,7 @@
"y": -369.233337
},
"parameters": {
"steps": 6
},
"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",
"node_position": {
@ -555,6 +497,18 @@
"color": 1
},
"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": {
@ -609,14 +563,7 @@
"y": -230.983337
},
"parameters": {
"color": {
"a": 1,
"b": 1,
"g": 1,
"r": 1,
"type": "Color"
},
"name": 0
},
"type": "combine"
},
@ -1108,14 +1055,7 @@
"y": 39.197388
},
"parameters": {
"color": {
"a": 1,
"b": 1,
"g": 1,
"r": 1,
"type": "Color"
},
"name": 0
},
"type": "combine"
},
@ -1137,13 +1077,10 @@
"y": 186.780701
},
"parameters": {
"amount": 0.5,
"param0": 11,
"param1": 2,
"param2": 0,
"param3": 0,
"param4": 0,
"size": 4
"param4": 0
},
"type": "normal_map"
},
@ -1171,7 +1108,6 @@
"y": 149.637848
},
"parameters": {
"Randomness": 0.5,
"angle": -1,
"layers": 10,
"length": 0.05,
@ -1784,14 +1720,7 @@
"y": 39.197388
},
"parameters": {
"color": {
"a": 1,
"b": 1,
"g": 1,
"r": 1,
"type": "Color"
},
"name": 0
},
"type": "combine"
},
@ -1813,13 +1742,10 @@
"y": 186.780701
},
"parameters": {
"amount": 0.5,
"param0": 11,
"param1": 2,
"param2": 0,
"param3": 0,
"param4": 0,
"size": 4
"param4": 0
},
"type": "normal_map"
},
@ -1847,7 +1773,6 @@
"y": 149.637848
},
"parameters": {
"Randomness": 0.5,
"angle": -1,
"layers": 10,
"length": 0.05,
@ -2129,7 +2054,6 @@
},
"parameters": {
"param0": 1,
"param1": 10,
"param2": 1
},
"type": "mwf_output"

View File

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

View File

@ -6,30 +6,6 @@
"to": "sdf3d_scale_2",
"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_port": 0,
@ -401,6 +377,30 @@
"from_port": 2,
"to": "mul_detect_2_2",
"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",
@ -411,6 +411,9 @@
},
"nodes": [
{
"export_paths": {
},
"name": "Material",
"node_position": {
"x": 1596.135986,
@ -424,14 +427,14 @@
"r": 1,
"type": "Color"
},
"ao_light_affect": 1,
"ao": 1,
"depth_scale": 0.3,
"emission_energy": 1,
"metallic": 1,
"normal_scale": 1,
"normal": 1,
"roughness": 1,
"size": 11,
"subsurf_scatter_strength": 0
"sss": 0
},
"type": "material"
},
@ -562,8 +565,8 @@
"label": "Donut",
"name": "graph",
"node_position": {
"x": -664.759155,
"y": -18.094296
"x": -660.759155,
"y": 14.905704
},
"nodes": [
{
@ -573,15 +576,7 @@
"y": 249.420105
},
"parameters": {
"bevel": 0,
"c": 0.31,
"cx": 0,
"cy": 0,
"h": 0.08,
"k": 0.15,
"op": 0,
"r": 0.15,
"w": 0.28
"c": 0.31
},
"shader_model": {
"code": "",
@ -624,13 +619,7 @@
"y": 320.541656
},
"parameters": {
"bevel": 0,
"cx": 0,
"cy": 0,
"h": 0.08,
"op": 2,
"r": 0.3,
"w": 0.28
"op": 2
},
"shader_model": {
"code": "",
@ -699,18 +688,13 @@
"name": "sdf3d_repeat",
"node_position": {
"x": -768.854126,
"y": 276.291656
"y": 281.291656
},
"parameters": {
"a": 0,
"r": 0.51,
"rx": 16,
"ry": 16,
"rz": 16,
"s": 0.3,
"x": 0.35,
"y": 0,
"z": 0
"rz": 16
},
"shader_model": {
"code": "",
@ -727,7 +711,7 @@
"name": "Repeat",
"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"
}
],
@ -784,10 +768,7 @@
},
"parameters": {
"l": 0.02,
"r": 0.01,
"sx": 0.25,
"sy": 0.25,
"sz": 0.5
"r": 0.01
},
"type": "sdf3d_capsule"
},
@ -799,10 +780,7 @@
},
"parameters": {
"R": 0.3,
"r": 0.14,
"sx": 0.1,
"sy": 0.1,
"sz": 0.02
"r": 0.14
},
"type": "sdf3d_torus"
},
@ -814,10 +792,7 @@
},
"parameters": {
"R": 0.3,
"r": 0.15,
"sx": 0.1,
"sy": 0.1,
"sz": 0.02
"r": 0.15
},
"type": "sdf3d_torus"
},
@ -828,13 +803,7 @@
"y": -3.083344
},
"parameters": {
"bevel": 0,
"cx": 0,
"cy": 0,
"h": 0.08,
"op": 0,
"r": 0.3,
"w": 0.28
"op": 0
},
"shader_model": {
"code": "",
@ -893,15 +862,7 @@
"y": -156.583344
},
"parameters": {
"bevel": 0,
"c": 0.08,
"cx": 0,
"cy": 0,
"h": 0.08,
"k": 0.15,
"op": 0,
"r": 0.15,
"w": 0.28
"c": 0.08
},
"shader_model": {
"code": "",
@ -957,15 +918,7 @@
"y": 130.166656
},
"parameters": {
"bevel": 0,
"c": 0.87,
"cx": 0,
"cy": 0,
"h": 0.08,
"k": 0.15,
"op": 0,
"r": 0.15,
"w": 0.28
"c": 0.87
},
"shader_model": {
"code": "",
@ -1008,13 +961,7 @@
"y": 127.920105
},
"parameters": {
"bevel": 0,
"cx": 0,
"cy": 0,
"h": 0.08,
"op": 0,
"r": 0.3,
"w": 0.28
"op": 0
},
"shader_model": {
"code": "",
@ -1117,76 +1064,6 @@
},
"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",
"node_position": {
@ -1194,11 +1071,7 @@
"y": 66.030228
},
"parameters": {
"a": 0,
"s": 0.37,
"x": 0.35,
"y": 0,
"z": 0
"s": 0.37
},
"shader_model": {
"code": "vec2 $(name_uv)_in = $in(($uv)/$s);",
@ -1234,86 +1107,16 @@
},
"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",
"node_position": {
"x": -479.952209,
"y": 213.034912
"x": -478.952209,
"y": 207.034912
},
"parameters": {
"x": 0.14,
"x": 0.18,
"y": 0.11,
"z": 0.2
"z": 0.14
},
"shader_model": {
"code": "",
@ -1372,17 +1175,11 @@
{
"name": "sdf3d_boolean",
"node_position": {
"x": -252.248795,
"x": -265.248779,
"y": 76.092621
},
"parameters": {
"bevel": 0,
"cx": 0,
"cy": 0,
"h": 0.08,
"op": 0,
"r": 0.3,
"w": 0.28
"op": 0
},
"shader_model": {
"code": "",
@ -1443,7 +1240,7 @@
"parameters": {
"x": 0,
"y": 0,
"z": 0.1
"z": 0.07
},
"shader_model": {
"code": "",
@ -1513,7 +1310,7 @@
"y": -50.802036
},
"parameters": {
"size": 4
},
"size": {
"x": 757.167969,
@ -1907,7 +1704,6 @@
},
"parameters": {
"param0": 10,
"param1": 50,
"param2": 4.9
},
"type": "remote",
@ -2069,7 +1865,6 @@
],
"parameters": {
"param0": 10,
"param1": 50,
"param2": 4.9
},
"type": "graph"
@ -2179,7 +1974,6 @@
},
"parameters": {
"param0": 0,
"param1": 10,
"param2": 4.9
},
"type": "remote",
@ -2216,8 +2010,7 @@
},
"parameters": {
"brightness": 0,
"contrast": 1,
"steps": 6
"contrast": 1
},
"type": "brightness_contrast"
},
@ -2228,20 +2021,16 @@
"y": 544.75
},
"parameters": {
"amount": 0.5,
"param0": 10,
"param1": 1.02,
"param2": 0,
"param3": 0,
"param4": 1,
"size": 4
"param4": 1
},
"type": "normal_map"
}
],
"parameters": {
"param0": 0,
"param1": 10,
"param2": 4.9
},
"type": "graph"
@ -2428,7 +2217,7 @@
"y": -50.148132
},
"parameters": {
"size": 4
},
"size": {
"x": 255.271576,
@ -2452,7 +2241,7 @@
"y": -373.398132
},
"parameters": {
"size": 4
},
"size": {
"x": 464,
@ -2476,7 +2265,7 @@
"y": -289.750183
},
"parameters": {
"size": 4
},
"size": {
"x": 743.688171,
@ -2521,6 +2310,32 @@
"v": 0.08
},
"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": {

View File

@ -165,6 +165,9 @@
},
"nodes": [
{
"export_paths": {
},
"name": "Material",
"node_position": {
"x": 356,
@ -178,14 +181,14 @@
"r": 1,
"type": "Color"
},
"ao_light_affect": 1,
"ao": 1,
"depth_scale": 1,
"emission_energy": 1,
"metallic": 1,
"normal_scale": 1,
"normal": 1,
"roughness": 1,
"size": 11,
"subsurf_scatter_strength": 0
"sss": 0
},
"type": "material"
},
@ -492,18 +495,6 @@
},
{
"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_port": 0,
@ -533,6 +524,18 @@
"from_port": 0,
"to": "sdf3d_scale",
"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",
@ -1319,68 +1322,6 @@
},
"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",
"node_position": {
@ -1438,6 +1379,19 @@
"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": {

View File

@ -103,7 +103,7 @@ func update_tab_title() -> void:
if get_parent().has_method("set_tab_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:
need_save = ns
update_tab_title()

View File

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

View File

@ -15,6 +15,7 @@ onready var projects = $VBoxContainer/Layout/SplitRight/ProjectsPane/Projects
onready var layout = $VBoxContainer/Layout
var library
var preview_2d
var histogram
var preview_3d
var hierarchy
@ -131,6 +132,7 @@ func _ready() -> void:
layout.load_panes(config_cache)
library = layout.get_pane("Library")
preview_2d = layout.get_pane("Preview2D")
histogram = layout.get_pane("Histogram")
preview_3d = layout.get_pane("Preview3D")
preview_3d.connect("need_update", self, "update_preview_3d")
hierarchy = layout.get_pane("Hierarchy")
@ -584,17 +586,13 @@ func update_preview_2d(node = null) -> void:
node = n
break
if node != null:
var result = node.generator.render(0, 1024, true)
while result is GDScriptFunctionState:
result = yield(result, "completed")
var tex = ImageTexture.new()
result.copy_to_texture(tex)
result.release()
preview_2d.set_preview_texture(tex)
preview_2d_background.set_preview_texture(tex)
preview_2d.set_generator(node.generator)
histogram.set_generator(node.generator)
preview_2d_background.set_generator(node.generator)
else:
preview_2d.set_preview_texture(null)
preview_2d_background.set_preview_texture(null)
preview_2d.set_generator(null)
histogram.set_generator(null)
preview_2d_background.set_generator(null)
func update_preview_3d(previews : Array) -> void:
var graph_edit : MMGraphEdit = get_current_graph_edit()
@ -610,7 +608,7 @@ var selected_node = null
func on_selected_node_change(node) -> void:
if node != selected_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)
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_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_ui.tscn" type="PackedScene" id=5]
[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/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/preview/preview_2d.gd" type="Script" id=11]
[sub_resource type="Shader" id=1]
code = "shader_type canvas_item;
uniform sampler2D tex;
uniform vec2 size;
void fragment() {
float ms = max(size.x, size.y);
vec2 uv = fract(0.5+1.2*(UV-vec2(0.5))*ms/size.yx);
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);
}"
resource_local_to_scene = true
[sub_resource type="ShaderMaterial" id=2]
resource_local_to_scene = true
shader = SubResource( 1 )
shader_param/size = Vector2( 947, 682 )
[sub_resource type="AtlasTexture" id=3]
flags = 4
@ -127,20 +114,11 @@ size_flags_horizontal = 3
size_flags_vertical = 3
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
material = SubResource( 2 )
anchor_right = 1.0
anchor_bottom = 1.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
}
margin_right = 0.0
margin_bottom = 0.0
[node name="Preview3D" parent="VBoxContainer/Layout/SplitRight/ProjectsPane" instance=ExtResource( 4 )]
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/Bottom" to="VBoxContainer/Layout" method="_on_tab_changed"]
[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="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"]

View File

@ -10,6 +10,7 @@ const PANES = [
{ 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="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" }
]

View File

@ -5,7 +5,8 @@ var controls = {}
var ignore_parameter_change = ""
var output_count = 0
var preview : TextureRect
var preview : ColorRect
#var preview : TextureRect
var preview_index : int = -1
var preview_position : int
var preview_size : int
@ -52,7 +53,7 @@ func on_parameter_changed(p, v) -> void:
o.value = gradient
else:
print("unsupported widget "+str(o))
update_shaders()
get_parent().set_need_save()
func initialize_properties() -> void:
var parameter_names = []
@ -81,33 +82,29 @@ func initialize_properties() -> void:
else:
print("unsupported widget "+str(o))
func update_shaders() -> void:
get_parent().send_changed_signal()
update_preview()
func _on_text_changed(new_text, variable) -> void:
ignore_parameter_change = variable
generator.set_parameter(variable, new_text)
ignore_parameter_change = ""
update_shaders()
get_parent().set_need_save()
func _on_value_changed(new_value, variable) -> void:
ignore_parameter_change = variable
generator.set_parameter(variable, new_value)
ignore_parameter_change = ""
update_shaders()
get_parent().set_need_save()
func _on_color_changed(new_color, variable) -> void:
ignore_parameter_change = variable
generator.set_parameter(variable, new_color)
ignore_parameter_change = ""
update_shaders()
get_parent().set_need_save()
func _on_gradient_changed(new_gradient, variable) -> void:
ignore_parameter_change = variable
generator.set_parameter(variable, MMType.serialize_value(new_gradient))
ignore_parameter_change = ""
update_shaders()
get_parent().set_need_save()
func create_parameter_control(p : Dictionary) -> Control:
var control = null
@ -150,7 +147,8 @@ func save_preview_widget() -> void:
func restore_preview_widget() -> void:
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_position = get_child_count()
if preview.visible:
@ -295,7 +293,7 @@ func edit_generator() -> void:
func update_generator(shader_model) -> void:
generator.set_shader_model(shader_model)
update_node()
update_shaders()
get_parent().set_need_save()
func load_generator() -> void:
var dialog = FileDialog.new()
@ -371,14 +369,9 @@ func update_preview(size : int = 0) -> void:
preview_timer.start(0.2)
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:
add_child(preview)
move_child(preview, preview_position)
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"
show_close = true
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}

View File

@ -5,12 +5,6 @@ var fixed_lines : int = 0
func _ready() -> void:
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:
if generator == null or !generator.parameters.has("outputs") or !generator.parameters.has("choices"):
return
@ -48,7 +42,6 @@ func update_node() -> void:
sizer.add_child(control)
control.connect("value_changed", self, "_on_value_changed", [ l.name ])
controls[l.name] = control
sizer.add_child(preload("res://material_maker/widgets/preview_button.tscn").instance())
add_child(sizer)
else:
# Keep lines with controls
@ -64,22 +57,12 @@ func update_node() -> void:
var sizer = HBoxContainer.new()
var input_label = Label.new()
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)
rect_size = Vector2(0, 0)
for i in range(get_child_count()):
var sizer = get_child(i)
var has_input = true
var has_output = false
if i < 5:
has_output = i < output_count
sizer.get_child(sizer.get_child_count()-1).visible = has_output
var has_output = i < output_count
if i >= input_count:
sizer.get_child(0).text = ""
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/widgets/preview_button.tscn" type="PackedScene" id=2]
[sub_resource type="Theme" id=1]
[node name="Switch" type="GraphNode"]
@ -36,6 +34,9 @@ slot/2/right_enabled = false
slot/2/right_type = 0
slot/2/right_color = Color( 1, 1, 1, 1 )
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="HBox1" type="HBoxContainer" parent="."]
margin_left = 16.0
@ -69,9 +70,9 @@ margin_bottom = 16.0
[node name="HBox2" type="HBoxContainer" parent="."]
margin_left = 16.0
margin_top = 40.0
margin_top = 41.0
margin_right = 135.0
margin_bottom = 56.0
margin_bottom = 57.0
[node name="Label" type="Label" parent="HBox2"]
margin_top = 1.0
@ -99,9 +100,9 @@ margin_bottom = 16.0
[node name="HBox3" type="HBoxContainer" parent="."]
margin_left = 16.0
margin_top = 57.0
margin_top = 58.0
margin_right = 135.0
margin_bottom = 73.0
margin_bottom = 74.0
[node name="Label" type="Label" parent="HBox3"]
margin_top = 1.0

View File

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

View File

@ -1,24 +1,66 @@
extends ColorRect
var generator = null
export(String, MULTILINE) var shader : String = ""
func set_preview_texture(tex: Texture) -> void:
material.set_shader_param("tex", tex)
var generator : MMGenBase = null
var output : int = 0
func on_resized() -> void:
material.set_shader_param("size", rect_size)
setup_controls(generator)
func setup_controls(g : MMGenBase) -> void:
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()
for c in get_children():
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:
g = null
for c in get_children():
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:
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]
[sub_resource type="Shader" id=1]
code = "shader_type canvas_item;
uniform sampler2D tex;
uniform vec2 size;
void fragment() {
float ms = max(size.x, size.y);
vec2 uv = fract(0.5+1.2*(UV-vec2(0.5))*ms/size.yx);
float is = min(size.x, size.y)/1.2;
vec2 m2 = min(fract(uv), 1.0-fract(uv));
vec4 image = texture(tex, uv);
vec3 image_with_background = mix(vec3(mod(floor(uv.x*32.0)+floor(uv.y*32.0), 2.0)), image.xyz, image.a);
float lines_color = 0.5*(cos(5.0*TIME+100.0*(uv.x+uv.y))+1.0);
COLOR = vec4(mix(image_with_background, vec3(lines_color), step(is*min(m2.x, m2.y), 1.0)), 1.0);
}"
resource_local_to_scene = true
[sub_resource type="ShaderMaterial" id=2]
resource_local_to_scene = true
shader = SubResource( 1 )
shader_param/size = Vector2( 585, 492 )
[node name="Preview2D" type="ColorRect"]
[node name="Preview2D" type="ColorRect" groups=[
"preview",
]]
material = SubResource( 2 )
anchor_right = 1.0
anchor_bottom = 1.0
@ -39,4 +26,16 @@ script = ExtResource( 1 )
__meta__ = {
"_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"]

View File

@ -1,9 +1,5 @@
extends ViewportContainer
const ENVIRONMENTS = [
"experiment", "lobby", "night", "park", "schelde"
]
const CAMERA_DISTANCE_MIN = 1.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_scene.tscn" type="PackedScene" id=2]
[sub_resource type="World" id=1]
[node name="Preview3D" type="ViewportContainer"]
[node name="Preview3D" type="ViewportContainer" groups=[
"preview",
]]
visible = false
anchor_right = 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 start_position : float
var last_position : float
var start_value : float
var modifiers : int
var from_lower_bound : bool = false
var from_upper_bound : bool = false
@ -45,28 +47,60 @@ func do_update(update_text : bool = true) -> void:
else:
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:
if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
if event.is_pressed():
start_position = event.position.x
last_position = event.position.x
start_position = last_position
start_value = value
sliding = true
from_lower_bound = value <= min_value
from_upper_bound = value >= max_value
modifiers = get_modifiers(event)
else:
sliding = false
elif sliding and event is InputEventMouseMotion and event.button_mask == BUTTON_MASK_LEFT:
var delta : float = event.position.x-start_position
var v : float = start_value+sign(delta)*pow(abs(delta)*0.005, 2)*abs(max_value - min_value)
if step != 0:
v = min_value+floor((v - min_value)/step)*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)
var new_modifiers = get_modifiers(event)
if new_modifiers != modifiers:
start_position = last_position
start_value = value
modifiers = new_modifiers
else:
last_position = event.position.x
var delta : float = last_position-start_position
var current_step = step
if event.control:
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:
if new_text.is_valid_float():

View File

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

View File

@ -147,8 +147,11 @@ func get_gradient_color(x) -> Color:
func update_shader() -> void:
var shader
shader = "shader_type canvas_item;\n"
shader += value.get_shader("gradient")
shader += "void fragment() { COLOR = gradient(UV.x); }"
var params = value.get_shader_params("")
for sp in params.keys():
shader += "uniform float "+sp+" = "+str(params[sp])+";\n"
shader += value.get_shader("")
shader += "void fragment() { COLOR = _gradient_fct(UV.x); }"
$Gradient.material.shader.set_code(shader)
emit_signal("updated", value)

View File

@ -25,7 +25,7 @@ func update_from_graph_edit(graph_edit) -> void:
update_index += 1
for g in item_from_gen.keys():
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 = {}
set_column_expand(0, true)
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_metadata(0, generator)
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:
for i in range(min(preview, generator.get_output_defs().size())):
item.set_icon(i+1, default_texture)
@ -97,7 +97,11 @@ func on_view_updated(generator) -> void:
if item_from_gen.has(current_generator):
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 !pending_updates.has(generator):
pending_updates[generator] = [index]

View File

@ -1,10 +1,89 @@
extends Control
func update_histogram() -> void:
pass
var generator : MMGenBase = null
var output : int = 0
var updating : bool = false
var update_again : bool = false
func get_image_texture() -> ImageTexture:
return $ViewportImage/ColorRect.material.get_shader_param("tex")
func get_histogram_texture() -> ImageTexture:
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_param/tex = SubResource( 11 )
[node name="Histogram" type="Control"]
[node name="Histogram" type="Control" groups=[
"preview",
]]
margin_right = 64.0
margin_bottom = 64.0
script = ExtResource( 1 )
@ -110,7 +112,7 @@ transparent_bg = true
hdr = false
usage = 0
render_target_v_flip = true
render_target_update_mode = 3
render_target_update_mode = 1
[node name="ColorRect" type="ColorRect" parent="ViewportImage"]
material = SubResource( 3 )
@ -122,10 +124,10 @@ rect_min_size = Vector2( 256, 256 )
size = Vector2( 128, 128 )
own_world = true
transparent_bg = true
hdr = false
usage = 0
disable_3d = true
keep_3d_linear = true
render_target_v_flip = true
render_target_update_mode = 3
render_target_update_mode = 1
[node name="ColorRect" type="ColorRect" parent="ViewportHistogram1"]
material = SubResource( 6 )
@ -138,7 +140,6 @@ size = Vector2( 128, 2 )
transparent_bg = true
disable_3d = true
keep_3d_linear = true
usage = 0
render_target_v_flip = true
render_target_update_mode = 3
@ -155,3 +156,4 @@ anchor_bottom = 1.0
__meta__ = {
"_edit_use_anchors_": false
}
[connection signal="visibility_changed" from="." to="." method="_on_Histogram_visibility_changed"]