More refactoring on rtexture generation

This commit is contained in:
Rodolphe Suescun 2019-08-17 17:35:48 +02:00
parent b614ab50ed
commit e9a21454c1
19 changed files with 533 additions and 262 deletions

View File

@ -9,7 +9,7 @@ class OutputPort:
func _init(g : MMGenBase, o : int):
generator = g
output_index = o
"""
func get_shader():
return generator.get_shader(output_index)
@ -18,19 +18,43 @@ class OutputPort:
func get_globals():
return generator.get_globals()
"""
func to_str():
return generator.name+"("+str(output_index)+")"
var position : Vector2 = Vector2(0, 0)
var parameters = {}
func _ready():
init_parameters()
func init_parameters():
for p in get_parameter_defs():
print(p)
if !parameters.has(p.name):
if p.has("default"):
parameters[p.name] = MMType.deserialize_value(p.default)
else:
print("No default value for parameter "+p.name)
func get_seed():
return 0
func get_type():
return "generic"
func get_type_name():
return "Unnamed"
func get_parameter_defs():
return []
func get_input_defs():
return []
func get_output_defs():
return []
func get_source(input_index : int):
return get_parent().get_port_source(name, input_index)
@ -39,7 +63,7 @@ func get_input_shader(input_index : int):
if source != null:
return source.get_shader()
func get_shader(output_index : int, context = MMGenContext.new()):
func get_shader(output_index : int, context):
return get_shader_code("UV", output_index, context);
# this will need an output index for switch
@ -48,14 +72,25 @@ func get_globals():
for i in range(10):
var source = get_source(i)
if source != null:
var source_list = source.get_globals()
var source_list = source.generator.get_globals()
for g in source_list:
if list.find(g) == -1:
list.append(g)
return list
func get_shader_code(uv, slot = 0, context = MMGenContext.new()):
var rv = _get_shader_code(uv, slot, context)
func render(output_index : int, renderer : MMGenRenderer, size : int):
var context : MMGenContext = MMGenContext.new(renderer)
var source = get_shader_code("UV", output_index, context)
if source == null:
return false
var shader : String = renderer.generate_shader(source)
var status = renderer.render_shader(shader, {}, 1024)
while status is GDScriptFunctionState:
status = yield(status, "completed")
return status
func get_shader_code(uv : String, output_index : int, context : MMGenContext):
var rv = _get_shader_code(uv, output_index, context)
if rv != null:
if !rv.has("f"):
if rv.has("rgb"):
@ -74,5 +109,5 @@ func get_shader_code(uv, slot = 0, context = MMGenContext.new()):
rv.globals = get_globals()
return rv
func _get_shader_code(uv : String, output_index : int, context = MMGenContext.new()):
func _get_shader_code(uv : String, output_index : int, context : MMGenContext):
return null

View File

@ -1,2 +1,22 @@
tool
extends MMGenBase
class_name MMGenBuffer
func _ready():
if !parameters.has("size"):
parameters.size = 4
func get_type():
return "buffer"
func get_type_name():
return "Buffer"
func get_parameter_defs():
return [ { name="size", type="size", first=4, last=11, default=4 } ]
func get_input_defs():
return [ ]
func get_output_defs():
return [ ]

View File

@ -1,8 +1,13 @@
tool
extends Object
class_name MMGenContext
var renderer : MMGenRenderer
var variants : Dictionary = {}
func _init(r : MMGenRenderer):
renderer = r
func has_variant(generator):
return variants.has(generator)

View File

@ -1,2 +1,3 @@
tool
extends MMGenBase
class_name MMGenConvolution

View File

@ -4,10 +4,15 @@ class_name MMGenGraph
var connections = []
func get_type():
return "graph"
func get_port_source(gen_name: String, input_index: int) -> OutputPort:
for c in connections:
if c.to == gen_name and c.to_port == input_index:
return OutputPort.new(get_node(c.from), c.from_port)
var src_gen = get_node(c.from)
if src_gen != null:
return OutputPort.new(get_node(c.from), c.from_port)
return null
func connect_children(from, from_port : int, to, to_port : int):

View File

