diff --git a/addons/material_maker/engine/gen_material.gd b/addons/material_maker/engine/gen_material.gd index 1a39d36..39e82f6 100644 --- a/addons/material_maker/engine/gen_material.gd +++ b/addons/material_maker/engine/gen_material.gd @@ -6,12 +6,12 @@ var material : SpatialMaterial var generated_textures = {} const TEXTURE_LIST = [ - { port=0, texture="albedo" }, - { port=1, texture="orm" }, - { port=2, texture="emission" }, - { port=3, texture="normal" }, - { port=4, texture="depth" }, - { port=5, texture="sss" } + { port=0, texture="albedo", sources=[0] }, + { port=1, texture="orm", sources=[1, 2, 5] }, + { port=2, texture="emission", sources=[3] }, + { port=3, texture="normal", sources=[4] }, + { port=4, texture="depth", sources=[6] }, + { port=5, texture="sss", sources=[7] } ] const INPUT_ALBEDO : int = 0 @@ -47,7 +47,7 @@ func get_type() -> String: func get_type_name() -> String: return "Material" -func get_output_defs__() -> Array: +func get_output_defs() -> Array: return [] func get_image_size() -> int: @@ -70,10 +70,9 @@ func set_parameter(p, v) -> void: update_preview() func source_changed(input_index : int) -> void: + print("source_changed "+str(input_index)) for t in TEXTURE_LIST: - if t.has("port") and t.port == input_index: - generated_textures[t.texture] = null - elif t.has("ports") and t.ports.has(input_index): + if t.has("sources") and t.sources.find(input_index) != -1: generated_textures[t.texture] = null update_preview() @@ -104,6 +103,7 @@ func render_textures() -> void: generated_textures[t.texture] = texture func update_materials(material_list) -> void: + render_textures() for m in material_list: update_material(m) @@ -124,7 +124,7 @@ func update_material(m, file_prefix = null) -> void: # Make the material double-sided for better visiblity in the preview m.params_cull_mode = SpatialMaterial.CULL_DISABLED # Albedo - m.albedo_color = parameters.albedo + m.albedo_color = parameters.albedo_color m.albedo_texture = get_generated_texture("albedo", file_prefix) # Ambient occlusion if get_source(INPUT_OCCLUSION) != null: @@ -143,7 +143,7 @@ func update_material(m, file_prefix = null) -> void: m.roughness_texture = null # Metallic m.metallic = parameters.metallic - if get_source(INPUT_ROUGHNESS) != null: + if get_source(INPUT_METALLIC) != null: m.metallic_texture = get_generated_texture("orm", file_prefix) m.metallic_texture_channel = SpatialMaterial.TEXTURE_CHANNEL_BLUE else: @@ -151,7 +151,7 @@ func update_material(m, file_prefix = null) -> void: # Emission if get_source(INPUT_EMISSION) != null: m.emission_enabled = true - m.emission_energy = parameters.emission + m.emission_energy = parameters.emission_energy m.emission_texture = get_generated_texture("emission", file_prefix) else: m.emission_enabled = false @@ -159,13 +159,14 @@ func update_material(m, file_prefix = null) -> void: if get_source(INPUT_NORMAL) != null: m.normal_enabled = true m.normal_texture = get_generated_texture("normal", file_prefix) + m.normal_scale = parameters.normal else: m.normal_enabled = false # Depth if get_source(INPUT_DEPTH) != null and parameters.depth > 0: m.depth_enabled = true m.depth_deep_parallax = true - m.depth_scale = parameters.depth * 0.2 + m.depth_scale = parameters.depth_scale * 0.2 m.depth_texture = get_generated_texture("depth", file_prefix) else: m.depth_enabled = false @@ -200,17 +201,55 @@ func get_export_profiles() -> Array: func get_export_extension(profile : String) -> String: return shader_model.exports[profile].export_extension +func subst_string(s : String, export_context : Dictionary) -> String: + for k in export_context.keys(): + s = s.replace("$("+k+")", export_context[k]) + for input_index in range(shader_model.inputs.size()): + var input = shader_model.inputs[input_index] + var is_input_connected = "true" if get_source(input_index) != null else "false" + s = s.replace("$(connected:"+input.name+")", is_input_connected) + return s + +func create_file_from_template(template : String, file_name : String, export_context : Dictionary) -> bool: + var in_file = File.new() + var out_file = File.new() + if in_file.open(mm_loader.STD_GENDEF_PATH+"/"+template, File.READ) != OK: + if in_file.open(OS.get_executable_path().get_base_dir()+"/generators/"+template, File.READ) != OK: + print("Cannot find template file "+template) + return false + if out_file.open(file_name, File.WRITE): + print("Cannot write file '"+file_name+"'") + return false + var skip_state : Array = [ false ] + while ! in_file.eof_reached(): + var l = in_file.get_line() + if l.left(4) == "$if ": + var condition = subst_string(l.right(4), export_context) + var expr = Expression.new() + var error = expr.parse(condition, []) + if error != OK: + print("Error in expression: "+expr.get_error_text()) + continue + skip_state.push_back(!expr.execute()) + elif l.left(3) == "$fi": + skip_state.pop_back() + elif l.left(5) == "$else": + skip_state.push_back(!skip_state.pop_back()) + elif ! skip_state.back(): + out_file.store_line(subst_string(l, export_context)) + return true + func export_material(prefix, profile) -> void: + var export_context : Dictionary = { + path_prefix=prefix, + file_prefix=prefix.get_file() + } for f in shader_model.exports[profile].files: match f.type: "texture": - var file_name = f.file_name.replace("$(file_prefix)", prefix) + var file_name = subst_string(f.file_name, export_context) if f.has("conditions"): - var condition = f.conditions - for input_index in range(shader_model.inputs.size()): - var input = shader_model.inputs[input_index] - var is_input_connected = "true" if get_source(input_index) != null else "false" - condition = condition.replace("$(connected:"+input.name+")", is_input_connected) + var condition = subst_string(f.conditions, export_context) var expr = Expression.new() var error = expr.parse(condition, []) if error != OK: @@ -223,6 +262,9 @@ func export_material(prefix, profile) -> void: result = yield(result, "completed") result.save_to_file(file_name) result.release() + "template": + var file_name = f.file_name.replace("$(path_prefix)", prefix) + create_file_from_template(f.template, file_name, export_context) func _serialize(data: Dictionary) -> Dictionary: return data diff --git a/addons/material_maker/nodes/godot.tres.tmpl b/addons/material_maker/nodes/godot.tres.tmpl new file mode 100644 index 0000000..7238237 --- /dev/null +++ b/addons/material_maker/nodes/godot.tres.tmpl @@ -0,0 +1,48 @@ +[gd_resource type="SpatialMaterial" load_steps=5 format=2] + +$if $(connected:albedo_tex) +[ext_resource path="$(file_prefix)_albedo.png" type="Texture" id=1] +$fi +$if $(connected:ao_tex) or $(connected:roughness_tex) or $(connected:metallic_tex) +[ext_resource path="$(file_prefix)_orm.png" type="Texture" id=2] +$fi +$if $(connected:normal_tex) +[ext_resource path="$(file_prefix)_normal.png" type="Texture" id=3] +$fi +$if $(connected:depth_tex) +[ext_resource path="$(file_prefix)_depth.png" type="Texture" id=4] +$fi + +[resource] +$if $(connected:albedo_tex) +albedo_texture = ExtResource( 1 ) +$fi +metallic = 1.0 +$if $(connected:metallic_tex) +metallic_texture = ExtResource( 2 ) +metallic_texture_channel = 2 +$fi +$if $(connected:ao_tex) or $(connected:roughness_tex) or $(connected:metallic_tex) +roughness_texture = ExtResource( 2 ) +roughness_texture_channel = 1 +$fi +$if $(connected:normal_tex) +normal_enabled = true +normal_scale = 1.0 +normal_texture = ExtResource( 3 ) +$fi +$if $(connected:ao_tex) +ao_enabled = true +ao_light_affect = 0.0 +ao_texture = ExtResource( 2 ) +ao_on_uv2 = false +ao_texture_channel = 0 +$fi +$if $(connected:depth_tex) +depth_enabled = true +depth_scale = 0.05 +depth_deep_parallax = false +depth_flip_tangent = false +depth_flip_binormal = false +depth_texture = ExtResource( 4 ) +$fi diff --git a/addons/material_maker/nodes/material.mmg b/addons/material_maker/nodes/material.mmg index 033ca52..b7203d8 100644 --- a/addons/material_maker/nodes/material.mmg +++ b/addons/material_maker/nodes/material.mmg @@ -34,13 +34,13 @@ "type": "rgb" }, { - "default": "1", + "default": "1.0", "label": "", "name": "metallic_tex", "type": "f" }, { - "default": "1", + "default": "1.0", "label": "", "name": "roughness_tex", "type": "f" @@ -96,7 +96,7 @@ }, { "desc":"3: normal map for Godot", - "rgb": "$normal_tex($uv)", + "rgb": "$normal_tex($uv)*vec3(-1.0, 1.0, 1.0)+vec3(1.0, 0.0, 0.0)", "type": "rgb" }, { @@ -108,6 +108,31 @@ "desc":"5: sub surface scattering", "f": "$sss_tex($uv)", "type": "f" + }, + { + "desc":"6: unity metallic/smoothness", + "rgba": "vec4(vec3($metallic_tex($uv)), 1.0-$roughness_tex($uv))", + "type": "rgba" + }, + { + "desc":"7: unity normal", + "rgb": "$normal_tex($uv)*vec3(1.0, 1.0, -1.0)+vec3(0.0, 0.0, 1.0)", + "type": "rgb" + }, + { + "desc":"8: unity height", + "f": "1.0-$depth_tex($uv)", + "type": "f" + }, + { + "desc":"9: unity occlusion", + "f": "$ao_tex($uv)", + "type": "f" + }, + { + "desc":"10: unreal normal", + "rgb": "$normal_tex($uv)*vec3(-1.0)+vec3(1.0)", + "type": "rgb" } ], "exports": { @@ -116,43 +141,87 @@ "files": [ { "type":"texture", - "file_name":"$(file_prefix)_albedo.png", + "file_name":"$(path_prefix)_albedo.png", "output":0, "conditions":"$(connected:albedo_tex)" }, { "type":"texture", - "file_name":"$(file_prefix)_orm.png", + "file_name":"$(path_prefix)_orm.png", "output":1, "conditions":"$(connected:ao_tex) or $(connected:roughness_tex) or $(connected:metallic_tex)" }, { "type":"texture", - "file_name":"$(file_prefix)_emission.png", + "file_name":"$(path_prefix)_emission.png", "output":2, "conditions":"$(connected:emission_tex)" }, { "type":"texture", - "file_name":"$(file_prefix)_normal.png", + "file_name":"$(path_prefix)_normal.png", "output":3, "conditions":"$(connected:normal_tex)" }, { "type":"texture", - "file_name":"$(file_prefix)_depth.png", + "file_name":"$(path_prefix)_depth.png", "output":4, "conditions":"$(connected:depth_tex)" }, { "type":"texture", - "file_name":"$(file_prefix)_sss.png", + "file_name":"$(path_prefix)_sss.png", "output":5, "conditions":"$(connected:sss_tex)" + }, + { + "type":"template", + "file_name":"$(path_prefix).tres", + "template":"godot.tres.tmpl" } ] }, "Unity": { + "export_extension":"mat", + "files": [ + { + "type":"texture", + "file_name":"$(path_prefix)_albedo.png", + "output":0, + "conditions":"$(connected:albedo_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_metal_smoothness.png", + "output":6, + "conditions":"$(connected:roughness_tex) or $(connected:metallic_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_normal.png", + "output":7, + "conditions":"$(connected:normal_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_height.png", + "output":8, + "conditions":"$(connected:depth_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_occlusion.png", + "output":9, + "conditions":"$(connected:ao_tex)" + }, + { + "type":"texture", + "file_name":"$(path_prefix)_emission.png", + "output":2, + "conditions":"$(connected:emission_tex)" + } + ] }, "Unreal": { } @@ -166,7 +235,7 @@ "r": 1 }, "label": "Albedo", - "name": "albeco_color", + "name": "albedo_color", "type": "color" }, { @@ -195,7 +264,7 @@ "label": "Emission", "max": 1, "min": 0, - "name": "emission", + "name": "emission_energy", "step": 0.01, "type": "float" },