mirror of
https://github.com/Relintai/material-maker.git
synced 2024-11-13 06:27:18 +01:00
Improved integration in Godot
Exporting a material will now create a SpatialMaterial. The Material graph node now generates different textures when used as a Godot addon (metallic, roughness and ambient occlusion are merged into a single texture). Rendering code (that was in graph_edit and node_base scenes) is now in a single "renderer scene" attached to the main window.
This commit is contained in:
parent
1c56fc60d8
commit
2621ff4b46
@ -1 +1 @@
|
|||||||
{"connections":[{"from":"perlin_0","from_port":0,"to":"warp_0","to_port":0},{"from":"perlin_1","from_port":0,"to":"warp_0","to_port":1},{"from":"perlin_2","from_port":0,"to":"blend_0","to_port":0},{"from":"blend_0","from_port":0,"to":"normal_map_0","to_port":0},{"from":"normal_map_0","from_port":0,"to":"Material","to_port":4},{"from":"blend_0","from_port":0,"to":"colorize_0","to_port":0},{"from":"colorize_0","from_port":0,"to":"Material","to_port":2},{"from":"blend_0","from_port":0,"to":"Material","to_port":1},{"from":"voronoi_0","from_port":0,"to":"colorize_1","to_port":0},{"from":"warp_0","from_port":0,"to":"warp_1","to_port":0},{"from":"colorize_1","from_port":0,"to":"warp_1","to_port":1},{"from":"warp_1","from_port":0,"to":"blend_0","to_port":1},{"from":"combine_0","from_port":0,"to":"export_0","to_port":0},{"from":"colorize_0","from_port":0,"to":"combine_0","to_port":1},{"from":"blend_0","from_port":0,"to":"colorize_2","to_port":0},{"from":"blend_0","from_port":0,"to":"combine_0","to_port":0},{"from":"colorize_2","from_port":0,"to":"Material","to_port":0}],"nodes":[{"amount":0.1,"name":"normal_map_0","node_position":{"x":319,"y":265.5},"type":"normal_map"},{"gradient":[{"b":0.53125,"g":0.53125,"pos":0,"r":0.53125},{"b":0.708333,"g":0.708333,"pos":1,"r":0.708333}],"name":"colorize_0","node_position":{"x":313,"y":176.5},"type":"colorize"},{"iterations":6,"name":"perlin_2","node_position":{"x":-312,"y":2.5},"persistence":1,"scale_x":32,"scale_y":4,"type":"perlin"},{"iterations":3,"name":"perlin_1","node_position":{"x":-400,"y":359.5},"persistence":0.5,"scale_x":4,"scale_y":4,"type":"perlin"},{"iterations":3,"name":"perlin_0","node_position":{"x":-393,"y":203.5},"persistence":0.5,"scale_x":32,"scale_y":4,"type":"perlin"},{"amount":0.3,"name":"warp_0","node_position":{"x":-180,"y":317.5},"type":"warp"},{"gradient":[{"b":0.432292,"g":0.432292,"pos":0,"r":0.432292},{"b":0,"g":0,"pos":0.345455,"r":0}],"name":"colorize_1","node_position":{"x":-194,"y":466.5},"type":"colorize"},{"amount":0.1,"name":"warp_1","node_position":{"x":-31,"y":336.5},"type":"warp"},{"intensity":1,"name":"voronoi_0","node_position":{"x":-381,"y":505.5},"scale_x":5,"scale_y":4,"type":"voronoi"},{"amount":1,"blend_type":2,"name":"blend_0","node_position":{"x":83,"y":245.5},"type":"blend"},{"name":"combine_0","node_position":{"x":515.35144,"y":-15.818176},"type":"combine"},{"name":"export_0","node_position":{"x":656.35144,"y":-20.818176},"suffix":"mr","type":"export"},{"name":"Material","node_position":{"x":544,"y":79},"type":"material"},{"gradient":[{"b":0.071126,"g":0.34877,"pos":0,"r":0.59375},{"b":0.013021,"g":0.144043,"pos":1,"r":0.3125}],"name":"colorize_2","node_position":{"x":305.35144,"y":76.181824},"type":"colorize"}]}
|
{"connections":[{"from":"perlin_0","from_port":0,"to":"warp_0","to_port":0},{"from":"perlin_1","from_port":0,"to":"warp_0","to_port":1},{"from":"perlin_2","from_port":0,"to":"blend_0","to_port":0},{"from":"blend_0","from_port":0,"to":"normal_map_0","to_port":0},{"from":"normal_map_0","from_port":0,"to":"Material","to_port":4},{"from":"blend_0","from_port":0,"to":"colorize_0","to_port":0},{"from":"colorize_0","from_port":0,"to":"Material","to_port":2},{"from":"blend_0","from_port":0,"to":"Material","to_port":1},{"from":"voronoi_0","from_port":0,"to":"colorize_1","to_port":0},{"from":"warp_0","from_port":0,"to":"warp_1","to_port":0},{"from":"colorize_1","from_port":0,"to":"warp_1","to_port":1},{"from":"warp_1","from_port":0,"to":"blend_0","to_port":1},{"from":"combine_0","from_port":0,"to":"export_0","to_port":0},{"from":"colorize_0","from_port":0,"to":"combine_0","to_port":1},{"from":"blend_0","from_port":0,"to":"colorize_2","to_port":0},{"from":"blend_0","from_port":0,"to":"combine_0","to_port":0},{"from":"colorize_2","from_port":0,"to":"Material","to_port":0}],"nodes":[{"iterations":6,"name":"perlin_2","node_position":{"x":-312,"y":2.5},"persistence":1,"scale_x":32,"scale_y":4,"type":"perlin"},{"iterations":3,"name":"perlin_1","node_position":{"x":-400,"y":359.5},"persistence":0.5,"scale_x":4,"scale_y":4,"type":"perlin"},{"iterations":3,"name":"perlin_0","node_position":{"x":-393,"y":203.5},"persistence":0.5,"scale_x":32,"scale_y":4,"type":"perlin"},{"amount":0.3,"name":"warp_0","node_position":{"x":-180,"y":317.5},"type":"warp"},{"gradient":[{"b":0.432292,"g":0.432292,"pos":0,"r":0.432292},{"b":0,"g":0,"pos":0.345455,"r":0}],"name":"colorize_1","node_position":{"x":-194,"y":466.5},"type":"colorize"},{"amount":0.1,"name":"warp_1","node_position":{"x":-31,"y":336.5},"type":"warp"},{"intensity":1,"name":"voronoi_0","node_position":{"x":-381,"y":505.5},"scale_x":5,"scale_y":4,"type":"voronoi"},{"amount":1,"blend_type":2,"name":"blend_0","node_position":{"x":83,"y":245.5},"type":"blend"},{"name":"combine_0","node_position":{"x":515.35144,"y":-15.818176},"type":"combine"},{"name":"export_0","node_position":{"x":656.35144,"y":-20.818176},"resolution":1,"suffix":"mr","type":"export"},{"albedo_color":{"a":1,"b":1,"g":1,"r":1,"type":"Color"},"ao_light_affect":1,"depth_scale":1,"emission_energy":1,"metallic":1,"name":"Material","node_position":{"x":544,"y":79},"normal_scale":1,"resolution":1,"roughness":1,"type":"material"},{"gradient":[{"b":0.071126,"g":0.34877,"pos":0,"r":0.59375},{"b":0.013021,"g":0.144043,"pos":1,"r":0.3125}],"name":"colorize_2","node_position":{"x":305.35144,"y":76.181824},"type":"colorize"},{"amount":0.1,"name":"normal_map_0","node_position":{"x":319,"y":265.5},"size":5,"type":"normal_map"},{"gradient":[{"b":0.53125,"g":0.53125,"pos":0,"r":0.53125},{"b":0.708333,"g":0.708333,"pos":1,"r":0.708333}],"name":"colorize_0","node_position":{"x":313,"y":176.5},"type":"colorize"}]}
|
@ -1,6 +1,9 @@
|
|||||||
tool
|
tool
|
||||||
extends GraphEdit
|
extends GraphEdit
|
||||||
|
|
||||||
|
var editor_interface = null
|
||||||
|
var renderer = null
|
||||||
|
|
||||||
var save_path = null
|
var save_path = null
|
||||||
var need_save = false
|
var need_save = false
|
||||||
|
|
||||||
@ -8,7 +11,6 @@ signal save_path_changed
|
|||||||
signal graph_changed
|
signal graph_changed
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
$SaveViewport/ColorRect.material = $SaveViewport/ColorRect.material.duplicate(true)
|
|
||||||
OS.low_processor_usage_mode = true
|
OS.low_processor_usage_mode = true
|
||||||
center_view()
|
center_view()
|
||||||
|
|
||||||
@ -284,59 +286,3 @@ func drop_data(position, data):
|
|||||||
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
|
||||||
create_nodes(data, offset_from_global_position(get_global_transform().xform(position)))
|
create_nodes(data, offset_from_global_position(get_global_transform().xform(position)))
|
||||||
return true
|
return true
|
||||||
|
|
||||||
# Save shader to image, create image texture
|
|
||||||
|
|
||||||
func setup_material(shader_material, textures, shader_code):
|
|
||||||
for k in textures.keys():
|
|
||||||
shader_material.set_shader_param(k+"_tex", textures[k])
|
|
||||||
shader_material.shader.code = shader_code
|
|
||||||
|
|
||||||
var render_queue = []
|
|
||||||
|
|
||||||
func render_shader_to_viewport(shader, textures, size, method, args):
|
|
||||||
render_queue.append( { shader=shader, textures=textures, size=size, method=method, args=args } )
|
|
||||||
if render_queue.size() == 1:
|
|
||||||
while !render_queue.empty():
|
|
||||||
var job = render_queue.front()
|
|
||||||
$SaveViewport.size = Vector2(job.size, job.size)
|
|
||||||
$SaveViewport/ColorRect.rect_position = Vector2(0, 0)
|
|
||||||
$SaveViewport/ColorRect.rect_size = Vector2(job.size, job.size)
|
|
||||||
var shader_material = $SaveViewport/ColorRect.material
|
|
||||||
shader_material.shader.code = job.shader
|
|
||||||
if job.textures != null:
|
|
||||||
for k in job.textures.keys():
|
|
||||||
shader_material.set_shader_param(k+"_tex", job.textures[k])
|
|
||||||
$SaveViewport.render_target_update_mode = Viewport.UPDATE_ONCE
|
|
||||||
$SaveViewport.update_worlds()
|
|
||||||
yield(get_tree(), "idle_frame")
|
|
||||||
yield(get_tree(), "idle_frame")
|
|
||||||
callv(job.method, job.args)
|
|
||||||
render_queue.pop_front()
|
|
||||||
|
|
||||||
func render_to_viewport(node, size, method, args):
|
|
||||||
render_shader_to_viewport(node.generate_shader(), node.get_textures(), size, method, args)
|
|
||||||
|
|
||||||
func export_texture(node, filename, size = 256):
|
|
||||||
if node == null:
|
|
||||||
return null
|
|
||||||
render_to_viewport(node, size, "do_export_texture", [ filename ])
|
|
||||||
|
|
||||||
func do_export_texture(filename):
|
|
||||||
var viewport_texture = $SaveViewport.get_texture()
|
|
||||||
var viewport_image = viewport_texture.get_data()
|
|
||||||
viewport_image.save_png(filename)
|
|
||||||
|
|
||||||
func precalculate_node(node, size, target_texture, object, method, args):
|
|
||||||
if node == null:
|
|
||||||
return null
|
|
||||||
render_to_viewport(node, size, "do_precalculate_texture", [ object, method, args ])
|
|
||||||
|
|
||||||
func precalculate_shader(shader, textures, size, target_texture, object, method, args):
|
|
||||||
render_shader_to_viewport(shader, textures, size, "do_precalculate_texture", [ target_texture, object, method, args ])
|
|
||||||
|
|
||||||
func do_precalculate_texture(target_texture, object, method, args):
|
|
||||||
var viewport_texture = $SaveViewport.get_texture()
|
|
||||||
target_texture.create_from_image(viewport_texture.get_data())
|
|
||||||
object.callv(method, args)
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
[gd_scene load_steps=6 format=2]
|
[gd_scene load_steps=4 format=2]
|
||||||
|
|
||||||
[ext_resource path="res://addons/material_maker/graph_edit.gd" type="Script" id=1]
|
[ext_resource path="res://addons/material_maker/graph_edit.gd" type="Script" id=1]
|
||||||
[ext_resource path="res://addons/material_maker/nodes/material.tscn" type="PackedScene" id=2]
|
[ext_resource path="res://addons/material_maker/nodes/material.tscn" type="PackedScene" id=2]
|
||||||
@ -6,20 +6,6 @@
|
|||||||
[sub_resource type="Theme" id=1]
|
[sub_resource type="Theme" id=1]
|
||||||
|
|
||||||
|
|
||||||
[sub_resource type="Shader" id=2]
|
|
||||||
|
|
||||||
code = "shader_type canvas_item;
|
|
||||||
|
|
||||||
void fragment() {
|
|
||||||
COLOR = vec4(1.0);
|
|
||||||
}
|
|
||||||
"
|
|
||||||
|
|
||||||
[sub_resource type="ShaderMaterial" id=3]
|
|
||||||
|
|
||||||
render_priority = 0
|
|
||||||
shader = SubResource( 2 )
|
|
||||||
|
|
||||||
[node name="GraphEdit" type="GraphEdit" index="0"]
|
[node name="GraphEdit" type="GraphEdit" index="0"]
|
||||||
|
|
||||||
self_modulate = Color( 1, 1, 1, 0 )
|
self_modulate = Color( 1, 1, 1, 0 )
|
||||||
@ -35,7 +21,7 @@ mouse_default_cursor_shape = 0
|
|||||||
size_flags_horizontal = 1
|
size_flags_horizontal = 1
|
||||||
size_flags_vertical = 1
|
size_flags_vertical = 1
|
||||||
right_disconnects = true
|
right_disconnects = true
|
||||||
scroll_offset = Vector2( 0, 0 )
|
scroll_offset = Vector2( -525, -250 )
|
||||||
snap_distance = 20
|
snap_distance = 20
|
||||||
use_snap = false
|
use_snap = false
|
||||||
zoom = 1.0
|
zoom = 1.0
|
||||||
@ -44,8 +30,12 @@ _sections_unfolded = [ "Material", "Mouse", "Visibility" ]
|
|||||||
|
|
||||||
[node name="Material" parent="." index="0" instance=ExtResource( 2 )]
|
[node name="Material" parent="." index="0" instance=ExtResource( 2 )]
|
||||||
|
|
||||||
|
margin_left = 525.0
|
||||||
|
margin_top = 250.0
|
||||||
|
margin_right = 755.0
|
||||||
|
margin_bottom = 470.0
|
||||||
theme = SubResource( 1 )
|
theme = SubResource( 1 )
|
||||||
_sections_unfolded = [ "Anchor", "Margin", "Mouse", "Theme", "slot", "slot/2", "slot/3", "slot/4", "slot/5" ]
|
_sections_unfolded = [ "Anchor", "Margin", "Mouse", "Theme", "slot", "slot/0", "slot/1", "slot/2", "slot/3", "slot/4", "slot/5" ]
|
||||||
|
|
||||||
[node name="Timer" type="Timer" parent="." index="1"]
|
[node name="Timer" type="Timer" parent="." index="1"]
|
||||||
|
|
||||||
@ -54,58 +44,6 @@ wait_time = 0.2
|
|||||||
one_shot = true
|
one_shot = true
|
||||||
autostart = false
|
autostart = false
|
||||||
|
|
||||||
[node name="SaveViewport" type="Viewport" parent="." index="2"]
|
|
||||||
|
|
||||||
arvr = false
|
|
||||||
size = Vector2( 0, 0 )
|
|
||||||
own_world = true
|
|
||||||
world = null
|
|
||||||
transparent_bg = false
|
|
||||||
msaa = 2
|
|
||||||
hdr = false
|
|
||||||
disable_3d = false
|
|
||||||
usage = 2
|
|
||||||
debug_draw = 0
|
|
||||||
render_target_v_flip = true
|
|
||||||
render_target_clear_mode = 0
|
|
||||||
render_target_update_mode = 1
|
|
||||||
audio_listener_enable_2d = false
|
|
||||||
audio_listener_enable_3d = false
|
|
||||||
physics_object_picking = false
|
|
||||||
gui_disable_input = true
|
|
||||||
gui_snap_controls_to_pixels = true
|
|
||||||
shadow_atlas_size = 0
|
|
||||||
shadow_atlas_quad_0 = 2
|
|
||||||
shadow_atlas_quad_1 = 2
|
|
||||||
shadow_atlas_quad_2 = 3
|
|
||||||
shadow_atlas_quad_3 = 4
|
|
||||||
_sections_unfolded = [ "GUI", "Render Target", "Rendering" ]
|
|
||||||
|
|
||||||
[node name="ColorRect" type="ColorRect" parent="SaveViewport" index="0"]
|
|
||||||
|
|
||||||
material = SubResource( 3 )
|
|
||||||
anchor_left = 0.0
|
|
||||||
anchor_top = 0.0
|
|
||||||
anchor_right = 0.0
|
|
||||||
anchor_bottom = 0.0
|
|
||||||
margin_right = 40.0
|
|
||||||
margin_bottom = 40.0
|
|
||||||
rect_pivot_offset = Vector2( 0, 0 )
|
|
||||||
rect_clip_content = false
|
|
||||||
mouse_filter = 0
|
|
||||||
mouse_default_cursor_shape = 0
|
|
||||||
size_flags_horizontal = 1
|
|
||||||
size_flags_vertical = 1
|
|
||||||
color = Color( 1, 1, 1, 1 )
|
|
||||||
_sections_unfolded = [ "Material", "Rect" ]
|
|
||||||
|
|
||||||
[node name="Timer" type="Timer" parent="SaveViewport" index="1"]
|
|
||||||
|
|
||||||
process_mode = 1
|
|
||||||
wait_time = 0.1
|
|
||||||
one_shot = true
|
|
||||||
autostart = false
|
|
||||||
|
|
||||||
[connection signal="connection_request" from="." to="." method="connect_node"]
|
[connection signal="connection_request" from="." to="." method="connect_node"]
|
||||||
|
|
||||||
[connection signal="disconnection_request" from="." to="." method="disconnect_node"]
|
[connection signal="disconnection_request" from="." to="." method="disconnect_node"]
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
tool
|
tool
|
||||||
extends Panel
|
extends Panel
|
||||||
|
|
||||||
|
var editor_interface = null
|
||||||
var current_tab = null
|
var current_tab = null
|
||||||
|
|
||||||
const MENU = [
|
const MENU = [
|
||||||
@ -26,6 +27,8 @@ const MENU = [
|
|||||||
{ menu="Help", command="about", description="About" }
|
{ menu="Help", command="about", description="About" }
|
||||||
]
|
]
|
||||||
|
|
||||||
|
signal quit
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
OS.set_window_title(ProjectSettings.get_setting("application/config/name")+" v"+ProjectSettings.get_setting("application/config/release"))
|
OS.set_window_title(ProjectSettings.get_setting("application/config/name")+" v"+ProjectSettings.get_setting("application/config/release"))
|
||||||
for m in $VBoxContainer/Menu.get_children():
|
for m in $VBoxContainer/Menu.get_children():
|
||||||
@ -76,6 +79,8 @@ func menu_about_to_show(name, menu):
|
|||||||
|
|
||||||
func new_pane():
|
func new_pane():
|
||||||
var graph_edit = preload("res://addons/material_maker/graph_edit.tscn").instance()
|
var graph_edit = preload("res://addons/material_maker/graph_edit.tscn").instance()
|
||||||
|
graph_edit.renderer = $Renderer
|
||||||
|
graph_edit.editor_interface = editor_interface
|
||||||
$VBoxContainer/HBoxContainer/Projects.add_child(graph_edit)
|
$VBoxContainer/HBoxContainer/Projects.add_child(graph_edit)
|
||||||
$VBoxContainer/HBoxContainer/Projects.current_tab = graph_edit.get_index()
|
$VBoxContainer/HBoxContainer/Projects.current_tab = graph_edit.get_index()
|
||||||
return graph_edit
|
return graph_edit
|
||||||
@ -140,8 +145,7 @@ func export_material_is_disabled():
|
|||||||
|
|
||||||
func quit():
|
func quit():
|
||||||
if Engine.editor_hint:
|
if Engine.editor_hint:
|
||||||
get_parent().hide()
|
emit_signal("quit")
|
||||||
get_parent().queue_free()
|
|
||||||
else:
|
else:
|
||||||
get_tree().quit()
|
get_tree().quit()
|
||||||
|
|
||||||
@ -245,7 +249,7 @@ func update_preview_2d(node = null):
|
|||||||
node = n
|
node = n
|
||||||
break
|
break
|
||||||
if node != null:
|
if node != null:
|
||||||
graph_edit.setup_material(preview.get_2d_material(), node.get_textures(), node.generate_shader())
|
graph_edit.renderer.setup_material(preview.get_2d_material(), node.get_textures(), node.generate_shader())
|
||||||
|
|
||||||
func _on_Projects_tab_changed(tab):
|
func _on_Projects_tab_changed(tab):
|
||||||
var new_tab = $VBoxContainer/HBoxContainer/Projects.get_current_tab_control()
|
var new_tab = $VBoxContainer/HBoxContainer/Projects.get_current_tab_control()
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
[gd_scene load_steps=5 format=2]
|
[gd_scene load_steps=6 format=2]
|
||||||
|
|
||||||
[ext_resource path="res://addons/material_maker/main_window.gd" type="Script" id=1]
|
[ext_resource path="res://addons/material_maker/main_window.gd" type="Script" id=1]
|
||||||
[ext_resource path="res://addons/material_maker/library.gd" type="Script" id=2]
|
[ext_resource path="res://addons/material_maker/library.gd" type="Script" id=2]
|
||||||
[ext_resource path="res://addons/material_maker/preview.tscn" type="PackedScene" id=3]
|
[ext_resource path="res://addons/material_maker/preview.tscn" type="PackedScene" id=3]
|
||||||
[ext_resource path="res://addons/material_maker/widgets/tabs.gd" type="Script" id=4]
|
[ext_resource path="res://addons/material_maker/widgets/tabs.gd" type="Script" id=4]
|
||||||
|
[ext_resource path="res://addons/material_maker/renderer.tscn" type="PackedScene" id=5]
|
||||||
|
|
||||||
[node name="MainWindow" type="Panel" index="0"]
|
[node name="MainWindow" type="Panel" index="0"]
|
||||||
|
|
||||||
@ -260,6 +261,8 @@ tab_align = 0
|
|||||||
tab_close_display_policy = 1
|
tab_close_display_policy = 1
|
||||||
scrolling_enabled = true
|
scrolling_enabled = true
|
||||||
|
|
||||||
|
[node name="Renderer" parent="." index="1" instance=ExtResource( 5 )]
|
||||||
|
|
||||||
[connection signal="no_more_tabs" from="VBoxContainer/HBoxContainer/Projects" to="." method="new_material"]
|
[connection signal="no_more_tabs" from="VBoxContainer/HBoxContainer/Projects" to="." method="new_material"]
|
||||||
|
|
||||||
[connection signal="resized" from="VBoxContainer/HBoxContainer/Projects" to="VBoxContainer/HBoxContainer/Projects" method="_on_Projects_resized"]
|
[connection signal="resized" from="VBoxContainer/HBoxContainer/Projects" to="VBoxContainer/HBoxContainer/Projects" method="_on_Projects_resized"]
|
||||||
|
@ -155,28 +155,12 @@ func deserialize_element(e):
|
|||||||
return Color(e.r, e.g, e.b, e.a)
|
return Color(e.r, e.g, e.b, e.a)
|
||||||
return e
|
return e
|
||||||
|
|
||||||
func do_generate_shader(src_code):
|
|
||||||
var code
|
|
||||||
code = "shader_type canvas_item;\n"
|
|
||||||
var file = File.new()
|
|
||||||
file.open("res://addons/material_maker/common.shader", File.READ)
|
|
||||||
code += file.get_as_text()
|
|
||||||
code += "\n"
|
|
||||||
var shader_code = src_code.defs
|
|
||||||
shader_code += "void fragment() {\n"
|
|
||||||
shader_code += src_code.code
|
|
||||||
shader_code += "COLOR = vec4("+src_code.rgb+", 1.0);\n"
|
|
||||||
shader_code += "}\n"
|
|
||||||
#print("GENERATED SHADER:\n"+shader_code)
|
|
||||||
code += shader_code
|
|
||||||
return code
|
|
||||||
|
|
||||||
func generate_shader(slot = 0):
|
func generate_shader(slot = 0):
|
||||||
# Reset all nodes
|
# Reset all nodes
|
||||||
for c in get_parent().get_children():
|
for c in get_parent().get_children():
|
||||||
if c is GraphNode:
|
if c is GraphNode:
|
||||||
c.reset()
|
c.reset()
|
||||||
return do_generate_shader(get_shader_code("UV", slot))
|
return get_parent().renderer.generate_shader(get_shader_code("UV", slot))
|
||||||
|
|
||||||
func serialize():
|
func serialize():
|
||||||
var type = get_script().resource_path
|
var type = get_script().resource_path
|
||||||
|
@ -6,9 +6,7 @@ var direction = 0
|
|||||||
var sigma = 1.0
|
var sigma = 1.0
|
||||||
|
|
||||||
var input_shader = ""
|
var input_shader = ""
|
||||||
var input_texture
|
var saved_texture
|
||||||
var mid_texture
|
|
||||||
var final_texture
|
|
||||||
|
|
||||||
const DIRECTION_H = 1
|
const DIRECTION_H = 1
|
||||||
const DIRECTION_V = 2
|
const DIRECTION_V = 2
|
||||||
@ -30,9 +28,7 @@ func _ready():
|
|||||||
$HBoxContainer2/direction.add_item(d.name)
|
$HBoxContainer2/direction.add_item(d.name)
|
||||||
$HBoxContainer2/direction.selected = direction
|
$HBoxContainer2/direction.selected = direction
|
||||||
initialize_properties([ $HBoxContainer1/size, $HBoxContainer2/direction, $HBoxContainer3/sigma ])
|
initialize_properties([ $HBoxContainer1/size, $HBoxContainer2/direction, $HBoxContainer3/sigma ])
|
||||||
input_texture = ImageTexture.new()
|
saved_texture = ImageTexture.new()
|
||||||
mid_texture = ImageTexture.new()
|
|
||||||
final_texture = ImageTexture.new()
|
|
||||||
|
|
||||||
func get_gaussian_blur_shader(horizontal):
|
func get_gaussian_blur_shader(horizontal):
|
||||||
var convolution = { x=0, y=0, kernel=[], epsilon=1.0/pow(2, 5+size) }
|
var convolution = { x=0, y=0, kernel=[], epsilon=1.0/pow(2, 5+size) }
|
||||||
@ -53,23 +49,23 @@ func get_gaussian_blur_shader(horizontal):
|
|||||||
|
|
||||||
func _rerender():
|
func _rerender():
|
||||||
if DIRECTIONS[direction].mask & DIRECTION_H != 0:
|
if DIRECTIONS[direction].mask & DIRECTION_H != 0:
|
||||||
get_parent().precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+size)), input_texture, self, "pass_1", [])
|
get_parent().renderer.precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+size)), saved_texture, self, "pass_1", [])
|
||||||
else:
|
else:
|
||||||
get_parent().precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+size)), mid_texture, self, "pass_2", [])
|
get_parent().renderer.precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+size)), saved_texture, self, "pass_2", [])
|
||||||
|
|
||||||
func pass_1():
|
func pass_1():
|
||||||
if DIRECTIONS[direction].mask & DIRECTION_V != 0:
|
if DIRECTIONS[direction].mask & DIRECTION_V != 0:
|
||||||
get_parent().precalculate_shader(get_gaussian_blur_shader(true), { input=input_texture}, int(pow(2, 5+size)), mid_texture, self, "pass_2", [])
|
get_parent().renderer.precalculate_shader(get_gaussian_blur_shader(true), { input=saved_texture }, int(pow(2, 5+size)), saved_texture, self, "pass_2", [])
|
||||||
else:
|
else:
|
||||||
get_parent().precalculate_shader(get_gaussian_blur_shader(true), { input=input_texture}, int(pow(2, 5+size)), final_texture, self, "rerender_targets", [])
|
get_parent().renderer.precalculate_shader(get_gaussian_blur_shader(true), { input=saved_texture }, int(pow(2, 5+size)), saved_texture, self, "rerender_targets", [])
|
||||||
|
|
||||||
|
|
||||||
func pass_2():
|
func pass_2():
|
||||||
get_parent().precalculate_shader(get_gaussian_blur_shader(false), { input=mid_texture}, int(pow(2, 5+size)), final_texture, self, "rerender_targets", [])
|
get_parent().renderer.precalculate_shader(get_gaussian_blur_shader(false), { input=saved_texture }, int(pow(2, 5+size)), saved_texture, self, "rerender_targets", [])
|
||||||
|
|
||||||
func get_textures():
|
func get_textures():
|
||||||
var list = {}
|
var list = {}
|
||||||
list[name] = final_texture
|
list[name] = saved_texture
|
||||||
return list
|
return list
|
||||||
|
|
||||||
func _get_shader_code(uv):
|
func _get_shader_code(uv):
|
||||||
@ -77,7 +73,7 @@ func _get_shader_code(uv):
|
|||||||
var src = get_source()
|
var src = get_source()
|
||||||
if src == null:
|
if src == null:
|
||||||
return rv
|
return rv
|
||||||
input_shader = do_generate_shader(src.get_shader_code("UV"))
|
input_shader = get_parent().renderer.generate_shader(src.get_shader_code("UV"))
|
||||||
_rerender()
|
_rerender()
|
||||||
if generated_variants.empty():
|
if generated_variants.empty():
|
||||||
rv.defs = "uniform sampler2D "+name+"_tex;\n"
|
rv.defs = "uniform sampler2D "+name+"_tex;\n"
|
||||||
|
@ -34,14 +34,14 @@ func _ready():
|
|||||||
initialize_properties([ $HBoxContainer1/size, $HBoxContainer2/direction ])
|
initialize_properties([ $HBoxContainer1/size, $HBoxContainer2/direction ])
|
||||||
|
|
||||||
func _rerender():
|
func _rerender():
|
||||||
get_parent().precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+size)), input_texture, self, "pass_1", [])
|
get_parent().renderer.precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+size)), input_texture, self, "pass_1", [])
|
||||||
|
|
||||||
func pass_1():
|
func pass_1():
|
||||||
var convolution = CONVOLUTION
|
var convolution = CONVOLUTION
|
||||||
convolution.epsilon=1.0/pow(2, 5+size)
|
convolution.epsilon=1.0/pow(2, 5+size)
|
||||||
for i in range(8):
|
for i in range(8):
|
||||||
convolution.kernel[INDICES[i]] = COEFS[(i+8-int(direction))%8]
|
convolution.kernel[INDICES[i]] = COEFS[(i+8-int(direction))%8]
|
||||||
get_parent().precalculate_shader(get_convolution_shader(convolution), {input=input_texture}, int(pow(2, 5+size)), final_texture, self, "rerender_targets", [])
|
get_parent().renderer.precalculate_shader(get_convolution_shader(convolution), {input=input_texture}, int(pow(2, 5+size)), final_texture, self, "rerender_targets", [])
|
||||||
|
|
||||||
func get_textures():
|
func get_textures():
|
||||||
var list = {}
|
var list = {}
|
||||||
@ -53,7 +53,7 @@ func _get_shader_code(uv):
|
|||||||
var src = get_source()
|
var src = get_source()
|
||||||
if src == null:
|
if src == null:
|
||||||
return rv
|
return rv
|
||||||
input_shader = do_generate_shader(src.get_shader_code("UV"))
|
input_shader = get_parent().generate_shader(src.get_shader_code("UV"))
|
||||||
_rerender()
|
_rerender()
|
||||||
if generated_variants.empty():
|
if generated_variants.empty():
|
||||||
rv.defs = "uniform sampler2D %s_tex;\n" % [ name ]
|
rv.defs = "uniform sampler2D %s_tex;\n" % [ name ]
|
||||||
|
@ -19,7 +19,7 @@ func export_textures(prefix, size = null):
|
|||||||
if suffix != "":
|
if suffix != "":
|
||||||
if size == null:
|
if size == null:
|
||||||
size = int(pow(2, 8+resolution))
|
size = int(pow(2, 8+resolution))
|
||||||
get_parent().export_texture(get_source(), "%s_%s.png" % [ prefix, suffix ], size)
|
get_parent().renderer.export_texture(get_source(), "%s_%s.png" % [ prefix, suffix ], size)
|
||||||
|
|
||||||
func serialize():
|
func serialize():
|
||||||
var data = .serialize()
|
var data = .serialize()
|
||||||
|
@ -10,6 +10,8 @@ var normal_scale
|
|||||||
var ao_light_affect
|
var ao_light_affect
|
||||||
var depth_scale
|
var depth_scale
|
||||||
|
|
||||||
|
var texture_list
|
||||||
|
|
||||||
var current_material_list = []
|
var current_material_list = []
|
||||||
var generated_textures = {}
|
var generated_textures = {}
|
||||||
|
|
||||||
@ -27,24 +29,30 @@ const ADDON_TEXTURE_LIST = [
|
|||||||
{ port=0, texture="albedo" },
|
{ port=0, texture="albedo" },
|
||||||
{ port=3, texture="emission" },
|
{ port=3, texture="emission" },
|
||||||
{ port=4, texture="normal_map" },
|
{ port=4, texture="normal_map" },
|
||||||
{ ports=[1, 2, 5], texture="mrao" },
|
{ ports=[1, 2, 5], default_values=["0.0", "1.0", "1.0"], texture="mrao" },
|
||||||
{ port=6, texture="depth_map" }
|
{ port=6, texture="depth_map" }
|
||||||
]
|
]
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
for t in TEXTURE_LIST:
|
texture_list = TEXTURE_LIST
|
||||||
|
if Engine.editor_hint:
|
||||||
|
texture_list = ADDON_TEXTURE_LIST
|
||||||
|
for t in texture_list:
|
||||||
generated_textures[t.texture] = { shader=null, source=null, texture=null }
|
generated_textures[t.texture] = { shader=null, source=null, texture=null }
|
||||||
initialize_properties([ $resolution, $Albedo/albedo_color, $Metallic/metallic, $Roughness/roughness, $Emission/emission_energy, $NormalMap/normal_scale, $AmbientOcclusion/ao_light_affect, $DepthMap/depth_scale ])
|
initialize_properties([ $resolution, $Albedo/albedo_color, $Metallic/metallic, $Roughness/roughness, $Emission/emission_energy, $NormalMap/normal_scale, $AmbientOcclusion/ao_light_affect, $DepthMap/depth_scale ])
|
||||||
|
|
||||||
func _rerender():
|
func _rerender():
|
||||||
|
var size = int(pow(2, 8+resolution))
|
||||||
var has_textures = false
|
var has_textures = false
|
||||||
for t in TEXTURE_LIST:
|
for t in texture_list:
|
||||||
var shader = generated_textures[t.texture].shader
|
var shader = generated_textures[t.texture].shader
|
||||||
if shader != null:
|
if shader != null:
|
||||||
var input_textures = null
|
var input_textures = {}
|
||||||
if generated_textures[t.texture].source != null:
|
for s in generated_textures[t.texture].sources:
|
||||||
input_textures = generated_textures[t.texture].source.get_textures()
|
var source_textures = s.get_textures()
|
||||||
get_parent().precalculate_shader(shader, input_textures, 1024, generated_textures[t.texture].texture, self, "do_update_materials", [ current_material_list ])
|
for st in source_textures.keys():
|
||||||
|
input_textures[st] = source_textures[st]
|
||||||
|
get_parent().renderer.precalculate_shader(shader, input_textures, size, generated_textures[t.texture].texture, self, "do_update_materials", [ current_material_list ])
|
||||||
has_textures = true
|
has_textures = true
|
||||||
if !has_textures:
|
if !has_textures:
|
||||||
do_update_materials(current_material_list)
|
do_update_materials(current_material_list)
|
||||||
@ -59,63 +67,123 @@ func _get_shader_code(uv):
|
|||||||
func update_materials(material_list):
|
func update_materials(material_list):
|
||||||
current_material_list = material_list
|
current_material_list = material_list
|
||||||
var has_textures = false
|
var has_textures = false
|
||||||
for t in TEXTURE_LIST:
|
for t in texture_list:
|
||||||
|
var shader = null
|
||||||
|
var sources = []
|
||||||
|
if t.has("port"):
|
||||||
var source = get_source(t.port)
|
var source = get_source(t.port)
|
||||||
if source == null:
|
if source != null:
|
||||||
generated_textures[t.texture].shader = null
|
shader = source.generate_shader()
|
||||||
generated_textures[t.texture].source = null
|
sources.append(source)
|
||||||
|
elif t.has("ports"):
|
||||||
|
var source = [ null, null, null ]
|
||||||
|
generated_textures[t.texture].mask = 0
|
||||||
|
for i in range(3):
|
||||||
|
source[i] = get_source(t.ports[i])
|
||||||
|
if source[i] != null:
|
||||||
|
sources.append(source[i])
|
||||||
|
generated_textures[t.texture].mask |= 1 << i
|
||||||
|
if !sources.empty():
|
||||||
|
for c in get_parent().get_children():
|
||||||
|
if c is GraphNode:
|
||||||
|
c.reset()
|
||||||
|
var source_code = [ null, null, null ]
|
||||||
|
for i in range(3):
|
||||||
|
if source[i] != null:
|
||||||
|
source_code[i] = source[i].get_shader_code("UV")
|
||||||
|
else:
|
||||||
|
source_code[i] = { defs="", code="", f=t.default_values[i] }
|
||||||
|
shader = get_parent().renderer.generate_combined_shader(source_code[0], source_code[1], source_code[2])
|
||||||
|
generated_textures[t.texture].shader = shader
|
||||||
|
generated_textures[t.texture].sources = sources
|
||||||
|
if shader == null:
|
||||||
if generated_textures[t.texture].texture != null:
|
if generated_textures[t.texture].texture != null:
|
||||||
generated_textures[t.texture].texture = null
|
generated_textures[t.texture].texture = null
|
||||||
else:
|
else:
|
||||||
generated_textures[t.texture].shader = source.generate_shader()
|
|
||||||
generated_textures[t.texture].source = source
|
|
||||||
if generated_textures[t.texture].texture == null:
|
if generated_textures[t.texture].texture == null:
|
||||||
generated_textures[t.texture].texture = ImageTexture.new()
|
generated_textures[t.texture].texture = ImageTexture.new()
|
||||||
_rerender()
|
_rerender()
|
||||||
|
|
||||||
|
func get_generated_texture(slot, file_prefix = null):
|
||||||
|
if file_prefix != null:
|
||||||
|
var file_name = "%s_%s.png" % [ file_prefix, slot ]
|
||||||
|
if File.new().file_exists(file_name):
|
||||||
|
return load(file_name)
|
||||||
|
else:
|
||||||
|
return null
|
||||||
|
else:
|
||||||
|
return generated_textures[slot].texture
|
||||||
|
|
||||||
|
func update_spatial_material(m, file_prefix = null):
|
||||||
|
var texture
|
||||||
|
m.albedo_color = albedo_color
|
||||||
|
m.albedo_texture = get_generated_texture("albedo", file_prefix)
|
||||||
|
m.metallic = metallic
|
||||||
|
m.roughness = roughness
|
||||||
|
if Engine.editor_hint:
|
||||||
|
texture = get_generated_texture("mrao", file_prefix)
|
||||||
|
m.metallic_texture = texture
|
||||||
|
m.metallic_texture_channel = SpatialMaterial.TEXTURE_CHANNEL_RED
|
||||||
|
m.roughness_texture = texture
|
||||||
|
m.roughness_texture_channel = SpatialMaterial.TEXTURE_CHANNEL_GREEN
|
||||||
|
else:
|
||||||
|
m.metallic_texture = get_generated_texture("metallic", file_prefix)
|
||||||
|
m.roughness_texture = get_generated_texture("roughness", file_prefix)
|
||||||
|
texture = get_generated_texture("emission", file_prefix)
|
||||||
|
if texture != null:
|
||||||
|
m.emission_enabled = true
|
||||||
|
m.emission_energy = emission_energy
|
||||||
|
m.emission_texture = texture
|
||||||
|
else:
|
||||||
|
m.emission_enabled = false
|
||||||
|
texture = get_generated_texture("normal_map", file_prefix)
|
||||||
|
if texture != null:
|
||||||
|
m.normal_enabled = true
|
||||||
|
m.normal_texture = texture
|
||||||
|
else:
|
||||||
|
m.normal_enabled = false
|
||||||
|
if Engine.editor_hint:
|
||||||
|
if (generated_textures.mrao.mask & (1 << 2)) != 0:
|
||||||
|
m.ao_enabled = true
|
||||||
|
m.ao_light_affect = ao_light_affect
|
||||||
|
m.ao_texture = m.metallic_texture
|
||||||
|
m.ao_texture_channel = SpatialMaterial.TEXTURE_CHANNEL_BLUE
|
||||||
|
else:
|
||||||
|
m.ao_enabled = false
|
||||||
|
else:
|
||||||
|
texture = get_generated_texture("ambient_occlusion", file_prefix)
|
||||||
|
if texture != null:
|
||||||
|
m.ao_enabled = true
|
||||||
|
m.ao_light_affect = ao_light_affect
|
||||||
|
m.ao_texture = texture
|
||||||
|
else:
|
||||||
|
m.ao_enabled = false
|
||||||
|
texture = get_generated_texture("depth_map", file_prefix)
|
||||||
|
if texture != null:
|
||||||
|
m.depth_enabled = true
|
||||||
|
m.depth_scale = depth_scale
|
||||||
|
m.depth_texture = texture
|
||||||
|
else:
|
||||||
|
m.depth_enabled = false
|
||||||
|
|
||||||
func do_update_materials(material_list):
|
func do_update_materials(material_list):
|
||||||
for m in material_list:
|
for m in material_list:
|
||||||
if m is SpatialMaterial:
|
if m is SpatialMaterial:
|
||||||
m.albedo_color = albedo_color
|
update_spatial_material(m)
|
||||||
m.albedo_texture = generated_textures.albedo.texture
|
|
||||||
m.metallic = metallic
|
|
||||||
m.metallic_texture = generated_textures.metallic.texture
|
|
||||||
m.roughness = roughness
|
|
||||||
m.roughness_texture = generated_textures.roughness.texture
|
|
||||||
if generated_textures.emission.texture != null:
|
|
||||||
m.emission_enabled = true
|
|
||||||
m.emission_energy = emission_energy
|
|
||||||
m.emission_texture = generated_textures.emission.texture
|
|
||||||
else:
|
|
||||||
m.emission_enabled = false
|
|
||||||
if generated_textures.normal_map.texture != null:
|
|
||||||
m.normal_enabled = true
|
|
||||||
m.normal_texture = generated_textures.normal_map.texture
|
|
||||||
else:
|
|
||||||
m.normal_enabled = false
|
|
||||||
if generated_textures.ambient_occlusion.texture != null:
|
|
||||||
m.ao_enabled = true
|
|
||||||
m.ao_light_affect = ao_light_affect
|
|
||||||
m.ao_texture = generated_textures.ambient_occlusion.texture
|
|
||||||
else:
|
|
||||||
m.ao_enabled = false
|
|
||||||
if generated_textures.depth_map.texture != null:
|
|
||||||
m.depth_enabled = true
|
|
||||||
m.depth_scale = depth_scale
|
|
||||||
m.depth_texture = generated_textures.depth_map.texture
|
|
||||||
else:
|
|
||||||
m.depth_enabled = false
|
|
||||||
|
|
||||||
func export_textures(prefix, size = null):
|
func export_textures(prefix, size = null):
|
||||||
if size == null:
|
if size == null:
|
||||||
size = int(pow(2, 8+resolution))
|
size = int(pow(2, 8+resolution))
|
||||||
var texture_list = TEXTURE_LIST
|
|
||||||
if Engine.editor_hint:
|
|
||||||
texture_list = ADDON_TEXTURE_LIST
|
|
||||||
for t in texture_list:
|
for t in texture_list:
|
||||||
if t.has("port"):
|
var texture = generated_textures[t.texture].texture
|
||||||
get_parent().export_texture(get_source(t.port), "%s_%s.png" % [ prefix, t.texture ], size)
|
if texture != null:
|
||||||
elif t.has("ports"):
|
var image = texture.get_data()
|
||||||
get_parent().export_combined_texture(get_source(t.port[0]), get_source(t.port[1]), get_source(t.port[2]), "%s_%s.png" % [ prefix, t.texture ], size)
|
image.save_png("%s_%s.png" % [ prefix, t.texture ])
|
||||||
if Engine.editor_hint:
|
if Engine.editor_hint:
|
||||||
print("Exporting material")
|
var resource_filesystem = get_parent().editor_interface.get_resource_filesystem()
|
||||||
|
resource_filesystem.scan()
|
||||||
|
yield(resource_filesystem, "filesystem_changed")
|
||||||
|
var new_material = SpatialMaterial.new()
|
||||||
|
update_spatial_material(new_material, prefix)
|
||||||
|
ResourceSaver.save("%s.tres" % [ prefix ], new_material)
|
||||||
|
resource_filesystem.scan()
|
||||||
|
@ -35,13 +35,13 @@ func _ready():
|
|||||||
initialize_properties([ $HBoxContainer1/size, $HBoxContainer2/amount ])
|
initialize_properties([ $HBoxContainer1/size, $HBoxContainer2/amount ])
|
||||||
|
|
||||||
func _rerender():
|
func _rerender():
|
||||||
get_parent().precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+size)), input_texture, self, "pass_1", [])
|
get_parent().renderer.precalculate_shader(input_shader, get_source().get_textures(), int(pow(2, 5+size)), input_texture, self, "pass_1", [])
|
||||||
|
|
||||||
func pass_1():
|
func pass_1():
|
||||||
var convolution = CONVOLUTION
|
var convolution = CONVOLUTION
|
||||||
convolution.epsilon=1.0/pow(2, 5+size)
|
convolution.epsilon=1.0/pow(2, 5+size)
|
||||||
convolution.scale_before_normalize = pow(2, size-1)*amount
|
convolution.scale_before_normalize = pow(2, size-1)*amount
|
||||||
get_parent().precalculate_shader(get_convolution_shader(convolution), { input=input_texture}, int(pow(2, 5+size)), final_texture, self, "rerender_targets", [])
|
get_parent().renderer.precalculate_shader(get_convolution_shader(convolution), { input=input_texture}, int(pow(2, 5+size)), final_texture, self, "rerender_targets", [])
|
||||||
|
|
||||||
func get_textures():
|
func get_textures():
|
||||||
var list = {}
|
var list = {}
|
||||||
@ -53,7 +53,7 @@ func _get_shader_code(uv):
|
|||||||
var src = get_source()
|
var src = get_source()
|
||||||
if src == null:
|
if src == null:
|
||||||
return rv
|
return rv
|
||||||
input_shader = do_generate_shader(src.get_shader_code("UV"))
|
input_shader = get_parent().renderer.generate_shader(src.get_shader_code("UV"))
|
||||||
_rerender()
|
_rerender()
|
||||||
if generated_variants.empty():
|
if generated_variants.empty():
|
||||||
rv.defs = "uniform sampler2D %s_tex;\n" % [ name ]
|
rv.defs = "uniform sampler2D %s_tex;\n" % [ name ]
|
||||||
|
@ -5,17 +5,12 @@ var mm_button = null
|
|||||||
var material_maker = null
|
var material_maker = null
|
||||||
|
|
||||||
func _enter_tree():
|
func _enter_tree():
|
||||||
#material_maker = preload("res://addons/material_maker/pm_material_maker.tscn").instance()
|
|
||||||
#add_control_to_bottom_panel(material_maker, "ProceduralMaterial")
|
|
||||||
print("Adding menu item")
|
|
||||||
mm_button = Button.new()
|
mm_button = Button.new()
|
||||||
mm_button.connect("pressed", self, "open_material_maker")
|
mm_button.connect("pressed", self, "open_material_maker")
|
||||||
mm_button.text = "Material Maker"
|
mm_button.text = "Material Maker"
|
||||||
add_control_to_container(CONTAINER_TOOLBAR, mm_button)
|
add_control_to_container(CONTAINER_TOOLBAR, mm_button)
|
||||||
print("done")
|
|
||||||
|
|
||||||
func _exit_tree():
|
func _exit_tree():
|
||||||
#remove_control_from_bottom_panel(material_maker)
|
|
||||||
if mm_button != null:
|
if mm_button != null:
|
||||||
remove_control_from_container(CONTAINER_TOOLBAR, mm_button)
|
remove_control_from_container(CONTAINER_TOOLBAR, mm_button)
|
||||||
mm_button.queue_free()
|
mm_button.queue_free()
|
||||||
@ -34,6 +29,15 @@ func _set_state(s):
|
|||||||
|
|
||||||
func open_material_maker():
|
func open_material_maker():
|
||||||
if material_maker == null:
|
if material_maker == null:
|
||||||
material_maker = load("res://addons/material_maker/window_dialog.tscn").instance()
|
material_maker = preload("res://addons/material_maker/window_dialog.tscn").instance()
|
||||||
|
var panel = material_maker.get_node("MainWindow")
|
||||||
|
panel.editor_interface = get_editor_interface()
|
||||||
|
panel.connect("quit", self, "close_material_maker")
|
||||||
add_child(material_maker)
|
add_child(material_maker)
|
||||||
material_maker.popup_centered()
|
material_maker.popup_centered()
|
||||||
|
|
||||||
|
func close_material_maker():
|
||||||
|
if material_maker != null:
|
||||||
|
material_maker.hide()
|
||||||
|
material_maker.queue_free()
|
||||||
|
material_maker = null
|
||||||
|
98
addons/material_maker/renderer.gd
Normal file
98
addons/material_maker/renderer.gd
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
tool
|
||||||
|
extends Viewport
|
||||||
|
|
||||||
|
var render_queue = []
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
$ColorRect.material = $ColorRect.material.duplicate(true)
|
||||||
|
|
||||||
|
# Save shader to image, create image texture
|
||||||
|
|
||||||
|
static func generate_shader(src_code):
|
||||||
|
var code
|
||||||
|
code = "shader_type canvas_item;\n"
|
||||||
|
var file = File.new()
|
||||||
|
file.open("res://addons/material_maker/common.shader", File.READ)
|
||||||
|
code += file.get_as_text()
|
||||||
|
code += "\n"
|
||||||
|
var shader_code = src_code.defs
|
||||||
|
shader_code += "void fragment() {\n"
|
||||||
|
shader_code += src_code.code
|
||||||
|
shader_code += "COLOR = vec4("+src_code.rgb+", 1.0);\n"
|
||||||
|
shader_code += "}\n"
|
||||||
|
#print("GENERATED SHADER:\n"+shader_code)
|
||||||
|
code += shader_code
|
||||||
|
return code
|
||||||
|
|
||||||
|
static func generate_combined_shader(red_code, green_code, blue_code):
|
||||||
|
var code
|
||||||
|
code = "shader_type canvas_item;\n"
|
||||||
|
var file = File.new()
|
||||||
|
file.open("res://addons/material_maker/common.shader", File.READ)
|
||||||
|
code += file.get_as_text()
|
||||||
|
code += "\n"
|
||||||
|
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("+red_code.f+", "+green_code.f+", "+blue_code.f+", 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):
|
||||||
|
for k in textures.keys():
|
||||||
|
shader_material.set_shader_param(k+"_tex", textures[k])
|
||||||
|
shader_material.shader.code = shader_code
|
||||||
|
|
||||||
|
func render_shader_to_viewport(shader, textures, render_size, method, args):
|
||||||
|
render_queue.append( { shader=shader, textures=textures, size=render_size, method=method, args=args } )
|
||||||
|
if render_queue.size() == 1:
|
||||||
|
while !render_queue.empty():
|
||||||
|
var job = render_queue.front()
|
||||||
|
size = Vector2(job.size, job.size)
|
||||||
|
$ColorRect.rect_position = Vector2(0, 0)
|
||||||
|
$ColorRect.rect_size = Vector2(job.size, job.size)
|
||||||
|
var shader_material = $ColorRect.material
|
||||||
|
shader_material.shader.code = job.shader
|
||||||
|
if job.textures != null:
|
||||||
|
for k in job.textures.keys():
|
||||||
|
shader_material.set_shader_param(k+"_tex", job.textures[k])
|
||||||
|
render_target_update_mode = Viewport.UPDATE_ALWAYS
|
||||||
|
update_worlds()
|
||||||
|
yield(get_tree(), "idle_frame")
|
||||||
|
yield(get_tree(), "idle_frame")
|
||||||
|
render_target_update_mode = Viewport.UPDATE_DISABLED
|
||||||
|
callv(job.method, job.args)
|
||||||
|
render_queue.pop_front()
|
||||||
|
|
||||||
|
func render_to_viewport(node, render_size, method, args):
|
||||||
|
render_shader_to_viewport(node.generate_shader(), node.get_textures(), render_size, method, args)
|
||||||
|
|
||||||
|
func export_texture(node, filename, render_size = 256):
|
||||||
|
if node == null:
|
||||||
|
return null
|
||||||
|
render_to_viewport(node, render_size, "do_export_texture", [ filename ])
|
||||||
|
|
||||||
|
func do_export_texture(filename):
|
||||||
|
var viewport_texture = get_texture()
|
||||||
|
var viewport_image = viewport_texture.get_data()
|
||||||
|
viewport_image.save_png(filename)
|
||||||
|
|
||||||
|
func precalculate_node(node, render_size, target_texture, object, method, args):
|
||||||
|
if node == null:
|
||||||
|
return null
|
||||||
|
render_to_viewport(node, render_size, "do_precalculate_texture", [ object, method, args ])
|
||||||
|
|
||||||
|
func precalculate_shader(shader, textures, render_size, target_texture, object, method, args):
|
||||||
|
render_shader_to_viewport(shader, textures, render_size, "do_precalculate_texture", [ target_texture, object, method, args ])
|
||||||
|
|
||||||
|
func do_precalculate_texture(target_texture, object, method, args):
|
||||||
|
var viewport_texture = get_texture()
|
||||||
|
target_texture.create_from_image(viewport_texture.get_data())
|
||||||
|
object.callv(method, args)
|
72
addons/material_maker/renderer.tscn
Normal file
72
addons/material_maker/renderer.tscn
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
[gd_scene load_steps=4 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://addons/material_maker/renderer.gd" type="Script" id=1]
|
||||||
|
|
||||||
|
[sub_resource type="Shader" id=1]
|
||||||
|
|
||||||
|
code = "shader_type canvas_item;
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
COLOR = vec4(1.0);
|
||||||
|
}
|
||||||
|
"
|
||||||
|
|
||||||
|
[sub_resource type="ShaderMaterial" id=2]
|
||||||
|
|
||||||
|
render_priority = 0
|
||||||
|
shader = SubResource( 1 )
|
||||||
|
|
||||||
|
[node name="Renderer" type="Viewport"]
|
||||||
|
|
||||||
|
arvr = false
|
||||||
|
size = Vector2( 0, 0 )
|
||||||
|
own_world = true
|
||||||
|
world = null
|
||||||
|
transparent_bg = false
|
||||||
|
msaa = 2
|
||||||
|
hdr = false
|
||||||
|
disable_3d = false
|
||||||
|
usage = 2
|
||||||
|
debug_draw = 0
|
||||||
|
render_target_v_flip = true
|
||||||
|
render_target_clear_mode = 0
|
||||||
|
render_target_update_mode = 1
|
||||||
|
audio_listener_enable_2d = false
|
||||||
|
audio_listener_enable_3d = false
|
||||||
|
physics_object_picking = false
|
||||||
|
gui_disable_input = true
|
||||||
|
gui_snap_controls_to_pixels = true
|
||||||
|
shadow_atlas_size = 0
|
||||||
|
shadow_atlas_quad_0 = 2
|
||||||
|
shadow_atlas_quad_1 = 2
|
||||||
|
shadow_atlas_quad_2 = 3
|
||||||
|
shadow_atlas_quad_3 = 4
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
_sections_unfolded = [ "GUI", "Render Target", "Rendering" ]
|
||||||
|
|
||||||
|
[node name="ColorRect" type="ColorRect" parent="." index="0"]
|
||||||
|
|
||||||
|
material = SubResource( 2 )
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_right = 40.0
|
||||||
|
margin_bottom = 40.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
color = Color( 1, 1, 1, 1 )
|
||||||
|
_sections_unfolded = [ "Material", "Rect" ]
|
||||||
|
|
||||||
|
[node name="Timer" type="Timer" parent="." index="1"]
|
||||||
|
|
||||||
|
process_mode = 1
|
||||||
|
wait_time = 0.1
|
||||||
|
one_shot = true
|
||||||
|
autostart = false
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
{"connections":[{"from":"pattern_1","from_port":0,"to":"colorize_0","to_port":0},{"from":"perlin_0","from_port":0,"to":"transform_0","to_port":0},{"from":"colorize_0","from_port":0,"to":"transform_0","to_port":3},{"from":"uniform_0","from_port":0,"to":"Material","to_port":2},{"from":"normal_map_0","from_port":0,"to":"Material","to_port":4},{"from":"transform_0","from_port":0,"to":"normal_map_0","to_port":0},{"from":"transform_0","from_port":0,"to":"colorize_1","to_port":0},{"from":"colorize_1","from_port":0,"to":"Material","to_port":0}],"nodes":[{"iterations":7,"name":"perlin_0","node_position":{"x":-248,"y":-183.5},"persistence":0.5,"scale_x":4,"scale_y":4,"type":"perlin"},{"mix":0,"name":"pattern_1","node_position":{"x":-488,"y":6.5},"type":"pattern","x_scale":1,"x_wave":0,"y_scale":1,"y_wave":0},{"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":1,"g":1,"pos":1,"r":1}],"name":"colorize_0","node_position":{"x":-214,"y":9.5},"type":"colorize"},{"albedo_color":{"a":1,"b":1,"g":1,"r":1,"type":"Color"},"ao_light_affect":1,"depth_scale":1,"emission_energy":1,"metallic":1,"name":"Material","node_position":{"x":387,"y":-79},"normal_scale":1,"resolution":1,"roughness":1,"type":"material"},{"color":{"a":1,"b":0,"g":0,"r":0,"type":"Color"},"name":"uniform_0","node_position":{"x":248.577271,"y":-53.178574},"type":"uniform"},{"amount":0.5,"name":"normal_map_0","node_position":{"x":234.577271,"y":52.821411},"type":"normal_map"},{"name":"transform_0","node_position":{"x":-8,"y":-73.5},"repeat":true,"rotate":100,"scale_x":1,"scale_y":1,"translate_x":0,"translate_y":0,"type":"transform"},{"gradient":[{"b":0,"g":0,"pos":0.3,"r":1},{"b":0,"g":1,"pos":0.409091,"r":0.96875},{"b":0,"g":0.801432,"pos":0.518182,"r":0.025045},{"b":1,"g":0.000001,"pos":0.627273,"r":0},{"b":0.708333,"g":0,"pos":0.745455,"r":0.641927}],"name":"colorize_1","node_position":{"x":213,"y":-149.5},"type":"colorize"}]}
|
|
Loading…
Reference in New Issue
Block a user