@ -43,6 +43,7 @@ func generate_material(renderer : MMGenRenderer):
var status = renderer.render_shader(shader, {}, 512)
while status is GDScriptFunctionState:
status = yield(status, "completed")
print("Render status: "+str(status))
renderer.get_texture().get_data().save_png("res://test.png")
material.albedo_texture = load("res://test.png")
return material

View File

@ -2,21 +2,26 @@ tool
extends MMGenBase
class_name MMGenShader
var model_data = null
var shader_model : Dictionary = {}
var generated_variants = []
func set_model_data(data: Dictionary):
model_data = data
for p in model_data.parameters:
if !parameters.has(p.name) and p.has("default"):
parameters[p.name] = MMType.deserialize_value(p.default)
func get_type():
return "shader"
func initialize(data: Dictionary):
if data.has("name"):
name = data.name
if data.has("parameters"):
for p in data.parameters.keys():
parameters[p] = data.parameters[p]
func get_type_name():
if shader_model.has("name"):
return shader_model.name
return .get_type_name()
func get_parameter_defs():
if shader_model == null or !shader_model.has("parameters"):
return []
else:
return shader_model.parameters
func set_shader_model(data: Dictionary):
shader_model = data
init_parameters()
func find_keyword_call(string, keyword):
var search_string = "$%s(" % keyword
@ -49,7 +54,8 @@ func replace_input(string, context, input, type, src, default):
if src == null:
src_code = subst(default, "(%s)" % uv)
else:
src_code = src.get_shader_code(uv)
print(src.to_str())
src_code = src.generator.get_shader_code(uv, src.output_index, context)
src_code.string = src_code[type]
required_defs += src_code.defs
required_code += src_code.code
@ -84,8 +90,8 @@ func subst(string, context, uv = ""):
string = replace_variable(string, "seed", str(get_seed()))
if uv != "":
string = replace_variable(string, "uv", "("+uv+")")
if model_data.has("parameters") and typeof(model_data.parameters) == TYPE_ARRAY:
for p in model_data.parameters:
if shader_model.has("parameters") and typeof(shader_model.parameters) == TYPE_ARRAY:
for p in shader_model.parameters:
if !p.has("name") or !p.has("type"):
continue
var value = parameters[p.name]
@ -102,9 +108,9 @@ func subst(string, context, uv = ""):
value_string = p.name+"_gradient_fct"
if value_string != null:
string = replace_variable(string, p.name, value_string)
if model_data.has("inputs") and typeof(model_data.inputs) == TYPE_ARRAY:
for i in range(model_data.inputs.size()):
var input = model_data.inputs[i]
if shader_model.has("inputs") and typeof(shader_model.inputs) == TYPE_ARRAY:
for i in range(shader_model.inputs.size()):
var input = shader_model.inputs[i]
var source = get_source(i)
var result = replace_input(string, context, input.name, input.type, source, input.default)
string = result.string
@ -112,18 +118,16 @@ func subst(string, context, uv = ""):
required_code += result.code
return { string=string, defs=required_defs, code=required_code }
func _get_shader_code(uv, slot = 0, context = MMGenContext.new()):
if context == null:
context = {}
func _get_shader_code(uv : String, output_index : int, context : MMGenContext):
var output_info = [ { field="rgba", type="vec4" }, { field="rgb", type="vec3" }, { field="f", type="float" } ]
var rv = { defs="", code="" }
var variant_string = uv+","+str(slot)
if model_data != null and model_data.has("outputs") and model_data.outputs.size() > slot:
var output = model_data.outputs[slot]
var variant_string = uv+","+str(output_index)
if shader_model != null and shader_model.has("outputs") and shader_model.outputs.size() > output_index:
var output = shader_model.outputs[output_index]
rv.defs = ""
if model_data.has("instance") && !context.has_variant(self):
rv.defs += subst(model_data.instance, context).string
for p in model_data.parameters:
if shader_model.has("instance") && !context.has_variant(self):
rv.defs += subst(shader_model.instance, context).string
for p in shader_model.parameters:
if p.type == "gradient":
var g = parameters[p.name]
if !(g is MMGradient):
@ -139,14 +143,14 @@ func _get_shader_code(uv, slot = 0, context = MMGenContext.new()):
var subst_output = subst(output[t.field], context, uv)
rv.defs += subst_output.defs
rv.code += subst_output.code
rv.code += "%s %s_%d_%d_%s = %s;\n" % [ t.type, name, slot, variant_index, t.field, subst_output.string ]
rv.code += "%s %s_%d_%d_%s = %s;\n" % [ t.type, name, output_index, variant_index, t.field, subst_output.string ]
for t in output_info:
if output.has(t.field):
rv[t.field] = "%s_%d_%d_%s" % [ name, slot, variant_index, t.field ]
rv[t.field] = "%s_%d_%d_%s" % [ name, output_index, variant_index, t.field ]
return rv
func get_globals():
var list = .get_globals()
if typeof(model_data) == TYPE_DICTIONARY and model_data.has("global") and list.find(model_data.global) == -1:
list.append(model_data.global)
if typeof(shader_model) == TYPE_DICTIONARY and shader_model.has("global") and list.find(shader_model.global) == -1:
list.append(shader_model.global)
return list

