mirror of
https://github.com/Relintai/material-maker.git
synced 2025-02-02 23:15:54 +01:00
Many changes & fixes...
- shader updates are delayed by .25 seconds to avouid UI freeze - fixed GraphNode initialization upon loading - started obsoleting get_source_rgb and get_source_f functions - updated colorize node to use gradient - image node can now be loaded/saved - removed iqnoise node - rewrote perlin shader to support a seed parameter (seed is calculated from the node's position, so just move it to reseed) - Added voronoi noise node - updated code to use % formats instead of concatenating strings (should solve type problems in shaders) - reworked the context menu (now has submenus) - fixes in the gradient editor
This commit is contained in:
parent
46adb434bf
commit
10ea905090
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1,3 @@
|
||||
.import
|
||||
generated_image.png
|
||||
generated_image.png
|
||||
|
@ -1,6 +1,8 @@
|
||||
tool
|
||||
extends GraphEdit
|
||||
|
||||
signal graph_changed
|
||||
|
||||
func _ready():
|
||||
pass
|
||||
|
||||
@ -14,6 +16,12 @@ func remove_node(node):
|
||||
if c.from == node or c.to == node:
|
||||
disconnect_node(c.from, c.from_port, c.to, c.to_port)
|
||||
|
||||
func send_changed_signal():
|
||||
$Timer.start()
|
||||
|
||||
func do_send_changed_signal():
|
||||
emit_signal("graph_changed")
|
||||
|
||||
func generate_shader(node, shader_type = 0):
|
||||
var code
|
||||
if shader_type == 1:
|
||||
@ -45,6 +53,6 @@ func generate_shader(node, shader_type = 0):
|
||||
else:
|
||||
shader_code += "COLOR = vec4(1.0);\n"
|
||||
shader_code += "}\n"
|
||||
print("GENERATED SHADER:\n"+shader_code)
|
||||
#print("GENERATED SHADER:\n"+shader_code)
|
||||
code += shader_code
|
||||
return code
|
||||
|
@ -6,6 +6,7 @@ var material = null
|
||||
func _ready():
|
||||
material = ShaderMaterial.new()
|
||||
material.shader = Shader.new()
|
||||
material.shader.set_code("shader_type spatial;\nvoid fragment() {\n ALBEDO=vec3(0.5);\n}\n")
|
||||
$Objects/Cube.set_surface_material(0, material)
|
||||
$Objects/Cylinder.set_surface_material(0, material)
|
||||
$AnimationPlayer.play("rotate")
|
||||
|
@ -22,24 +22,32 @@ func initialize_properties(object_list):
|
||||
set(o.name, o.color)
|
||||
o.connect("color_changed", self, "_on_color_changed", [ o.name ])
|
||||
|
||||
func get_seed():
|
||||
return int(offset.x)*3+int(offset.y)*5
|
||||
|
||||
func update_property_widgets():
|
||||
for o in property_widgets:
|
||||
if o is LineEdit:
|
||||
o.text = str(get(o.name))
|
||||
elif o is SpinBox:
|
||||
o.value = get(o.name)
|
||||
elif o is ColorPickerButton:
|
||||
o.color = get(o.name)
|
||||
|
||||
func update_shaders():
|
||||
get_parent().send_changed_signal()
|
||||
|
||||
func _on_text_changed(new_text, variable):
|
||||
set(variable, float(new_text))
|
||||
get_parent().get_parent().generate_shader()
|
||||
update_shaders()
|
||||
|
||||
func _on_value_changed(new_value, variable):
|
||||
set(variable, new_value)
|
||||
get_parent().get_parent().generate_shader()
|
||||
update_shaders()
|
||||
|
||||
func _on_color_changed(new_color, variable):
|
||||
set(variable, new_color)
|
||||
get_parent().get_parent().generate_shader()
|
||||
update_shaders()
|
||||
|
||||
func get_source(index = 0):
|
||||
for c in get_parent().get_children():
|
||||
@ -51,7 +59,7 @@ func get_source(index = 0):
|
||||
func get_source_f(source):
|
||||
var rv
|
||||
if source.has("rgb"):
|
||||
rv = "dot("+source.rgb+", vec3(1.0, 1.0, 1.0))"
|
||||
rv = "dot("+source.rgb+", vec3(1.0))/3.0"
|
||||
elif source.has("f"):
|
||||
rv = source.f
|
||||
else:
|
||||
@ -69,7 +77,12 @@ func get_source_rgb(source):
|
||||
return rv
|
||||
|
||||
func get_shader_code(uv):
|
||||
return _get_shader_code(uv)
|
||||
var rv = _get_shader_code(uv)
|
||||
if !rv.has("f") && rv.has("rgb"):
|
||||
rv.f = "(dot("+rv.rgb+", vec3(1.0))/3.0)"
|
||||
if !rv.has("rgb") && rv.has("f"):
|
||||
rv.rgb = "vec3("+rv.f+")"
|
||||
return rv
|
||||
|
||||
func get_textures():
|
||||
var list = {}
|
||||
@ -107,10 +120,9 @@ func serialize():
|
||||
return data
|
||||
|
||||
func deserialize(data):
|
||||
print("deserialize: "+name)
|
||||
offset = Vector2(data.node_position.x, data.node_position.y)
|
||||
for w in property_widgets:
|
||||
var v = w.name
|
||||
set(v, deserialize_element(data[v]))
|
||||
print(" "+v+" = "+str(deserialize_element(data[v])))
|
||||
var variable = w.name
|
||||
var value = deserialize_element(data[variable])
|
||||
set(variable, value)
|
||||
update_property_widgets()
|
||||
|
@ -22,10 +22,10 @@ func _get_shader_code(uv):
|
||||
var src0_code = src0.get_shader_code(uv)
|
||||
var src1_code = src1.get_shader_code(uv)
|
||||
var src2_code = { defs="", code="" }
|
||||
var amount_str = str(amount)
|
||||
var amount_str = "%.9f" % amount
|
||||
if src2 != null:
|
||||
src2_code = src2.get_shader_code(uv)
|
||||
amount_str = str(src2_code.f)
|
||||
amount_str = src2_code.f
|
||||
if generated_variants.empty():
|
||||
rv.defs = src0_code.defs+src1_code.defs+src2_code.defs
|
||||
var variant_index = generated_variants.find(uv)
|
||||
|
@ -6,10 +6,6 @@ var color1
|
||||
|
||||
func _ready():
|
||||
set_slot(0, true, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1))
|
||||
initialize_properties([ $color0, $color1 ])
|
||||
|
||||
func color_to_string(c):
|
||||
return "vec3("+str(c.r)+","+str(c.g)+","+str(c.b)+")"
|
||||
|
||||
func _get_shader_code(uv):
|
||||
var rv = { defs="", code="" }
|
||||
@ -18,15 +14,20 @@ func _get_shader_code(uv):
|
||||
return rv
|
||||
var src_code = src.get_shader_code(uv)
|
||||
if generated_variants.empty():
|
||||
rv.defs = src_code.defs;
|
||||
rv.defs = src_code.defs+$Control.get_shader(name+"_gradient");
|
||||
var variant_index = generated_variants.find(uv)
|
||||
if variant_index == -1:
|
||||
variant_index = generated_variants.size()
|
||||
generated_variants.append(uv)
|
||||
rv.code = src_code.code+"vec3 "+name+"_"+str(variant_index)+"_rgb = mix("+color_to_string(color0)+", "+color_to_string(color1)+", "+get_source_f(src_code)+");\n"
|
||||
rv.f = get_source_f(src_code)
|
||||
rv.code = src_code.code+"vec3 "+name+"_"+str(variant_index)+"_rgb = "+name+"_gradient("+src_code.f+");\n"
|
||||
rv.rgb = name+"_"+str(variant_index)+"_rgb"
|
||||
return rv
|
||||
|
||||
func _get_state_variables():
|
||||
return [ "color0", "color1" ]
|
||||
func serialize():
|
||||
var data = .serialize()
|
||||
data.gradient = $Control.serialize()
|
||||
return data
|
||||
|
||||
func deserialize(data):
|
||||
$Control.deserialize(data.gradient)
|
||||
.deserialize(data)
|
||||
|
@ -1,7 +1,7 @@
|
||||
[gd_scene load_steps=3 format=2]
|
||||
[gd_scene load_steps=4 format=2]
|
||||
|
||||
[ext_resource path="res://addons/procedural_material/nodes/colorize.gd" type="Script" id=1]
|
||||
|
||||
[ext_resource path="res://addons/procedural_material/widgets/gradient_editor.tscn" type="PackedScene" id=2]
|
||||
|
||||
[sub_resource type="Theme" id=1]
|
||||
|
||||
@ -14,8 +14,8 @@ anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 1.0
|
||||
margin_top = 4.0
|
||||
margin_right = 98.0
|
||||
margin_bottom = 74.0
|
||||
margin_right = 133.0
|
||||
margin_bottom = 63.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 1
|
||||
@ -36,71 +36,18 @@ slot/0/left_color = Color( 0.5, 0.5, 1, 1 )
|
||||
slot/0/right_enabled = true
|
||||
slot/0/right_type = 0
|
||||
slot/0/right_color = Color( 0.5, 0.5, 1, 1 )
|
||||
slot/1/left_enabled = false
|
||||
slot/1/left_type = 0
|
||||
slot/1/left_color = Color( 1, 1, 1, 1 )
|
||||
slot/1/right_enabled = false
|
||||
slot/1/right_type = 0
|
||||
slot/1/right_color = Color( 1, 1, 1, 1 )
|
||||
script = ExtResource( 1 )
|
||||
_sections_unfolded = [ "Theme" ]
|
||||
|
||||
[node name="color0" type="ColorPickerButton" parent="." index="0"]
|
||||
[node name="Control" parent="." index="0" instance=ExtResource( 2 )]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 16.0
|
||||
margin_top = 24.0
|
||||
margin_right = 81.0
|
||||
margin_bottom = 44.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
focus_mode = 2
|
||||
mouse_filter = 0
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
group = null
|
||||
text = "0"
|
||||
flat = false
|
||||
align = 1
|
||||
color = Color( 0, 0, 0, 1 )
|
||||
edit_alpha = true
|
||||
_sections_unfolded = [ "Caret", "Placeholder" ]
|
||||
|
||||
[node name="color1" type="ColorPickerButton" parent="." index="1"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 16.0
|
||||
margin_top = 44.0
|
||||
margin_right = 81.0
|
||||
margin_bottom = 64.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
focus_mode = 2
|
||||
mouse_filter = 0
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
toggle_mode = false
|
||||
enabled_focus_mode = 2
|
||||
shortcut = null
|
||||
group = null
|
||||
text = "0"
|
||||
flat = false
|
||||
align = 1
|
||||
color = Color( 1, 1, 1, 1 )
|
||||
edit_alpha = true
|
||||
_sections_unfolded = [ "Caret", "Placeholder" ]
|
||||
margin_right = 136.0
|
||||
margin_bottom = 54.0
|
||||
|
||||
[connection signal="close_request" from="." to="." method="queue_free"]
|
||||
|
||||
[connection signal="updated" from="Control" to="." method="update_shaders"]
|
||||
|
||||
|
||||
|
@ -39,3 +39,12 @@ func _on_TextureButton_pressed():
|
||||
dialog.add_filter("*.jpg;JPG image")
|
||||
dialog.connect("file_selected", self, "set_texture")
|
||||
dialog.popup_centered()
|
||||
|
||||
func serialize():
|
||||
var data = .serialize()
|
||||
data.file_path = file_path
|
||||
return data
|
||||
|
||||
func deserialize(data):
|
||||
set_texture(data.file_path)
|
||||
.deserialize(data)
|
||||
|
@ -6,7 +6,7 @@
|
||||
[sub_resource type="Theme" id=1]
|
||||
|
||||
|
||||
[node name="Image" type="GraphNode"]
|
||||
[node name="Image" type="GraphNode" index="0"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
|
@ -1,22 +0,0 @@
|
||||
tool
|
||||
extends "res://addons/procedural_material/node_base.gd"
|
||||
|
||||
var subdivide
|
||||
var u
|
||||
var v
|
||||
|
||||
func _ready():
|
||||
set_slot(0, false, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1))
|
||||
initialize_properties([ $GridContainer/subdivide, $GridContainer/u, $GridContainer/v ])
|
||||
|
||||
func _get_shader_code(uv):
|
||||
var rv = { defs="", code="" }
|
||||
if generated_variants.empty():
|
||||
rv.defs = "float "+name+"_f(vec2 uv) { return iqnoise(uv, "+str(subdivide)+", "+str(u)+", "+str(v)+"); }\n"
|
||||
var variant_index = generated_variants.find(uv)
|
||||
if variant_index == -1:
|
||||
variant_index = generated_variants.size()
|
||||
generated_variants.append(uv)
|
||||
rv.code = "float "+name+"_"+str(variant_index)+"_f = "+name+"_f("+uv+");\n"
|
||||
rv.f = name+"_"+str(variant_index)+"_f"
|
||||
return rv
|
@ -1,198 +0,0 @@
|
||||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://addons/procedural_material/nodes/iqnoise.gd" type="Script" id=1]
|
||||
|
||||
[sub_resource type="Theme" id=1]
|
||||
|
||||
|
||||
[node name="IQNoise" type="GraphNode" index="0"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 1.0
|
||||
margin_top = 2.0
|
||||
margin_right = 161.0
|
||||
margin_bottom = 111.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 1
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
theme = SubResource( 1 )
|
||||
title = "IQNoise"
|
||||
offset = Vector2( 0, 0 )
|
||||
show_close = true
|
||||
resizable = false
|
||||
selected = false
|
||||
comment = false
|
||||
overlay = 0
|
||||
slot/0/left_enabled = false
|
||||
slot/0/left_type = 0
|
||||
slot/0/left_color = Color( 0.5, 0.5, 1, 1 )
|
||||
slot/0/right_enabled = true
|
||||
slot/0/right_type = 0
|
||||
slot/0/right_color = Color( 0.5, 0.5, 1, 1 )
|
||||
script = ExtResource( 1 )
|
||||
_sections_unfolded = [ "Theme" ]
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="." index="0"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 16.0
|
||||
margin_top = 24.0
|
||||
margin_right = 144.0
|
||||
margin_bottom = 104.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 1
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
columns = 2
|
||||
|
||||
[node name="Label1" type="Label" parent="GridContainer" index="0"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_top = 5.0
|
||||
margin_right = 66.0
|
||||
margin_bottom = 19.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 = "Subdivide:"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="subdivide" type="LineEdit" parent="GridContainer" index="1"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 70.0
|
||||
margin_right = 128.0
|
||||
margin_bottom = 24.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
focus_mode = 2
|
||||
mouse_filter = 0
|
||||
mouse_default_cursor_shape = 1
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
text = "8"
|
||||
focus_mode = 2
|
||||
context_menu_enabled = true
|
||||
placeholder_alpha = 0.6
|
||||
caret_blink = false
|
||||
caret_blink_speed = 0.65
|
||||
caret_position = 0
|
||||
_sections_unfolded = [ "Caret", "Placeholder" ]
|
||||
|
||||
[node name="Label2" type="Label" parent="GridContainer" index="2"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_top = 33.0
|
||||
margin_right = 66.0
|
||||
margin_bottom = 47.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 = "U:"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="u" type="LineEdit" parent="GridContainer" index="3"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 70.0
|
||||
margin_top = 28.0
|
||||
margin_right = 128.0
|
||||
margin_bottom = 52.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
focus_mode = 2
|
||||
mouse_filter = 0
|
||||
mouse_default_cursor_shape = 1
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
text = "0.5"
|
||||
focus_mode = 2
|
||||
context_menu_enabled = true
|
||||
placeholder_alpha = 0.6
|
||||
caret_blink = false
|
||||
caret_blink_speed = 0.65
|
||||
caret_position = 0
|
||||
_sections_unfolded = [ "Caret", "Placeholder" ]
|
||||
|
||||
[node name="Label3" type="Label" parent="GridContainer" index="4"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_top = 61.0
|
||||
margin_right = 66.0
|
||||
margin_bottom = 75.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 = "V:"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
|
||||
[node name="v" type="LineEdit" parent="GridContainer" index="5"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 70.0
|
||||
margin_top = 56.0
|
||||
margin_right = 128.0
|
||||
margin_bottom = 80.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
focus_mode = 2
|
||||
mouse_filter = 0
|
||||
mouse_default_cursor_shape = 1
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
text = "0.5"
|
||||
focus_mode = 2
|
||||
context_menu_enabled = true
|
||||
placeholder_alpha = 0.6
|
||||
caret_blink = false
|
||||
caret_blink_speed = 0.65
|
||||
caret_position = 0
|
||||
_sections_unfolded = [ "Caret", "Placeholder" ]
|
||||
|
||||
[connection signal="close_request" from="." to="." method="queue_free"]
|
||||
|
||||
|
@ -33,12 +33,12 @@ slot/0/left_color = Color( 0.5, 0.5, 1, 1 )
|
||||
slot/0/right_enabled = false
|
||||
slot/0/right_type = 0
|
||||
slot/0/right_color = Color( 0.5, 0.5, 1, 1 )
|
||||
slot/1/left_enabled = false
|
||||
slot/1/left_enabled = true
|
||||
slot/1/left_type = 0
|
||||
slot/1/left_color = Color( 1, 1, 1, 1 )
|
||||
slot/1/left_color = Color( 0.5, 0.5, 1, 1 )
|
||||
slot/1/right_enabled = false
|
||||
slot/1/right_type = 0
|
||||
slot/1/right_color = Color( 1, 1, 1, 1 )
|
||||
slot/1/right_color = Color( 0.5, 0.5, 1, 1 )
|
||||
script = ExtResource( 1 )
|
||||
_sections_unfolded = [ "Theme" ]
|
||||
|
||||
|
@ -13,7 +13,7 @@ func _ready():
|
||||
func _get_shader_code(uv):
|
||||
var rv = { defs="", code="" }
|
||||
if generated_variants.empty():
|
||||
rv.defs = "float "+name+"_f(vec2 uv) { return perlin(uv, vec2("+str(scale_x)+", "+str(scale_y)+"), "+str(iterations)+", "+str(persistance)+"); }\n"
|
||||
rv.defs = "float "+name+"_f(vec2 uv) { return perlin(uv, vec2(%f, %f), %d, %.9f, %d); }\n" % [ scale_x, scale_y, iterations, persistance, get_seed() ]
|
||||
var variant_index = generated_variants.find(uv)
|
||||
if variant_index == -1:
|
||||
variant_index = generated_variants.size()
|
||||
@ -21,3 +21,6 @@ func _get_shader_code(uv):
|
||||
rv.code = "float "+name+"_"+str(variant_index)+"_f = "+name+"_f("+uv+");\n"
|
||||
rv.f = name+"_"+str(variant_index)+"_f"
|
||||
return rv
|
||||
|
||||
func _on_offset_changed():
|
||||
update_shaders()
|
||||
|
@ -5,7 +5,7 @@
|
||||
[sub_resource type="Theme" id=1]
|
||||
|
||||
|
||||
[node name="Perlin" type="GraphNode" index="0"]
|
||||
[node name="Perlin" type="GraphNode"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
@ -249,4 +249,6 @@ _sections_unfolded = [ "Caret", "Placeholder" ]
|
||||
|
||||
[connection signal="close_request" from="." to="." method="queue_free"]
|
||||
|
||||
[connection signal="offset_changed" from="." to="." method="_on_offset_changed"]
|
||||
|
||||
|
||||
|
@ -16,7 +16,7 @@ func _get_shader_code(uv):
|
||||
rv.uv = name+"_uv("+uv+")"
|
||||
var src_code = src.get_shader_code(rv.uv)
|
||||
if !generated:
|
||||
rv.defs = src_code.defs+"vec2 "+name+"_uv(vec2 uv) { return transform(uv, "+str(3.1415928*rotate/180.0)+", "+str(scale)+"); }\n"
|
||||
rv.defs = src_code.defs+"vec2 "+name+"_uv(vec2 uv) { return transform(uv, %.9f, %.9f); }\n" % [ 3.1415928*rotate/180.0, scale ]
|
||||
generated = true
|
||||
rv.code = src_code.code;
|
||||
if src_code.has("f"):
|
||||
|
25
addons/procedural_material/nodes/voronoi.gd
Normal file
25
addons/procedural_material/nodes/voronoi.gd
Normal file
@ -0,0 +1,25 @@
|
||||
tool
|
||||
extends "res://addons/procedural_material/node_base.gd"
|
||||
|
||||
var scale_x
|
||||
var scale_y
|
||||
var intensity
|
||||
|
||||
func _ready():
|
||||
set_slot(0, false, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1))
|
||||
initialize_properties([ $HBoxContainer1/scale_x, $HBoxContainer2/scale_y, $HBoxContainer3/intensity ])
|
||||
|
||||
func _get_shader_code(uv):
|
||||
var rv = { defs="", code="" }
|
||||
if generated_variants.empty():
|
||||
rv.defs = "vec4 "+name+"_xyzw(vec2 uv) { return voronoi(uv, vec2(%f, %f), %.9f, %d); }\n" % [ scale_x, scale_y, intensity, get_seed() ]
|
||||
var variant_index = generated_variants.find(uv)
|
||||
if variant_index == -1:
|
||||
variant_index = generated_variants.size()
|
||||
generated_variants.append(uv)
|
||||
rv.code = "vec4 "+name+"_"+str(variant_index)+"_xyzw = "+name+"_xyzw("+uv+");\n"
|
||||
rv.f = name+"_"+str(variant_index)+"_xyzw.z"
|
||||
return rv
|
||||
|
||||
func _on_offset_changed():
|
||||
update_shaders()
|
256
addons/procedural_material/nodes/voronoi.tscn
Normal file
256
addons/procedural_material/nodes/voronoi.tscn
Normal file
@ -0,0 +1,256 @@
|
||||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://addons/procedural_material/nodes/voronoi.gd" type="Script" id=1]
|
||||
|
||||
[sub_resource type="Theme" id=1]
|
||||
|
||||
|
||||
[node name="Voronoi" type="GraphNode" index="0"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 1.0
|
||||
margin_top = 2.0
|
||||
margin_right = 172.0
|
||||
margin_bottom = 105.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 1
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
theme = SubResource( 1 )
|
||||
title = "Voronoi"
|
||||
offset = Vector2( 0, 0 )
|
||||
show_close = true
|
||||
resizable = false
|
||||
selected = false
|
||||
comment = false
|
||||
overlay = 0
|
||||
slot/0/left_enabled = false
|
||||
slot/0/left_type = 0
|
||||
slot/0/left_color = Color( 0.5, 0.5, 1, 1 )
|
||||
slot/0/right_enabled = true
|
||||
slot/0/right_type = 0
|
||||
slot/0/right_color = Color( 0.5, 0.5, 1, 1 )
|
||||
slot/1/left_enabled = false
|
||||
slot/1/left_type = 0
|
||||
slot/1/left_color = Color( 1, 1, 1, 1 )
|
||||
slot/1/right_enabled = false
|
||||
slot/1/right_type = 0
|
||||
slot/1/right_color = Color( 1, 1, 1, 1 )
|
||||
slot/2/left_enabled = false
|
||||
slot/2/left_type = 0
|
||||
slot/2/left_color = Color( 1, 1, 1, 1 )
|
||||
slot/2/right_enabled = false
|
||||
slot/2/right_type = 0
|
||||
slot/2/right_color = Color( 1, 1, 1, 1 )
|
||||
script = ExtResource( 1 )
|
||||
_sections_unfolded = [ "Theme" ]
|
||||
|
||||
[node name="HBoxContainer1" type="HBoxContainer" parent="." index="0"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 16.0
|
||||
margin_top = 24.0
|
||||
margin_right = 155.0
|
||||
margin_bottom = 48.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 1
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 1
|
||||
alignment = 0
|
||||
_sections_unfolded = [ "Size Flags" ]
|
||||
|
||||
[node name="Label1" type="Label" parent="HBoxContainer1" index="0"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_top = 5.0
|
||||
margin_right = 61.0
|
||||
margin_bottom = 19.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 2
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 4
|
||||
text = "Scale X:"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
_sections_unfolded = [ "Anchor", "Size Flags" ]
|
||||
|
||||
[node name="scale_x" type="SpinBox" parent="HBoxContainer1" index="1"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 65.0
|
||||
margin_right = 139.0
|
||||
margin_bottom = 24.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 8
|
||||
size_flags_vertical = 1
|
||||
min_value = 0.0
|
||||
max_value = 32.0
|
||||
step = 1.0
|
||||
page = 0.0
|
||||
value = 4.0
|
||||
exp_edit = false
|
||||
rounded = false
|
||||
editable = true
|
||||
prefix = ""
|
||||
suffix = ""
|
||||
_sections_unfolded = [ "Anchor", "Caret", "Focus", "Grow Direction", "Hint", "Margin", "Mouse", "Placeholder", "Rect", "Size Flags" ]
|
||||
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="." index="1"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 16.0
|
||||
margin_top = 48.0
|
||||
margin_right = 155.0
|
||||
margin_bottom = 72.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 1
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
alignment = 0
|
||||
|
||||
[node name="Label2" type="Label" parent="HBoxContainer2" index="0"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_top = 5.0
|
||||
margin_right = 61.0
|
||||
margin_bottom = 19.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 2
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 4
|
||||
text = "Scale Y:"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
_sections_unfolded = [ "Size Flags" ]
|
||||
|
||||
[node name="scale_y" type="SpinBox" parent="HBoxContainer2" index="1"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 65.0
|
||||
margin_right = 139.0
|
||||
margin_bottom = 24.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 8
|
||||
size_flags_vertical = 1
|
||||
min_value = 0.0
|
||||
max_value = 32.0
|
||||
step = 1.0
|
||||
page = 0.0
|
||||
value = 4.0
|
||||
exp_edit = false
|
||||
rounded = false
|
||||
editable = true
|
||||
prefix = ""
|
||||
suffix = ""
|
||||
_sections_unfolded = [ "Caret", "Placeholder", "Size Flags" ]
|
||||
|
||||
[node name="HBoxContainer3" type="HBoxContainer" 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 = 73.0
|
||||
margin_right = 155.0
|
||||
margin_bottom = 97.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 1
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 1
|
||||
size_flags_vertical = 1
|
||||
alignment = 0
|
||||
|
||||
[node name="Label3" type="Label" parent="HBoxContainer3" index="0"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_top = 5.0
|
||||
margin_right = 61.0
|
||||
margin_bottom = 19.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 2
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 4
|
||||
text = "Intensity:"
|
||||
percent_visible = 1.0
|
||||
lines_skipped = 0
|
||||
max_lines_visible = -1
|
||||
_sections_unfolded = [ "Size Flags" ]
|
||||
|
||||
[node name="intensity" type="SpinBox" parent="HBoxContainer3" index="1"]
|
||||
|
||||
anchor_left = 0.0
|
||||
anchor_top = 0.0
|
||||
anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 65.0
|
||||
margin_right = 139.0
|
||||
margin_bottom = 24.0
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
mouse_default_cursor_shape = 0
|
||||
size_flags_horizontal = 8
|
||||
size_flags_vertical = 1
|
||||
min_value = 0.0
|
||||
max_value = 3.0
|
||||
step = 0.05
|
||||
page = 0.0
|
||||
value = 1.0
|
||||
exp_edit = false
|
||||
rounded = false
|
||||
editable = true
|
||||
prefix = ""
|
||||
suffix = ""
|
||||
_sections_unfolded = [ "Caret", "Placeholder", "Size Flags" ]
|
||||
|
||||
[connection signal="close_request" from="." to="." method="queue_free"]
|
||||
|
||||
[connection signal="offset_changed" from="." to="." method="_on_offset_changed"]
|
||||
|
||||
|
@ -24,7 +24,7 @@ func _get_shader_code(uv):
|
||||
var src1_code3 = src1.get_shader_code(uv+"-vec2(0.0, 0.01)")
|
||||
rv.defs = src1_code0.defs
|
||||
rv.code = src1_code0.code+src1_code1.code+src1_code2.code+src1_code3.code
|
||||
rv.code += "vec2 "+name+"_"+str(variant_index)+"_uv = "+uv+"+"+str(amount)+"*vec2("+get_source_f(src1_code0)+"-"+get_source_f(src1_code1)+", "+get_source_f(src1_code2)+"-"+get_source_f(src1_code3)+");\n"
|
||||
rv.code += "vec2 "+name+"_"+str(variant_index)+"_uv = "+uv+"+%.9f*vec2((%s)-(%s), (%s)-(%s));\n" % [ amount, src1_code0.f, src1_code1.f, src1_code2.f, src1_code3.f ]
|
||||
var src0_code = src0.get_shader_code(name+"_"+str(variant_index)+"_uv")
|
||||
rv.defs += src0_code.defs
|
||||
rv.code += src0_code.code
|
||||
|
@ -1,6 +1,7 @@
|
||||
tool
|
||||
extends Container
|
||||
|
||||
var popup_menu = null
|
||||
var popup_position = Vector2(0, 0)
|
||||
var selected_node = null
|
||||
|
||||
@ -11,31 +12,52 @@ const MENU = [
|
||||
{ command="load_texture", description="Load texture" },
|
||||
{ command="save_texture", description="Save texture" },
|
||||
{ command="export_texture", description="Export texture" },
|
||||
{ name="image", description="Image" },
|
||||
{ name="sine", description="Sine" },
|
||||
{ name="bricks", description="Bricks" },
|
||||
{ name="iqnoise", description="IQ Noise" },
|
||||
{ name="perlin", description="Perlin noise" },
|
||||
{ name="transform", description="Transform" },
|
||||
{ name="warp", description="Warp" },
|
||||
{ name="colorize", description="Colorize" },
|
||||
{ name="normal_map", description="Normal Map" },
|
||||
{ name="blend", description="Blend" }
|
||||
{ submenu="generator", description="Generator" },
|
||||
{ name="image", description="Image", in_submenu="generator" },
|
||||
{ name="sine", description="Sine", in_submenu="generator" },
|
||||
{ name="bricks", description="Bricks", in_submenu="generator" },
|
||||
{ name="perlin", description="Perlin noise", in_submenu="generator" },
|
||||
{ name="voronoi", description="Voronoi Noise", in_submenu="generator" },
|
||||
{ submenu="filter", description="Filter" },
|
||||
{ name="colorize", description="Colorize", in_submenu="filter" },
|
||||
{ name="blend", description="Blend", in_submenu="filter" },
|
||||
{ name="transform", description="Transform", in_submenu="filter" },
|
||||
{ name="warp", description="Warp", in_submenu="filter" },
|
||||
{ name="normal_map", description="Normal Map", in_submenu="filter" }
|
||||
]
|
||||
|
||||
func _ready():
|
||||
# Duplicate the material we'll modify and store the shaders
|
||||
preview_material = $Container/ViewportContainer/MaterialPreview.material
|
||||
$Container/ViewportContainer/SelectedPreview.material = $Container/ViewportContainer/SelectedPreview.material.duplicate(true)
|
||||
texture_preview_material = $Container/ViewportContainer/SelectedPreview.material
|
||||
preview_material = $Preview/ViewportContainer/MaterialPreview.material
|
||||
$Preview/ViewportContainer/SelectedPreview.material = $Preview/ViewportContainer/SelectedPreview.material.duplicate(true)
|
||||
texture_preview_material = $Preview/ViewportContainer/SelectedPreview.material
|
||||
$GraphEdit.add_valid_connection_type(0, 0)
|
||||
$GraphEdit/PopupMenu.clear()
|
||||
# create or update popup menu
|
||||
if popup_menu != null:
|
||||
popup_menu.queue_free()
|
||||
popup_menu = create_menu()
|
||||
$GraphEdit.add_child(popup_menu)
|
||||
|
||||
func create_menu(in_submenu = null):
|
||||
var menu = PopupMenu.new()
|
||||
menu.connect("id_pressed", self, "_on_PopupMenu_id_pressed")
|
||||
for i in MENU.size():
|
||||
$GraphEdit/PopupMenu.add_item(MENU[i].description, i)
|
||||
if MENU[i].has("in_submenu"):
|
||||
if in_submenu != MENU[i].in_submenu:
|
||||
continue
|
||||
elif in_submenu != null:
|
||||
continue
|
||||
if MENU[i].has("submenu"):
|
||||
var submenu = create_menu(MENU[i].submenu)
|
||||
menu.add_child(submenu)
|
||||
menu.add_submenu_item(MENU[i].description, submenu.get_name())
|
||||
else:
|
||||
menu.add_item(MENU[i].description, i)
|
||||
return menu
|
||||
|
||||
func _on_GraphEdit_popup_request(position):
|
||||
popup_position = position
|
||||
$GraphEdit/PopupMenu.popup(Rect2(position, $GraphEdit/PopupMenu.rect_size))
|
||||
popup_menu.popup(Rect2(position, popup_menu.rect_size))
|
||||
|
||||
func _on_PopupMenu_id_pressed(id):
|
||||
var node_type = null
|
||||
@ -45,6 +67,13 @@ func _on_PopupMenu_id_pressed(id):
|
||||
node_type = load("res://addons/procedural_material/nodes/"+MENU[id].name+".tscn")
|
||||
if node_type != null:
|
||||
var node = node_type.instance()
|
||||
var i = 0
|
||||
while true:
|
||||
var name = MENU[id].name+"_"+str(i)
|
||||
if !$GraphEdit.has_node(name):
|
||||
node.set_name(name)
|
||||
break
|
||||
i += 1
|
||||
$GraphEdit.add_child(node)
|
||||
node.offset = ($GraphEdit.scroll_offset + popup_position - $GraphEdit.rect_global_position) / $GraphEdit.zoom
|
||||
|
||||
@ -125,7 +154,7 @@ func export_texture():
|
||||
|
||||
func setup_material(shader_material, textures, shader_code):
|
||||
for k in textures.keys():
|
||||
print("Setting param "+k+" to "+str(textures[k]))
|
||||
#print("Setting param "+k+" to "+str(textures[k]))
|
||||
shader_material.set_shader_param(k+"_tex", textures[k])
|
||||
shader_material.shader.code = shader_code
|
||||
|
||||
@ -135,6 +164,7 @@ func generate_shader():
|
||||
setup_material(texture_preview_material, selected_node.get_textures(), $GraphEdit.generate_shader(selected_node))
|
||||
|
||||
func _on_GraphEdit_node_selected(node):
|
||||
selected_node = node
|
||||
setup_material(texture_preview_material, selected_node.get_textures(), $GraphEdit.generate_shader(selected_node))
|
||||
if selected_node != node:
|
||||
selected_node = node
|
||||
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
@ -1,19 +1,16 @@
|
||||
float hash1(vec2 p) {
|
||||
float q = dot(p,vec2(127.1,311.7));
|
||||
return fract(sin(q)*43758.5453);
|
||||
float rand(vec2 x) {
|
||||
return fract(sin(dot(x, vec2(13.9898, 8.141))) * 43758.5453);
|
||||
}
|
||||
|
||||
vec2 hash2(vec2 p) {
|
||||
vec2 q = vec2( dot(p,vec2(127.1,311.7)),
|
||||
dot(p,vec2(269.5,183.3)) );
|
||||
return fract(sin(q)*43758.5453);
|
||||
vec2 rand2(vec2 x) {
|
||||
return fract(sin(vec2(dot(x, vec2(13.9898, 8.141)),
|
||||
dot(x, vec2(3.4562, 17.398)))) * 43758.5453);
|
||||
}
|
||||
|
||||
vec3 hash3(vec2 p) {
|
||||
vec3 q = vec3( dot(p,vec2(127.1,311.7)),
|
||||
dot(p,vec2(269.5,183.3)),
|
||||
dot(p,vec2(419.2,371.9)) );
|
||||
return fract(sin(q)*43758.5453);
|
||||
vec3 rand3(vec2 x) {
|
||||
return fract(sin(vec3(dot(x, vec2(13.9898, 8.141)),
|
||||
dot(x, vec2(3.4562, 17.398)),
|
||||
dot(x, vec2(13.254, 5.867)))) * 43758.5453);
|
||||
}
|
||||
|
||||
float sine(vec2 uv, float count, float sharpness) {
|
||||
@ -51,68 +48,54 @@ float colored_bricks(vec2 uv, vec2 count, float offset) {
|
||||
return fract(x/3.0+y/7.0);
|
||||
}
|
||||
|
||||
float iqnoise(vec2 uv, float s, float u, float v) {
|
||||
uv *= s;
|
||||
vec2 p = floor(uv);
|
||||
vec2 f = fract(uv);
|
||||
|
||||
float k = 1.0+63.0*pow(1.0-v,4.0);
|
||||
|
||||
float va = 0.0;
|
||||
float wt = 0.0;
|
||||
for( int j=-2; j<=2; j++ )
|
||||
for( int i=-2; i<=2; i++ )
|
||||
{
|
||||
vec2 g = vec2( float(i),float(j) );
|
||||
vec3 o = hash3( p + g )*vec3(u,u,1.0);
|
||||
vec2 r = g - f + o.xy;
|
||||
float d = dot(r,r);
|
||||
float ww = pow( 1.0-smoothstep(0.0,1.414,sqrt(d)), k );
|
||||
va += o.z*ww;
|
||||
wt += ww;
|
||||
float perlin(vec2 uv, vec2 size, int iterations, float persistence, int seed) {
|
||||
uv += vec2(float(seed)*0.1234567);
|
||||
float rv = 0.0;
|
||||
float coef = 1.0;
|
||||
float acc = 0.0;
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
vec2 step = vec2(1.0)/size;
|
||||
float f0 = rand(floor(fract(uv)*size));
|
||||
float f1 = rand(floor(fract(uv+vec2(step.x, 0.0))*size));
|
||||
float f2 = rand(floor(fract(uv+vec2(0.0, step.y))*size));
|
||||
float f3 = rand(floor(fract(uv+vec2(step.x, step.y))*size));
|
||||
vec2 mixval = fract(uv*size);
|
||||
mixval = 0.5*(1.0-cos(3.1415928*mixval));
|
||||
rv += coef * mix(mix(f0, f1, mixval.x), mix(f2, f3, mixval.x), mixval.y);
|
||||
acc += coef;
|
||||
size *= 2.0;
|
||||
coef *= persistence;
|
||||
}
|
||||
|
||||
return va/wt;
|
||||
|
||||
return rv / acc;
|
||||
}
|
||||
|
||||
float perlin_old(vec2 uv, vec2 scale, int iterations, float turbulence) {
|
||||
float f = 0.0;
|
||||
float c = 1.0;
|
||||
float m = 0.0;
|
||||
for(int i = 0; i < iterations; i++) {
|
||||
vec2 uv2 = scale * mod(uv, vec2(1.0, 1.0));
|
||||
vec2 uv2_floor = floor(uv2);
|
||||
vec2 uv2_fract = fract(uv2);
|
||||
f += c * ( (1.0 - uv2_fract.x) * ((1.0 - uv2_fract.y) * hash1(uv2_floor) + uv2_fract.y * hash1(uv2_floor+vec2(0.0, 1.0)))
|
||||
+ uv2_fract.x * ((1.0 - uv2_fract.y) * hash1(uv2_floor+vec2(1.0, 0.0)) + uv2_fract.y * hash1(uv2_floor+vec2(1.0, 1.0))));
|
||||
m += c;
|
||||
scale *= 2.0;
|
||||
c *= turbulence;
|
||||
}
|
||||
return f/m;
|
||||
}
|
||||
|
||||
float noise(vec2 p, vec2 freq ){
|
||||
vec2 unit = vec2(1.0)/freq;
|
||||
vec2 ij = floor(p/unit);
|
||||
vec2 xy = mod(p,unit)/unit;
|
||||
float a = hash1((ij+vec2(0.0,0.0)));
|
||||
float b = hash1((ij+vec2(1.0,0.0)));
|
||||
float c = hash1((ij+vec2(0.0,1.0)));
|
||||
float d = hash1((ij+vec2(1.0,1.0)));
|
||||
return mix(mix(a, b, xy.x), mix(c, d, xy.x), xy.y);
|
||||
}
|
||||
|
||||
float perlin(vec2 p, vec2 scale, int iterations, float persistance) {
|
||||
float n = 0.0;
|
||||
float normK = 0.0;
|
||||
vec2 f = scale;
|
||||
float amp = 1.0;
|
||||
for (int i = 0; i<iterations; i++){
|
||||
n += amp*noise(p, f);
|
||||
f*=2.0;
|
||||
normK += amp;
|
||||
amp*=persistance;
|
||||
}
|
||||
return n/normK;
|
||||
vec4 voronoi(vec2 uv, vec2 size, float intensity, int seed) {
|
||||
uv += vec2(float(seed)*0.1234567);
|
||||
uv *= size;
|
||||
float best_distance0 = 1.0;
|
||||
float best_distance1 = 1.0;
|
||||
vec2 point0;
|
||||
vec2 point1;
|
||||
vec2 p0 = floor(uv);
|
||||
for (int dx = -1; dx < 2; ++dx) {
|
||||
for (int dy = -1; dy < 2; ++dy) {
|
||||
vec2 d = vec2(float(dx), float(dy));
|
||||
vec2 p = p0+d;
|
||||
p += rand2(mod(p, size));
|
||||
float distance = length((uv - p) / size);
|
||||
if (best_distance0 > distance) {
|
||||
best_distance1 = best_distance0;
|
||||
best_distance0 = distance;
|
||||
point1 = point0;
|
||||
point0 = p;
|
||||
} else if (best_distance1 > distance) {
|
||||
best_distance1 = distance;
|
||||
point1 = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
float edge_distance = dot(uv - 0.5*(point0+point1), normalize(point0-point1));
|
||||
|
||||
return vec4(point0, best_distance0*length(size)*intensity, edge_distance);
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
tool
|
||||
extends Control
|
||||
|
||||
class GradientCursor:
|
||||
@ -29,6 +30,8 @@ class GradientCursor:
|
||||
return true
|
||||
return false
|
||||
|
||||
signal updated
|
||||
|
||||
func _ready():
|
||||
$Gradient.material = $Gradient.material.duplicate(true)
|
||||
add_cursor(0, Color(0, 0, 0))
|
||||
@ -81,13 +84,13 @@ func get_color(x):
|
||||
|
||||
# get_color_in_shader
|
||||
func gcis(color):
|
||||
return "vec3(%.1f,%.1f,%.1f)" % [color.r, color.g, color.b]
|
||||
return "vec3(%.9f,%.9f,%.9f)" % [color.r, color.g, color.b]
|
||||
|
||||
func get_shader(name):
|
||||
var array = get_sorted_cursors()
|
||||
var shader
|
||||
shader = "vec3 "+name+"(float x) {\n"
|
||||
shader += " if (x < %.1f) {\n" % array[0].get_position()
|
||||
shader += " if (x < %.9f) {\n" % array[0].get_position()
|
||||
shader += " return "+gcis(array[0].color)+";\n"
|
||||
for i in range(array.size()-1):
|
||||
var p0 = array[i].get_position()
|
||||
@ -95,7 +98,7 @@ func get_shader(name):
|
||||
var p1mp0 = array[i+1].get_position()-p0
|
||||
var c1mc0 = array[i+1].color-c0
|
||||
if p1mp0 > 0:
|
||||
shader += " } else if (x < %.1f) {\n" % array[i+1].get_position()
|
||||
shader += " } else if (x < %.9f) {\n" % array[i+1].get_position()
|
||||
shader += " return %s+x*%s;\n" % [gcis(c0-c1mc0*(p0/p1mp0)), gcis(c1mc0/p1mp0)]
|
||||
shader += " }\n"
|
||||
shader += " return "+gcis(array[array.size()-1].color)+";\n"
|
||||
@ -106,8 +109,9 @@ func update_shader():
|
||||
var shader
|
||||
shader = "shader_type canvas_item;\n"
|
||||
shader += get_shader("gradient")
|
||||
shader += "void fragment() { COLOR = vec4(gradient((UV.x-%.1f)*%.1f), 1.0); }" % [ 0.5*GradientCursor.WIDTH/rect_size.x, (rect_size.x-GradientCursor.WIDTH)/rect_size.x ]
|
||||
shader += "void fragment() { COLOR = vec4(gradient((UV.x-%.9f)*%.9f), 1.0); }" % [ float(GradientCursor.WIDTH)*0.5/float(rect_size.x), rect_size.x/(rect_size.x-GradientCursor.WIDTH) ]
|
||||
$Gradient.material.shader.set_code(shader)
|
||||
emit_signal("updated")
|
||||
|
||||
func serialize():
|
||||
var rv = []
|
||||
@ -117,6 +121,7 @@ func serialize():
|
||||
|
||||
func deserialize(v):
|
||||
for c in get_sorted_cursors():
|
||||
queue_free(c)
|
||||
remove_child(c)
|
||||
c.free()
|
||||
for i in v:
|
||||
add_cursor(i.pos*(rect_size.x-GradientCursor.WIDTH), Color(i.r, i.g, i.b))
|
||||
|
@ -33,7 +33,7 @@ margin_left = 24.0
|
||||
margin_top = 14.0
|
||||
margin_right = 144.0
|
||||
margin_bottom = 44.0
|
||||
rect_min_size = Vector2( 100, 30 )
|
||||
rect_min_size = Vector2( 120, 30 )
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
mouse_filter = 0
|
||||
@ -89,8 +89,8 @@ anchor_right = 0.0
|
||||
anchor_bottom = 0.0
|
||||
margin_left = 4.0
|
||||
margin_top = 4.0
|
||||
margin_right = 302.0
|
||||
margin_bottom = 462.0
|
||||
margin_right = 4.0
|
||||
margin_bottom = 4.0
|
||||
rect_scale = Vector2( 0.75, 0.75 )
|
||||
rect_pivot_offset = Vector2( 0, 0 )
|
||||
rect_clip_content = false
|
||||
|
@ -1,14 +0,0 @@
|
||||
tool
|
||||
extends ColorRect
|
||||
|
||||
func _ready():
|
||||
pass
|
||||
|
||||
func _on_gui_input(ev):
|
||||
if ev is InputEventMouseButton && ev.button_index == 1 && ev.doubleclick:
|
||||
var dialog = ColorPicker.new()
|
||||
add_child(dialog)
|
||||
elif ev is InputEventMouseMotion && (ev.button_mask & 1) != 0:
|
||||
rect_position.x += ev.relative.x
|
||||
rect_position.x = min(max(0, rect_position.x), get_parent().rect_size.x-rect_size.x)
|
||||
|
@ -1 +1 @@
|
||||
{"connections":[{"from":"Perlin","from_port":0,"to":"Colorize2","to_port":0},{"from":"Perlin","from_port":0,"to":"Colorize","to_port":0},{"from":"Warp","from_port":0,"to":"Blend","to_port":2},{"from":"Colorize","from_port":0,"to":"Blend","to_port":0},{"from":"Colorize2","from_port":0,"to":"Blend","to_port":1},{"from":"Perlin2","from_port":0,"to":"Warp","to_port":1},{"from":"Blend","from_port":0,"to":"Material","to_port":0},{"from":"Warp","from_port":0,"to":"NormalMap","to_port":0},{"from":"Bricks","from_port":0,"to":"Warp","to_port":0},{"from":"NormalMap","from_port":0,"to":"Material","to_port":1}],"nodes":[{"color0":{"a":1,"b":0,"g":0,"r":1,"type":"Color"},"color1":{"a":1,"b":0.061523,"g":0.461907,"r":0.875,"type":"Color"},"name":"Colorize2","node_position":{"x":120.75943,"y":-319},"type":"colorize"},{"color0":{"a":1,"b":0,"g":0,"r":0,"type":"Color"},"color1":{"a":1,"b":1,"g":1,"r":1,"type":"Color"},"name":"Colorize","node_position":{"x":116.759399,"y":-431},"type":"colorize"},{"amount":0.2,"name":"Warp","node_position":{"x":124,"y":-199},"type":"warp"},{"amount":0.5,"name":"NormalMap","node_position":{"x":310.416809,"y":-124.375488},"type":"normal_map"},{"name":"Material","node_position":{"x":528,"y":-285},"type":"material"},{"iterations":7,"name":"Perlin","node_position":{"x":-149,"y":-455},"persistance":1,"scale_x":8,"scale_y":9,"type":"perlin"},{"iterations":6,"name":"Perlin2","node_position":{"x":-141.24057,"y":-86.125458},"persistance":0.4,"scale_x":4,"scale_y":4,"type":"perlin"},{"bevel":0.1,"columns":3,"mortar":0.1,"name":"Bricks","node_position":{"x":-147.327362,"y":-292.797089},"row_offset":0.5,"rows":6,"type":"bricks"},{"amount":0.5,"name":"Blend","node_position":{"x":326.759399,"y":-306},"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":"Colorize2","to_port":0},{"from":"Perlin2","from_port":0,"to":"Colorize","to_port":0},{"from":"Colorize","from_port":0,"to":"Blend","to_port":0},{"from":"Colorize2","from_port":0,"to":"Blend","to_port":1},{"from":"Warp","from_port":0,"to":"Colorize3","to_port":0},{"from":"Colorize3","from_port":0,"to":"Blend","to_port":2},{"from":"Blend","from_port":0,"to":"Material","to_port":0},{"from":"Warp","from_port":0,"to":"NormalMap","to_port":0},{"from":"NormalMap","from_port":0,"to":"Material","to_port":1}],"nodes":[{"iterations":6,"name":"Perlin","node_position":{"x":254,"y":317},"persistance":0.35,"scale_x":4,"scale_y":4,"type":"perlin"},{"iterations":7,"name":"Perlin2","node_position":{"x":258,"y":-32},"persistance":0.9,"scale_x":8,"scale_y":8,"type":"perlin"},{"name":"Material","node_position":{"x":981,"y":-13},"type":"material"},{"amount":0.4,"name":"Blend","node_position":{"x":803,"y":-23.75},"type":"blend"},{"bevel":0.6,"columns":3,"mortar":0.05,"name":"Bricks","node_position":{"x":260,"y":132},"row_offset":0.5,"rows":6,"type":"bricks"},{"amount":0.5,"name":"Warp","node_position":{"x":504,"y":199.75},"type":"warp"},{"amount":0.5,"name":"NormalMap","node_position":{"x":820,"y":269},"type":"normal_map"},{"gradient":[{"b":0.001994,"g":0.150751,"pos":0,"r":0.382813},{"b":0.001994,"g":0.067447,"pos":1,"r":0.382813}],"name":"Colorize2","node_position":{"x":540,"y":46.25},"type":"colorize"},{"gradient":[{"b":0.299479,"g":0.299479,"pos":0,"r":0.299479},{"b":0.127604,"g":0.127604,"pos":1,"r":0.127604}],"name":"Colorize","node_position":{"x":540,"y":-18.75},"type":"colorize"},{"gradient":[{"b":0,"g":0,"pos":0,"r":0},{"b":1,"g":1,"pos":0.072727,"r":1}],"name":"Colorize3","node_position":{"x":649,"y":136},"type":"colorize"}]}
|
Loading…
Reference in New Issue
Block a user