Improved SpatialMaterial support

Now the material node is aimed at Godot's SpatialMaterial. Textures are generated and passed to the SpatialMaterial (and not generated as shaders anymore).
Rendering textures requires a Timer (to wait for the viewport to be rendered). There has to be a better solution...
Added a couple more examples.
This commit is contained in:
RodZill4 2018-07-29 23:43:24 +02:00
parent 58f30c4276
commit 279b0e0103
11 changed files with 587 additions and 390 deletions

View File

@ -56,3 +56,41 @@ func generate_shader(node, shader_type = 0):
#print("GENERATED SHADER:\n"+shader_code) #print("GENERATED SHADER:\n"+shader_code)
code += shader_code code += shader_code
return 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 export_texture(node, filename, size = 256):
if node != null:
$SaveViewport.size = Vector2(size, size)
$SaveViewport/ColorRect.rect_position = Vector2(0, 0)
$SaveViewport/ColorRect.rect_size = Vector2(size, size)
setup_material($SaveViewport/ColorRect.material, node.get_textures(), generate_shader(node))
$SaveViewport.render_target_update_mode = Viewport.UPDATE_ONCE
$SaveViewport.update_worlds()
$SaveViewport/Timer.start()
yield($SaveViewport/Timer, "timeout")
var viewport_texture = $SaveViewport.get_texture()
var viewport_image = viewport_texture.get_data()
viewport_image.save_png("res://generated_image.png")
func precalculate_texture(node, size, object, method, args):
if node == null:
return null
$SaveViewport.size = Vector2(size, size)
$SaveViewport/ColorRect.rect_position = Vector2(0, 0)
$SaveViewport/ColorRect.rect_size = Vector2(size, size)
setup_material($SaveViewport/ColorRect.material, node.get_textures(), generate_shader(node))
$SaveViewport.render_target_update_mode = Viewport.UPDATE_ONCE
$SaveViewport.update_worlds()
$SaveViewport/Timer.start()
yield($SaveViewport/Timer, "timeout")
var viewport_texture = $SaveViewport.get_texture()
var texture = ImageTexture.new()
texture.create_from_image(viewport_texture.get_data())
args.append(texture)
object.callv(method, args)

View File

@ -1,9 +1,18 @@
tool tool
extends "res://addons/procedural_material/node_base.gd" extends "res://addons/procedural_material/node_base.gd"
var texture_albedo = null
var texture_metallic = null
var texture_roughness = null
var texture_emission = null
var texture_normal_map = null
var texture_depth_map = null
var render_queue = [] # render queue for generated textures
var material_list = [] # materials to be updatedwith generated textures
func _ready(): func _ready():
set_slot(0, true, 0, Color(0.5, 0.5, 1), false, 0, Color(0.5, 0.5, 1)) pass
set_slot(1, true, 0, Color(0.5, 0.5, 1), false, 0, Color(0.5, 0.5, 1))
func _get_shader_code(uv): func _get_shader_code(uv):
var rv = { defs="", code="", f="0.0" } var rv = { defs="", code="", f="0.0" }
@ -21,3 +30,53 @@ func _get_shader_code(uv):
func _get_state_variables(): func _get_state_variables():
return [ ] return [ ]
func update_materials(ml):
material_list = ml
render_queue = [
{ port= 0, texture= "albedo" },
{ port= 1, texture= "metallic" },
{ port= 2, texture= "roughness" },
{ port= 3, texture= "emission" },
{ port= 4, texture= "normal_map" },
{ port= 5, texture= "depth_map" }
]
process_render_queue()
func process_render_queue():
while !render_queue.empty():
var job = render_queue.pop_front()
var source = get_source(job.port)
if source != null:
get_parent().precalculate_texture(source, 1024, self, "store_texture", [ job.texture ])
return
else:
set("texture_"+job.texture, null)
do_update_materials()
func store_texture(texture_name, texture):
set("texture_"+texture_name, texture)
process_render_queue()
func do_update_materials():
for m in material_list:
if m is SpatialMaterial:
m.albedo_texture = texture_albedo
m.metallic_texture = texture_metallic
m.roughness_texture = texture_roughness
if texture_emission != null:
m.emission_enabled = true
m.emission_texture = texture_emission
else:
m.emission_enabled = false
if texture_normal_map != null:
m.normal_enabled = true
m.normal_texture = texture_normal_map
else:
m.normal_enabled = false
if texture_depth_map != null:
m.depth_enabled = true
m.depth_texture = texture_depth_map
else:
m.depth_enabled = false