View File

@ -32,28 +32,29 @@ func create_gen(data) -> MMGenBase:
if data.has("connections") and data.has("nodes"):
generator = MMGenGraph.new()
add_to_gen_graph(generator, data.nodes, data.connections)
elif data.has("model_data"):
elif data.has("shader_model"):
generator = MMGenShader.new()
generator.set_model_data(data.model_data)
generator.set_shader_model(data.shader_model)
elif data.has("type"):
if data.type == "material":
generator = MMGenMaterial.new()
elif data.type == "buffer":
generator = MMGenBuffer.new()
else:
var file = File.new()
if file.open("res://addons/material_maker/library/"+data.type+".mml", File.READ) == OK:
var model_data = parse_json(file.get_as_text())
print("loaded description "+data.type+".mml")
generator = create_gen(model_data)
generator = create_gen(parse_json(file.get_as_text()))
file.close()
elif file.open("res://addons/material_maker/nodes/"+data.type+".mmn", File.READ) == OK:
generator = MMGenShader.new()
var model_data = parse_json(file.get_as_text())
print("loaded description "+data.type+".mmn")
generator.set_model_data(model_data)
generator.set_shader_model(parse_json(file.get_as_text()))
file.close()
else:
print("Cannot find description for "+data.type)
generator.name = data.type
if generator != null:
generator.name = data.type
else:
print(data)
if generator != null:
@ -63,5 +64,6 @@ func create_gen(data) -> MMGenBase:
generator.position.x = data.node_position.x
generator.position.y = data.node_position.y
if data.has("parameters"):
generator.initialize(data)
for p in data.parameters.keys():
generator.parameters[p] = data.parameters[p]
return generator

View File

@ -68,6 +68,7 @@ func setup_material(shader_material, textures, shader_code):
func render_shader(shader, textures, render_size):
if rendering:
print("Already rendering...")
return false
rendering = true
if debug_path != null and debug_path != "":

View File

@ -128,7 +128,7 @@ func get_free_name(type):
return node_name
i += 1
func create_nodes(data, position = null):
func create_nodes(data, position : Vector2 = Vector2(0, 0)):
if data == null:
return
if data.has("type"):
@ -136,6 +136,8 @@ func create_nodes(data, position = null):
if typeof(data.nodes) == TYPE_ARRAY and typeof(data.connections) == TYPE_ARRAY:
var loader = MMGenLoader.new()
var new_stuff = loader.add_to_gen_graph(generator, data.nodes, data.connections)
for g in new_stuff.generators:
g.position += position
update_graph(new_stuff.generators, new_stuff.connections)
func load_file(filename):

View File

