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" if src_code.has("globals"): for g in src_code.globals: code += g var shader_code = src_code.defs shader_code += "void fragment() {\n" shader_code += src_code.code shader_code += "COLOR = "+src_code.rgba+";\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" if red_code.has("globals"): for g in red_code.globals: code += g if green_code.has("globals"): for g in green_code.globals: code += g if blue_code.has("globals"): for g in blue_code.globals: code += g var shader_code = "" shader_code += red_code.defs shader_code += green_code.defs shader_code += blue_code.defs shader_code += "void fragment() {\n" shader_code += red_code.code shader_code += green_code.code shader_code += blue_code.code shader_code += "COLOR = vec4("+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_with_globals(), 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)