View File

@ -39,8 +39,32 @@ slot/1/left_color = Color( 0.5, 0.5, 1, 1 )
slot/1/right_enabled = false slot/1/right_enabled = false
slot/1/right_type = 0 slot/1/right_type = 0
slot/1/right_color = Color( 0.5, 0.5, 1, 1 ) slot/1/right_color = Color( 0.5, 0.5, 1, 1 )
slot/2/left_enabled = true
slot/2/left_type = 0
slot/2/left_color = Color( 0.498039, 0.498039, 1, 1 )
slot/2/right_enabled = false
slot/2/right_type = 0
slot/2/right_color = Color( 0.498039, 0.498039, 1, 1 )
slot/3/left_enabled = true
slot/3/left_type = 0
slot/3/left_color = Color( 0.498039, 0.498039, 1, 1 )
slot/3/right_enabled = false
slot/3/right_type = 0
slot/3/right_color = Color( 0.498039, 0.498039, 1, 1 )
slot/4/left_enabled = true
slot/4/left_type = 0
slot/4/left_color = Color( 0.498039, 0.498039, 1, 1 )
slot/4/right_enabled = false
slot/4/right_type = 0
slot/4/right_color = Color( 0.498039, 0.498039, 1, 1 )
slot/5/left_enabled = true
slot/5/left_type = 0
slot/5/left_color = Color( 0.498039, 0.498039, 1, 1 )
slot/5/right_enabled = false
slot/5/right_type = 0
slot/5/right_color = Color( 0.498039, 0.498039, 1, 1 )
script = ExtResource( 1 ) script = ExtResource( 1 )
_sections_unfolded = [ "Theme" ] _sections_unfolded = [ "Theme", "slot", "slot/2", "slot/3", "slot/4", "slot/5" ]
[node name="Label1" type="Label" parent="." index="0"] [node name="Label1" type="Label" parent="." index="0"]
@ -79,9 +103,93 @@ mouse_filter = 2
mouse_default_cursor_shape = 0 mouse_default_cursor_shape = 0
size_flags_horizontal = 1 size_flags_horizontal = 1
size_flags_vertical = 4 size_flags_vertical = 4
text = "Metallic"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="Label3" type="Label" parent="." index="2"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 16.0
margin_top = 53.0
margin_right = 95.0
margin_bottom = 67.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "Roughness"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="Label4" type="Label" parent="." index="3"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 16.0
margin_top = 68.0
margin_right = 95.0
margin_bottom = 82.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "Emission"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1
[node name="Label5" type="Label" parent="." index="4"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 16.0
margin_top = 83.0
margin_right = 95.0
margin_bottom = 97.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "Normal map" text = "Normal map"
percent_visible = 1.0 percent_visible = 1.0
lines_skipped = 0 lines_skipped = 0
max_lines_visible = -1 max_lines_visible = -1
[node name="Label6" type="Label" parent="." index="5"]
anchor_left = 0.0
anchor_top = 0.0
anchor_right = 0.0
anchor_bottom = 0.0
margin_left = 16.0
margin_top = 98.0
margin_right = 95.0
margin_bottom = 112.0
rect_pivot_offset = Vector2( 0, 0 )
rect_clip_content = false
mouse_filter = 2
mouse_default_cursor_shape = 0
size_flags_horizontal = 1
size_flags_vertical = 4
text = "Depth map"
percent_visible = 1.0
lines_skipped = 0
max_lines_visible = -1

View File

@ -5,7 +5,7 @@
[sub_resource type="Theme" id=1] [sub_resource type="Theme" id=1]
[node name="Transform" type="GraphNode" index="0"] [node name="Transform" type="GraphNode"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0

View File

@ -5,7 +5,7 @@
[sub_resource type="Theme" id=1] [sub_resource type="Theme" id=1]
[node name="Warp" type="GraphNode" index="0"] [node name="Warp" type="GraphNode"]
anchor_left = 0.0 anchor_left = 0.0
anchor_top = 0.0 anchor_top = 0.0
@ -120,6 +120,4 @@ _sections_unfolded = [ "Caret", "Placeholder" ]
[connection signal="close_request" from="." to="." method="queue_free"] [connection signal="close_request" from="." to="." method="queue_free"]
[connection signal="text_changed" from="amount" to="." method="_on_Rotate_text_changed"]

View File

@ -5,7 +5,6 @@ var popup_menu = null
var popup_position = Vector2(0, 0) var popup_position = Vector2(0, 0)
var selected_node = null var selected_node = null
var preview_material = null
var texture_preview_material = null var texture_preview_material = null
const MENU = [ const MENU = [
@ -28,7 +27,6 @@ const MENU = [
func _ready(): func _ready():
# Duplicate the material we'll modify and store the shaders # Duplicate the material we'll modify and store the shaders
preview_material = $Preview/Preview.preview_material
$Preview/Preview/SelectedPreview.material = $Preview/Preview/SelectedPreview.material.duplicate(true) $Preview/Preview/SelectedPreview.material = $Preview/Preview/SelectedPreview.material.duplicate(true)
texture_preview_material = $Preview/Preview/SelectedPreview.material texture_preview_material = $Preview/Preview/SelectedPreview.material
$GraphEdit.add_valid_connection_type(0, 0) $GraphEdit.add_valid_connection_type(0, 0)
@ -137,34 +135,16 @@ func save_file(filename):
file.store_string(to_json(data)) file.store_string(to_json(data))
file.close() file.close()
func export_texture(): func export_texture(size = 256):
var size = 256 $GraphEdit.export_texture(selected_node, "res://generated_image.png", size)
$SaveViewport.size = Vector2(size, size)
$SaveViewport/ColorRect.rect_position = Vector2(0, 0)
$SaveViewport/ColorRect.rect_size = Vector2(size, size)
setup_material($SaveViewport/ColorRect.material, selected_node.get_textures(), $GraphEdit.generate_shader(selected_node))
$SaveViewport.render_target_update_mode = Viewport.UPDATE_ONCE
#$SaveViewport/ColorRect.update()
$SaveViewport.update_worlds()
$SaveViewport/Timer.start()
yield($SaveViewport/Timer, "timeout")
var viewport_texture = $SaveViewport.get_texture()
var viewport_image = viewport_texture.get_data()
viewport_image.save_png("res://generated_image.png")
func setup_material(shader_material, textures, shader_code):
for k in textures.keys():
#print("Setting param "+k+" to "+str(textures[k]))
shader_material.set_shader_param(k+"_tex", textures[k])
shader_material.shader.code = shader_code
func generate_shader(): func generate_shader():
setup_material(preview_material, $GraphEdit/Material.get_textures(), $GraphEdit.generate_shader($GraphEdit/Material, 1)) $GraphEdit/Material.update_materials($Preview/Preview.get_materials())
if selected_node != null: if selected_node != null:
setup_material(texture_preview_material, selected_node.get_textures(), $GraphEdit.generate_shader(selected_node)) $GraphEdit.setup_material(texture_preview_material, selected_node.get_textures(), $GraphEdit.generate_shader(selected_node))
func _on_GraphEdit_node_selected(node): func _on_GraphEdit_node_selected(node):
if selected_node != node: if selected_node != node && node is GraphNode:
selected_node = node selected_node = node
setup_material(texture_preview_material, selected_node.get_textures(), $GraphEdit.generate_shader(selected_node)) $GraphEdit.setup_material(texture_preview_material, selected_node.get_textures(), $GraphEdit.generate_shader(selected_node))

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,6 @@
tool tool
extends ViewportContainer extends ViewportContainer
var preview_material = null
var preview_maximized = false var preview_maximized = false
const ENVIRONMENTS = [ const ENVIRONMENTS = [
@ -9,11 +8,9 @@ const ENVIRONMENTS = [
] ]
func _ready(): func _ready():
preview_material = ShaderMaterial.new() var m = $MaterialPreview/Objects/Cube.get_surface_material(0).duplicate()
preview_material.shader = Shader.new() $MaterialPreview/Objects/Cube.set_surface_material(0, m)
preview_material.shader.set_code("shader_type spatial;\nvoid fragment() {\n ALBEDO=vec3(0.5);\n}\n") $MaterialPreview/Objects/Cylinder.set_surface_material(0, m)
$MaterialPreview/Objects/Cube.set_surface_material(0, preview_material)
$MaterialPreview/Objects/Cylinder.set_surface_material(0, preview_material)
$ObjectRotate.play("rotate") $ObjectRotate.play("rotate")
_on_Environment_item_selected($Environment.selected) _on_Environment_item_selected($Environment.selected)
@ -32,3 +29,6 @@ func _on_Model_item_selected(id):
var model = $Model.get_item_text(id) var model = $Model.get_item_text(id)
for c in $MaterialPreview/Objects.get_children(): for c in $MaterialPreview/Objects.get_children():
c.visible = (c.get_name() == model) c.visible = (c.get_name() == model)
func get_materials():
return [ $MaterialPreview/Objects/Cube.get_surface_material(0) ]

View File

@ -1 +1 @@
{"connections":[{"from":"Bricks","from_port":0,"to":"Warp","to_port":0},{"from":"Perlin","from_port":0,"to":"Warp","to_port":1},{"from":"Warp","from_port":0,"to":"NormalMap","to_port":0},{"from":"Perlin2","from_port":0,"to":"colorize_0","to_port":0},{"from":"Perlin2","from_port":0,"to":"colorize_1","to_port":0},{"from":"Warp","from_port":0,"to":"colorize_2","to_port":0},{"from":"colorize_2","from_port":0,"to":"blend_0","to_port":2},{"from":"blend_0","from_port":0,"to":"transform_0","to_port":0},{"from":"transform_0","from_port":0,"to":"Material","to_port":0},{"from":"NormalMap","from_port":0,"to":"transform_1","to_port":0},{"from":"transform_1","from_port":0,"to":"Material","to_port":1},{"from":"colorize_1","from_port":0,"to":"blend_0","to_port":0},{"from":"colorize_0","from_port":0,"to":"blend_0","to_port":1}],"nodes":[{"iterations":7,"name":"Perlin2","node_position":{"x":258,"y":-32},"persistence":0.5,"scale_x":8,"scale_y":8,"type":"perlin"},{"bevel":0.6,"columns":6,"mortar":0.05,"name":"Bricks","node_position":{"x":260,"y":132},"row_offset":0.5,"rows":12,"type":"bricks"},{"amount":0.5,"name":"NormalMap","node_position":{"x":694,"y":297},"type":"normal_map"},{"iterations":6,"name":"Perlin","node_position":{"x":255,"y":322},"persistence":0.5,"scale_x":4,"scale_y":4,"type":"perlin"},{"amount":0.1,"name":"Warp","node_position":{"x":504,"y":199.75},"type":"warp"},{"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":1,"g":1,"pos":0.090909,"r":1}],"name":"colorize_2","node_position":{"x":639.943665,"y":152},"type":"colorize"},{"name":"transform_1","node_position":{"x":944.779785,"y":262.75},"rotate":0,"scale":1,"type":"transform"},{"name":"Material","node_position":{"x":1165,"y":171},"type":"material"},{"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":1,"g":1,"pos":1,"r":1}],"name":"colorize_0","node_position":{"x":560.943665,"y":50},"type":"colorize"},{"gradient":[{"b":0.002889,"g":0.102424,"pos":0,"r":0.184896},{"b":0,"g":0.19869,"pos":0.327273,"r":0.669271},{"b":0.019368,"g":0.060224,"pos":0.681818,"r":0.309896},{"b":0,"g":0.180135,"pos":1,"r":0.606771}],"name":"colorize_1","node_position":{"x":562.943665,"y":-65},"type":"colorize"},{"name":"transform_0","node_position":{"x":938.779785,"y":129.75},"rotate":0,"scale":1,"type":"transform"},{"amount":0.5,"blend_type":0,"name":"blend_0","node_position":{"x":820.943726,"y":-33},"type":"blend"}]} {"connections":[{"from":"Bricks","from_port":0,"to":"Warp","to_port":0},{"from":"Perlin","from_port":0,"to":"Warp","to_port":1},{"from":"Perlin2","from_port":0,"to":"colorize_0","to_port":0},{"from":"Perlin2","from_port":0,"to":"colorize_1","to_port":0},{"from":"Warp","from_port":0,"to":"colorize_2","to_port":0},{"from":"colorize_2","from_port":0,"to":"blend_0","to_port":2},{"from":"colorize_1","from_port":0,"to":"blend_0","to_port":0},{"from":"colorize_0","from_port":0,"to":"blend_0","to_port":1},{"from":"Warp","from_port":0,"to":"normal_map_0","to_port":0},{"from":"normal_map_0","from_port":0,"to":"Material","to_port":1},{"from":"Warp","from_port":0,"to":"colorize_3","to_port":0},{"from":"blend_0","from_port":0,"to":"Material","to_port":0},{"from":"colorize_3","from_port":0,"to":"Material","to_port":2}],"nodes":[{"iterations":7,"name":"Perlin2","node_position":{"x":258,"y":-32},"persistence":0.5,"scale_x":8,"scale_y":8,"type":"perlin"},{"bevel":0.2,"columns":3,"mortar":0.05,"name":"Bricks","node_position":{"x":260,"y":132},"row_offset":0.5,"rows":6,"type":"bricks"},{"iterations":6,"name":"Perlin","node_position":{"x":255,"y":322},"persistence":0.5,"scale_x":4,"scale_y":4,"type":"perlin"},{"amount":0.1,"name":"Warp","node_position":{"x":504,"y":199.75},"type":"warp"},{"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":1,"g":1,"pos":0.072727,"r":1}],"name":"colorize_2","node_position":{"x":639.943665,"y":152},"type":"colorize"},{"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":1,"g":1,"pos":1,"r":1}],"name":"colorize_0","node_position":{"x":560.943665,"y":50},"type":"colorize"},{"gradient":[{"b":0.002889,"g":0.102424,"pos":0,"r":0.184896},{"b":0,"g":0.19869,"pos":0.327273,"r":0.669271},{"b":0.019368,"g":0.060224,"pos":0.663636,"r":0.309896},{"b":0,"g":0.180135,"pos":1,"r":0.606771}],"name":"colorize_1","node_position":{"x":562.943665,"y":-65},"type":"colorize"},{"amount":0.5,"blend_type":0,"name":"blend_0","node_position":{"x":820.943726,"y":-33},"type":"blend"},{"name":"Material","node_position":{"x":1024,"y":204},"type":"material"},{"gradient":[{"b":0.273438,"g":0.273438,"pos":0,"r":0.273438},{"b":0,"g":0,"pos":1,"r":0}],"name":"colorize_3","node_position":{"x":688,"y":355},"type":"colorize"},{"amount":0.5,"name":"normal_map_0","node_position":{"x":721,"y":244},"type":"normal_map"}]}