@ -28,124 +28,156 @@
"tree_item":"Generators/Pattern",
"icon":"pattern",
"type":"pattern",
"mix":0,
"x_scale":4,
"x_wave":0,
"y_scale":4,
"y_wave":0
"parameters":{
"mix":0,
"x_scale":4,
"x_wave":0,
"y_scale":4,
"y_wave":0
}
},
{
"tree_item": "Generators/Pattern/Checkerboard",
"type": "pattern",
"icon": "checkerboard",
"mix": 4,
"x_scale": 4,
"x_wave": 2,
"y_scale": 4,
"y_wave": 2
"tree_item": "Generators/Pattern/Checkerboard",
"type": "pattern",
"icon": "checkerboard",
"parameters":{
"mix": 4,
"x_scale": 4,
"x_wave": 2,
"y_scale": 4,
"y_wave": 2
}
},
{
"tree_item":"Generators/Bricks",
"type":"bricks",
"icon":"bricks",
"bevel":0.1,
"columns":3,
"mortar":0.1,
"row_offset":0.5,
"rows":6
"parameters":{
"bevel":0.1,
"columns":3,
"mortar":0.1,
"row_offset":0.5,
"rows":6
}
},
{
"tree_item": "Generators/Bricks/Tiles",
"type": "bricks",
"icon": "tiles",
"bevel": 0.05,
"columns": 4,
"mortar": 0.05,
"row_offset": 0,
"rows": 4
"tree_item": "Generators/Bricks/Tiles",
"type": "bricks",
"icon": "tiles",
"parameters":{
"bevel": 0.05,
"columns": 4,
"mortar": 0.05,
"row_offset": 0,
"rows": 4
}
},
{
"tree_item": "Generators/Bricks/BasketWeave",
"type": "bricks",
"icon": "basketweave",
"parameters":{
"bevel": 0.05,
"columns": 2,
"mortar": 0.05,
"pattern": 3,
"repeat": 2,
"row_offset": 0,
"rows": 2
}
},
{
"tree_item": "Generators/Bricks/BasketWeave",
"type": "bricks",
"icon": "basketweave",
"bevel": 0.05,
"columns": 2,
"mortar": 0.05,
"pattern": 3,
"repeat": 2,
"row_offset": 0,
"rows": 2
"tree_item": "Generators/Bricks/HerringBone",
"type": "bricks",
"icon": "herringbone",
"parameters":{
"bevel": 0.05,
"columns": 2,
"mortar": 0.05,
"pattern": 2,
"repeat": 2,
"row_offset": 0,
"rows": 2
}
},
{
"tree_item": "Generators/Bricks/HerringBone",
"type": "bricks",
"icon": "herringbone",
"bevel": 0.05,
"columns": 2,
"mortar": 0.05,
"pattern": 2,
"repeat": 2,
"row_offset": 0,
"rows": 2
},
{
"tree_item": "Generators/Bricks/SpanishBond",
"type": "bricks",
"icon": "spanishbond",
"bevel": 0.05,
"columns": 2,
"mortar": 0.05,
"pattern": 4,
"repeat": 2,
"row_offset": 0,
"rows": 2
"tree_item": "Generators/Bricks/SpanishBond",
"type": "bricks",
"icon": "spanishbond",
"parameters":{
"bevel": 0.05,
"columns": 2,
"mortar": 0.05,
"pattern": 4,
"repeat": 2,
"row_offset": 0,
"rows": 2
}
},
{
"tree_item":"Generators/Noise",
"type":"noise",
"icon":"noise",
"size":4,
"density":0.5
"parameters":{
"size":4,
"density":0.5
}
},
{
"tree_item":"Generators/Perlin Noise",
"type":"perlin",
"icon":"perlin",
"iterations":3,
"persistence":0.5,
"scale_x":4,
"scale_y":4
"parameters":{
"iterations":3,
"persistence":0.5,
"scale_x":4,
"scale_y":4
}
},
{
"tree_item":"Generators/Voronoi Noise",
"type":"voronoi",
"icon":"voronoi",
"intensity":1,
"scale_x":4,
"scale_y":4
"parameters":{
"intensity":1,
"scale_x":4,
"scale_y":4
}
},
{
"tree_item":"Filters/Buffer",
"type":"buffer"
},
{
"tree_item":"Filters/AdjustHSV",
"type":"adjust_hsv",
"hue":0,
"saturation":1,
"value":1
"parameters":{
"hue":0,
"saturation":1,
"value":1
}
},
{
"tree_item":"Filters/Colorize",
"type":"colorize",
"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":1,"g":1,"pos":1,"r":1}]
"parameters":{
"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":1,"g":1,"pos":1,"r":1}]
}
},
{
"tree_item":"Filters/Blend",
"type":"blend",
"amount":0.5,
"blend_type":0
"parameters":{
"amount":0.5,
"blend_type":0
}
},
{
"tree_item":"Filters/Blur",
"type":"blur",
"sigma":1.0
"parameters":{
"sigma":1.0
}
},
{
"tree_item":"Filters/Combine",
@ -158,45 +190,55 @@
{
"tree_item":"Filters/Emboss",
"type":"emboss",
"direction":0
"parameters":{
"direction":0
}
},
{
"tree_item":"Filters/Normal map",
"type":"normal_map",
"amount":0.5
"parameters":{
"amount":0.5
}
},
{
"tree_item":"Filters/Transform",
"type":"transform",
"rotate":0,
"scale_x":1,
"scale_y":1,
"translate_x":0,
"translate_y":0
"parameters":{
"rotate":0,
"scale_x":1,
"scale_y":1,
"translate_x":0,
"translate_y":0
}
},
{
"tree_item":"Filters/Warp",
"type":"warp",
"amount":0.5
"parameters":{
"amount":0.5
}
},
{
"tree_item": "Filters/Colorize/Invert",
"type": "colorize",
"icon": "invert",
"gradient": [
{
"b": 1,
"g": 1,
"pos": 0,
"r": 1
},
{
"b": 0,
"g": 0,
"pos": 1,
"r": 0
}
]
"tree_item": "Filters/Colorize/Invert",
"type": "colorize",
"icon": "invert",
"parameters":{
"gradient": [
{
"b": 1,
"g": 1,
"pos": 0,
"r": 1
},
{
"b": 0,
"g": 0,
"pos": 1,
"r": 0
}
]
}
},
{
"tree_item":"Miscellaneous/Comment",

View File

@ -311,12 +311,10 @@ func update_preview_2d(node = null):
node = n
break
if node != null:
var source = node.generator.get_shader(0)
if source != null:
var shader : String = renderer.generate_shader(source)
var status = renderer.render_shader(shader, {}, 1024)
while status is GDScriptFunctionState:
status = yield(status, "completed")
var status = node.generator.render(0, renderer, 1024)
while status is GDScriptFunctionState:
status = yield(status, "completed")
if status:
var image = renderer.get_texture().get_data()
var tex = ImageTexture.new()
tex.create_from_image(image)

View File

@ -15,4 +15,6 @@ func create_node(type):
var node_type = load("res://addons/material_maker/nodes/"+type+".tscn")
if node_type != null:
node = node_type.instance()
else:
node = preload("res://addons/material_maker/nodes/generic.tscn").instance()
return node

View File

@ -1,7 +1,7 @@
{
"name":"Bricks",
"parameters":[
{ "name":"pattern", "label":"", "type":"enum", "values":[
{ "name":"pattern", "label":"", "type":"enum", "default":0, "values":[
{ "name":"Running bond", "value":"rb" },
{ "name":"Running bond (2)", "value":"rb2" },
{ "name":"HerringBone", "value":"hb" },

View File

@ -6,16 +6,16 @@ var controls = []
var uses_seed : bool = false
var parameters = {}
var model_data = {}
# Called when the node enters the scene tree for the first time.
func _ready():
pass # Replace with function body.
func set_generator(g):
generator = g
update_node(g.model_data)
if g.get("shader_model") != null:
update_node(g.shader_model)
else:
update_node({})
func initialize_properties():
for o in controls:
@ -70,13 +70,9 @@ func _on_gradient_changed(new_gradient, variable):
update_shaders()
func update_node(data):
print("node_generic.update_node")
if typeof(data) != TYPE_DICTIONARY:
return
if !data.has("name"):
return
# Clean node
parameters = {}
var custom_node_buttons = null
for c in get_children():
if c.name != "CustomNodeButtons":
@ -85,71 +81,69 @@ func update_node(data):
else:
custom_node_buttons = c
# Rebuild node
title = data.name
model_data = data
title = generator.get_type_name()
uses_seed = false
if model_data.has("instance") and model_data.instance.find("$(seed)"):
if data.has("instance") and data.instance.find("$(seed)"):
uses_seed = true
if model_data.has("parameters") and typeof(model_data.parameters) == TYPE_ARRAY:
controls = []
var sizer = null
for p in model_data.parameters:
if !p.has("name") or !p.has("type"):
continue
var control = null
if p.type == "float":
if p.has("widget") and p.widget == "spinbox":
control = SpinBox.new()
else:
control = HSlider.new()
control.min_value = p.min
control.max_value = p.max
control.step = 0 if !p.has("step") else p.step
if p.has("default"):
control.value = p.default
control.rect_min_size.x = 80
parameters[p.name] = 0.5*(p.min+p.max)
elif p.type == "size":
control = OptionButton.new()
for i in range(p.first, p.last+1):
var s = pow(2, i)
control.add_item("%dx%d" % [ s, s ])
control.selected = 0 if !p.has("default") else p.default-p.first
elif p.type == "enum":
control = OptionButton.new()
for i in range(p.values.size()):
var value = p.values[i]
control.add_item(value.name)
control.selected = 0 if !p.has("default") else p.default
elif p.type == "boolean":
control = CheckBox.new()
elif p.type == "color":
control = ColorPickerButton.new()
elif p.type == "gradient":
control = preload("res://addons/material_maker/widgets/gradient_editor.tscn").instance()
if control != null:
var label = p.name
control.name = label
controls.append(control)
if p.has("label"):
label = p.label
if sizer == null or label != "nonewline":
sizer = HBoxContainer.new()
sizer.size_flags_horizontal = SIZE_EXPAND | SIZE_FILL
add_child(sizer)
if label != "" && label != "nonewline":
var label_widget = Label.new()
label_widget.text = label
label_widget.size_flags_horizontal = SIZE_EXPAND | SIZE_FILL
sizer.add_child(label_widget)
control.size_flags_horizontal = SIZE_EXPAND | SIZE_FILL
sizer.add_child(control)
initialize_properties()
else:
model_data.parameters = []
if model_data.has("inputs") and typeof(model_data.inputs) == TYPE_ARRAY:
for i in range(model_data.inputs.size()):
var input = model_data.inputs[i]
# Parameters
print("Parameters")
controls = []
var sizer = null
for p in generator.get_parameter_defs():
if !p.has("name") or !p.has("type"):
continue
print(p.name)
var control = null
if p.type == "float":
if p.has("widget") and p.widget == "spinbox":
control = SpinBox.new()
else:
control = HSlider.new()
control.min_value = p.min
control.max_value = p.max
control.step = 0 if !p.has("step") else p.step
if p.has("default"):
control.value = p.default
control.rect_min_size.x = 80
elif p.type == "size":
control = OptionButton.new()
for i in range(p.first, p.last+1):
var s = pow(2, i)
control.add_item("%dx%d" % [ s, s ])
control.selected = 0 if !p.has("default") else p.default-p.first
elif p.type == "enum":
control = OptionButton.new()
for i in range(p.values.size()):
var value = p.values[i]
control.add_item(value.name)
control.selected = 0 if !p.has("default") else p.default
elif p.type == "boolean":
control = CheckBox.new()
elif p.type == "color":
control = ColorPickerButton.new()
elif p.type == "gradient":
control = preload("res://addons/material_maker/widgets/gradient_editor.tscn").instance()
if control != null:
var label = p.name
control.name = label
controls.append(control)
if p.has("label"):
label = p.label
if sizer == null or label != "nonewline":
sizer = HBoxContainer.new()
sizer.size_flags_horizontal = SIZE_EXPAND | SIZE_FILL
add_child(sizer)
if label != "" && label != "nonewline":
var label_widget = Label.new()
label_widget.text = label
label_widget.size_flags_horizontal = SIZE_EXPAND | SIZE_FILL
sizer.add_child(label_widget)
control.size_flags_horizontal = SIZE_EXPAND | SIZE_FILL
sizer.add_child(control)
initialize_properties()
if data.has("inputs") and typeof(data.inputs) == TYPE_ARRAY:
for i in range(data.inputs.size()):
var input = data.inputs[i]
var enable_left = false
var color_left = Color(0.5, 0.5, 0.5)
if typeof(input) == TYPE_DICTIONARY:
@ -162,11 +156,9 @@ func update_node(data):
else:
enable_left = true
set_slot(i, enable_left, 0, color_left, false, 0, Color())
else:
model_data.inputs = []
if model_data.has("outputs") and typeof(model_data.outputs) == TYPE_ARRAY:
for i in range(model_data.outputs.size()):
var output = model_data.outputs[i]
if data.has("outputs") and typeof(data.outputs) == TYPE_ARRAY:
for i in range(data.outputs.size()):
var output = data.outputs[i]
var enable_right = false
var color_right = Color(0.5, 0.5, 0.5)
if typeof(output) == TYPE_DICTIONARY:
@ -179,7 +171,5 @@ func update_node(data):
elif output.has("f"):
enable_right = true
set_slot(i, is_slot_enabled_left(i), get_slot_type_left(i), get_slot_color_left(i), enable_right, 0, color_right)
else:
model_data.outputs = []
if custom_node_buttons != null:
move_child(custom_node_buttons, get_child_count()-1)

View File

@ -51,4 +51,7 @@ func generate_material(ptex_filename: String) -> Material:
var generator = loader.load_gen(ptex_filename)
add_child(generator)
var material = generator.get_node("Material")
return material.generate_material(renderer)
var return_value = material.generate_material(renderer)
while return_value is GDScriptFunctionState:
return_value = yield(return_value, "completed")
return return_value

View File

@ -8,9 +8,6 @@ class CustomSorter:
var points = [ { v=0.0, c=Color(0.0, 0.0, 0.0, 0.0) }, { v=1.0, c=Color(1.0, 1.0, 1.0, 1.0) } ]
var sorted = true
func _ready():
pass
func to_string():
var rv = PoolStringArray()
for p in points:
@ -39,17 +36,20 @@ func sort():
func get_color(x):
sort()
if x < points[0].v:
return points[0].c
var s = points.size()-1
for i in range(s):
if x < points[i+1].v:
var p0 = points[i].v
var c0 = points[i].c
var p1 = points[i+1].v
var c1 = points[i+1].c
return c0 + (c1-c0) * (x-p0) / (p1-p0)
return points[s].c
if points.size() >0:
if x < points[0].v:
return points[0].c
var s = points.size()-1
for i in range(s):
if x < points[i+1].v:
var p0 = points[i].v
var c0 = points[i].c
var p1 = points[i+1].v
var c1 = points[i+1].c
return c0 + (c1-c0) * (x-p0) / (p1-p0)
return points[s].c
else:
return Color(0.0, 0.0, 0.0, 1.0)
# get_color_in_shader
func gcis(color):
@ -59,19 +59,22 @@ func get_shader(name):
sort()
var shader
shader = "vec4 "+name+"(float x) {\n"
shader += " if (x < %.9f) {\n" % points[0].v
shader += " return "+gcis(points[0].c)+";\n"
var s = points.size()-1
for i in range(s):
var p0 = points[i].v
var c0 = points[i].c
var p1mp0 = points[i+1].v-p0
var c1mc0 = points[i+1].c-c0
if p1mp0 > 0:
shader += " } else if (x < %.9f) {\n" % points[i+1].v
shader += " return %s+x*%s;\n" % [gcis(c0-c1mc0*(p0/p1mp0)), gcis(c1mc0/p1mp0)]
shader += " }\n"
shader += " return "+gcis(points[s].c)+";\n"
if points.size() > 0:
shader += " if (x < %.9f) {\n" % points[0].v
shader += " return "+gcis(points[0].c)+";\n"
var s = points.size()-1
for i in range(s):
var p0 = points[i].v
var c0 = points[i].c
var p1mp0 = points[i+1].v-p0
var c1mc0 = points[i+1].c-c0
if p1mp0 > 0:
shader += " } else if (x < %.9f) {\n" % points[i+1].v
shader += " return %s+x*%s;\n" % [gcis(c0-c1mc0*(p0/p1mp0)), gcis(c1mc0/p1mp0)]
shader += " }\n"
shader += " return "+gcis(points[s].c)+";\n"
else:
shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n"
shader += "}\n"
return shader
@ -89,7 +92,7 @@ func deserialize(v):
for i in v:
if !i.has("a"): i.a = 1.0
add_point(i.pos, Color(i.r, i.g, i.b, i.a))
elif typeof(v) == TYPE_DICTIONARY && v.has("type") && v.type == "Gradient":
elif typeof(v) == TYPE_DICTIONARY and v.has("type") && v.type == "Gradient":
for i in v.points:
if !i.has("a"): i.a = 1.0
add_point(i.pos, Color(i.r, i.g, i.b, i.a))

BIN
test.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

159
test.ptex
View File

@ -1 +1,158 @@
{"connections":[{"from":"bricks_0","from_port":0,"to":"custom_0","to_port":0},{"from":"custom_0","from_port":0,"to":"adjust_hsv_0","to_port":0},{"from":"adjust_hsv_0","from_port":0,"to":"Material","to_port":0}],"nodes":[{"name":"Material","node_position":{"x":143,"y":-210},"parameters":{"albedo_color":{"a":1,"b":1,"g":1,"r":1,"type":"Color"},"ao_light_affect":1,"depth_scale":1,"emission_energy":1,"metallic":1,"normal_scale":1,"resolution":1,"roughness":1},"type":"material"},{"model_data":{"global":"","inputs":[{"default":"0.0","label":"Input","name":"input","type":"f"}],"instance":"","name":"Colorize","outputs":[{"rgba":"$gradient($input($uv))"}],"parameters":[{"default":{"points":[{"a":1,"b":0,"g":0,"pos":0,"r":0},{"a":1,"b":1,"g":1,"pos":1,"r":1}],"type":"Gradient"},"label":"Gradient","name":"gradient","type":"gradient"}]},"name":"custom_0","node_position":{"x":-433,"y":-109.416656},"parameters":{"gradient":{"points":[{"a":1,"b":0,"g":0,"pos":0,"r":0},{"a":1,"b":0,"g":0,"pos":0.517045,"r":1},{"a":0,"b":1,"g":1,"pos":1,"r":1}],"type":"Gradient"}},"type":"custom"},{"name":"adjust_hsv_0","node_position":{"x":-135.541687,"y":-150.597229},"parameters":{"hue":0,"saturation":1,"value":1},"type":"adjust_hsv"},{"name":"bricks_0","node_position":{"x":-599,"y":-332},"parameters":{"bevel":0.209961,"columns":3,"mortar":0.116211,"pattern":0,"repeat":1,"row_offset":0.5,"rows":6},"type":"bricks"}]}
{
"connections": [
{
"from": "bricks_0",
"from_port": 0,
"to": "custom_0",
"to_port": 0
},
{
"from": "custom_0",
"from_port": 0,
"to": "adjust_hsv_0",
"to_port": 0
},
{
"from": "adjust_hsv_0",
"from_port": 0,
"to": "Material",
"to_port": 0
}
],
"nodes": [
{
"name": "Material",
"node_position": {
"x": 143,
"y": -210
},
"parameters": {
"albedo_color": {
"a": 1,
"b": 1,
"g": 1,
"r": 1,
"type": "Color"
},
"ao_light_affect": 1,
"depth_scale": 1,
"emission_energy": 1,
"metallic": 1,
"normal_scale": 1,
"resolution": 1,
"roughness": 1
},
"type": "material"
},
{
"shader_model": {
"global": "",
"inputs": [
{
"default": "0.0",
"label": "Input",
"name": "input",
"type": "f"
}
],
"instance": "",
"name": "Colorize",
"outputs": [
{
"rgba": "$gradient($input($uv))"
}
],
"parameters": [
{
"default": {
"points": [
{
"a": 1,
"b": 0,
"g": 0,
"pos": 0,
"r": 0
},
{
"a": 1,
"b": 1,
"g": 1,
"pos": 1,
"r": 1
}
],
"type": "Gradient"
},
"label": "Gradient",
"name": "gradient",
"type": "gradient"
}
]
},
"name": "custom_0",
"node_position": {
"x": -433,
"y": -109.416656
},
"parameters": {
"gradient": {
"points": [
{
"a": 1,
"b": 0,
"g": 0,
"pos": 0,
"r": 0
},
{
"a": 1,
"b": 0,
"g": 0,
"pos": 0.517045,
"r": 1
},
{
"a": 0,
"b": 1,
"g": 1,
"pos": 1,
"r": 1
}
],
"type": "Gradient"
}
},
"type": "custom"
},
{
"name": "adjust_hsv_0",
"node_position": {
"x": -135.541687,
"y": -150.597229
},
"parameters": {
"hue": 0,
"saturation": 1,
"value": 1
},
"type": "adjust_hsv"
},
{
"name": "bricks_0",
"node_position": {
"x": -599,
"y": -332
},
"parameters": {
"bevel": 0.209961,
"columns": 3,
"mortar": 0.116211,
"pattern": 0,
"repeat": 1,
"row_offset": 0.5,
"rows": 6
},
"type": "bricks"
}
]
}