1
examples/lava.ptex Normal file
View File

@ -0,0 +1 @@
{"connections":[{"from":"perlin_0","from_port":0,"to":"blend_0","to_port":0},{"from":"blend_0","from_port":0,"to":"colorize_0","to_port":0},{"from":"colorize_0","from_port":0,"to":"Material","to_port":0},{"from":"perlin_0","from_port":0,"to":"warp_0","to_port":1},{"from":"voronoi_0","from_port":0,"to":"warp_0","to_port":0},{"from":"warp_0","from_port":0,"to":"blend_0","to_port":1},{"from":"warp_0","from_port":0,"to":"colorize_1","to_port":0},{"from":"warp_0","from_port":0,"to":"Material","to_port":1},{"from":"warp_0","from_port":0,"to":"colorize_2","to_port":0},{"from":"colorize_2","from_port":0,"to":"Material","to_port":2},{"from":"warp_0","from_port":0,"to":"normal_map_0","to_port":0},{"from":"normal_map_0","from_port":0,"to":"Material","to_port":4},{"from":"colorize_1","from_port":0,"to":"Material","to_port":3}],"nodes":[{"name":"Material","node_position":{"x":956,"y":271},"type":"material"},{"iterations":8,"name":"perlin_0","node_position":{"x":-63,"y":-34},"persistence":0.75,"scale_x":4,"scale_y":4,"type":"perlin"},{"intensity":0.55,"name":"voronoi_0","node_position":{"x":-2,"y":204},"scale_x":6,"scale_y":6,"type":"voronoi"},{"amount":0.3,"name":"warp_0","node_position":{"x":242,"y":23},"type":"warp"},{"gradient":[{"b":0.032597,"g":0.032597,"pos":0.072727,"r":0.032597},{"b":0.111979,"g":0.111979,"pos":0.3,"r":0.111979},{"b":0.029781,"g":0.029781,"pos":0.518182,"r":0.029781},{"b":0.069093,"g":0.069093,"pos":0.818182,"r":0.069093},{"b":0,"g":0,"pos":1,"r":0}],"name":"colorize_0","node_position":{"x":666,"y":27},"type":"colorize"},{"gradient":[{"b":1,"g":1,"pos":0.290909,"r":1},{"b":0,"g":0,"pos":0.8,"r":0}],"name":"colorize_2","node_position":{"x":535,"y":123.5},"type":"colorize"},{"gradient":[{"b":0,"g":0.765625,"pos":0,"r":1},{"b":0,"g":0,"pos":0.181818,"r":1},{"b":0,"g":0,"pos":0.245455,"r":0}],"name":"colorize_1","node_position":{"x":479,"y":215},"type":"colorize"},{"amount":0.9,"name":"normal_map_0","node_position":{"x":501,"y":314.5},"type":"normal_map"},{"amount":0.45,"blend_type":1,"name":"blend_0","node_position":{"x":433,"y":-87},"type":"blend"}]}

View File

@ -0,0 +1 @@
{"connections":[{"from":"perlin_0","from_port":0,"to":"colorize_0","to_port":0},{"from":"bricks_0","from_port":0,"to":"blend_0","to_port":0},{"from":"perlin_0","from_port":0,"to":"blend_0","to_port":1},{"from":"normal_map_0","from_port":0,"to":"Material","to_port":4},{"from":"blend_0","from_port":0,"to":"normal_map_0","to_port":0},{"from":"blend_0","from_port":0,"to":"colorize_1","to_port":0},{"from":"perlin_1","from_port":0,"to":"colorize_2","to_port":0},{"from":"colorize_2","from_port":0,"to":"blend_1","to_port":0},{"from":"colorize_0","from_port":0,"to":"blend_1","to_port":1},{"from":"perlin_2","from_port":0,"to":"colorize_3","to_port":0},{"from":"colorize_3","from_port":0,"to":"blend_1","to_port":2},{"from":"blend_1","from_port":0,"to":"Material","to_port":0},{"from":"colorize_1","from_port":0,"to":"blend_2","to_port":1},{"from":"colorize_3","from_port":0,"to":"blend_2","to_port":0},{"from":"blend_2","from_port":0,"to":"Material","to_port":2}],"nodes":[{"gradient":[{"b":0.004367,"g":0.004367,"pos":0,"r":0.059896},{"b":0.012831,"g":0.012831,"pos":0.172727,"r":0.111979},{"b":0.006687,"g":0.006687,"pos":0.463636,"r":0.075521},{"b":0.007871,"g":0.007871,"pos":0.754545,"r":0.144176},{"b":0.002062,"g":0.002062,"pos":1,"r":0.049479}],"name":"colorize_2","node_position":{"x":487.633789,"y":-144.5},"type":"colorize"},{"gradient":[{"b":0.025567,"g":0.207086,"pos":0,"r":0.377604},{"b":0.013346,"g":0.061518,"pos":0.163636,"r":0.106771},{"b":0.017965,"g":0.174595,"pos":0.345455,"r":0.321733},{"b":0.015933,"g":0.124841,"pos":0.527273,"r":0.22715},{"b":0.017148,"g":0.148096,"pos":0.681818,"r":0.271107},{"b":0.015842,"g":0.105696,"pos":0.854545,"r":0.190104},{"b":0.011393,"g":0.14651,"pos":1,"r":0.273438}],"name":"colorize_0","node_position":{"x":468,"y":62.5},"type":"colorize"},{"gradient":[{"b":0,"g":0,"pos":0.454545,"r":0},{"b":1,"g":1,"pos":0.563636,"r":1}],"name":"colorize_3","node_position":{"x":494.633789,"y":-32},"type":"colorize"},{"amount":0.35,"blend_type":0,"name":"blend_2","node_position":{"x":687.633789,"y":201.5},"type":"blend"},{"gradient":[{"b":0.690104,"g":0.690104,"pos":0,"r":0.690104},{"b":0.492188,"g":0.492188,"pos":1,"r":0.492188}],"name":"colorize_1","node_position":{"x":495.633789,"y":220.5},"type":"colorize"},{"amount":0.5,"name":"normal_map_0","node_position":{"x":724.633789,"y":345.5},"type":"normal_map"},{"iterations":3,"name":"perlin_0","node_position":{"x":29,"y":214.5},"persistence":0.5,"scale_x":20,"scale_y":3,"type":"perlin"},{"bevel":0,"columns":5,"mortar":0.05,"name":"bricks_0","node_position":{"x":-1,"y":30.5},"row_offset":0.5,"rows":1,"type":"bricks"},{"iterations":6,"name":"perlin_2","node_position":{"x":220.633789,"y":19},"persistence":0.65,"scale_x":4,"scale_y":4,"type":"perlin"},{"iterations":7,"name":"perlin_1","node_position":{"x":110.633789,"y":-137.5},"persistence":0.55,"scale_x":4,"scale_y":4,"type":"perlin"},{"name":"Material","node_position":{"x":938,"y":96},"type":"material"},{"amount":0.2,"blend_type":0,"name":"blend_0","node_position":{"x":280,"y":302.5},"type":"blend"},{"amount":0.5,"blend_type":0,"name":"blend_1","node_position":{"x":694.633789,"y":-2},"type":"blend"}]}