mirror of
https://github.com/Relintai/material-maker.git
synced 2024-12-23 21:16:54 +01:00
commit
1d53b938de
@ -53,6 +53,9 @@ func toggle_editable() -> bool:
|
||||
func is_template() -> bool:
|
||||
return model != null
|
||||
|
||||
func get_template_name() -> bool:
|
||||
return model
|
||||
|
||||
func is_editable() -> bool:
|
||||
return false
|
||||
|
||||
|
122
addons/material_maker/nodes/tones.mmg
Normal file
122
addons/material_maker/nodes/tones.mmg
Normal file
@ -0,0 +1,122 @@
|
||||
{
|
||||
"name": "levels",
|
||||
"node_position": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"parameters": {
|
||||
"in_max": {
|
||||
"a": 1,
|
||||
"b": 1,
|
||||
"g": 1,
|
||||
"r": 1,
|
||||
"type": "Color"
|
||||
},
|
||||
"in_mid": {
|
||||
"a": 0.5,
|
||||
"b": 0.5,
|
||||
"g": 0.5,
|
||||
"r": 0.5,
|
||||
"type": "Color"
|
||||
},
|
||||
"in_min": {
|
||||
"a": 0,
|
||||
"b": 0,
|
||||
"g": 0,
|
||||
"r": 0,
|
||||
"type": "Color"
|
||||
},
|
||||
"out_max": {
|
||||
"a": 1,
|
||||
"b": 1,
|
||||
"g": 1,
|
||||
"r": 1,
|
||||
"type": "Color"
|
||||
},
|
||||
"out_min": {
|
||||
"a": 0,
|
||||
"b": 0,
|
||||
"g": 0,
|
||||
"r": 0,
|
||||
"type": "Color"
|
||||
}
|
||||
},
|
||||
"shader_model": {
|
||||
"code": "",
|
||||
"global": "vec4 adjust_levels(vec4 input, vec4 in_min, vec4 in_mid, vec4 in_max, vec4 out_min, vec4 out_max) {\n\tinput = clamp((input-in_min)/(in_max-in_min), 0.0, 1.0);\n\tin_mid = (in_mid-in_min)/(in_max-in_min);\n\tvec4 dark = step(in_mid, input);\n\tinput = 0.5*mix(input/(in_mid), 1.0+(input-in_mid)/(1.0-in_mid), dark);\n\treturn out_min+input*(out_max-out_min);\n}\n",
|
||||
"inputs": [
|
||||
{
|
||||
"default": "vec4(1.0)",
|
||||
"label": "",
|
||||
"name": "input",
|
||||
"type": "rgba"
|
||||
}
|
||||
],
|
||||
"instance": "",
|
||||
"name": "Levels",
|
||||
"outputs": [
|
||||
{
|
||||
"rgba": "adjust_levels($input($uv), $in_min, $in_mid, $in_max, $out_min, $out_max)",
|
||||
"type": "rgba"
|
||||
}
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"default": {
|
||||
"a": 0,
|
||||
"b": 0,
|
||||
"g": 0,
|
||||
"r": 0
|
||||
},
|
||||
"label": "",
|
||||
"name": "in_min",
|
||||
"type": "color"
|
||||
},
|
||||
{
|
||||
"default": {
|
||||
"a": 0.498039,
|
||||
"b": 0.498039,
|
||||
"g": 0.498039,
|
||||
"r": 0.498039
|
||||
},
|
||||
"label": "",
|
||||
"name": "in_mid",
|
||||
"type": "color"
|
||||
},
|
||||
{
|
||||
"default": {
|
||||
"a": 1,
|
||||
"b": 1,
|
||||
"g": 1,
|
||||
"r": 1
|
||||
},
|
||||
"label": "",
|
||||
"name": "in_max",
|
||||
"type": "color"
|
||||
},
|
||||
{
|
||||
"default": {
|
||||
"a": 1,
|
||||
"b": 0,
|
||||
"g": 0,
|
||||
"r": 0
|
||||
},
|
||||
"label": "",
|
||||
"name": "out_min",
|
||||
"type": "color"
|
||||
},
|
||||
{
|
||||
"default": {
|
||||
"a": 1,
|
||||
"b": 1,
|
||||
"g": 1,
|
||||
"r": 1
|
||||
},
|
||||
"label": "",
|
||||
"name": "out_max",
|
||||
"type": "color"
|
||||
}
|
||||
]
|
||||
},
|
||||
"type": "shader"
|
||||
}
|
BIN
material_maker/doc/images/node_filter_tones.png
Normal file
BIN
material_maker/doc/images/node_filter_tones.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.7 KiB |
38
material_maker/doc/node_filter_tones.rst
Normal file
38
material_maker/doc/node_filter_tones.rst
Normal file
@ -0,0 +1,38 @@
|
||||
Tones node
|
||||
~~~~~~~~~~
|
||||
|
||||
The **Tones** node provides an easy interface to adjust the tones of its input. It can be applied
|
||||
homogeneously to the R, G and B channels, or separately on R, G, B and A.
|
||||
|
||||
The nodes shows an histogram of all channels of its input, and 3 cursors to modify the input
|
||||
adjustment at the top, and 2 cursors to modify the output adjustment.
|
||||
|
||||
.. image:: images/node_filter_tones.png
|
||||
:align: center
|
||||
|
||||
Inputs
|
||||
++++++
|
||||
|
||||
The **Tones** node requires an RGBA input texture.
|
||||
|
||||
Outputs
|
||||
+++++++
|
||||
|
||||
The **Tones** node provides a single RGBA texture.
|
||||
|
||||
Parameters
|
||||
++++++++++
|
||||
|
||||
At the top of the node, a control can be used to select the active channel (Luminance, Red,
|
||||
Green, Blue and Alpha).
|
||||
|
||||
The button can be used to adjust automatically the Tones to the node's input to obtain better
|
||||
contrast.
|
||||
|
||||
The 3 cursors at the top of the histogram can be used to select the input colors that will be
|
||||
remapped to black (value = 0 for single channel), mid-grey (value = 0.5) and white (value = 1).
|
||||
Values between those defined by cursors are interpolated linearly, and all values are clamped
|
||||
between 0 and 1.
|
||||
|
||||
The 2 bottom cursors define the output color for black (value = 0 for single channel) and
|
||||
white (value = 1).
|
@ -9,6 +9,7 @@ The filter nodes accept one or several inputs and generate one or several images
|
||||
node_filter_invert
|
||||
node_filter_brightness_contrast
|
||||
node_filter_adjust_hsv
|
||||
node_filter_tones
|
||||
node_filter_greyscale
|
||||
node_filter_colorize
|
||||
node_filter_combine
|
||||
|
@ -166,7 +166,7 @@ func clear_material() -> void:
|
||||
func update_graph(generators, connections) -> Array:
|
||||
var rv = []
|
||||
for g in generators:
|
||||
var node = node_factory.create_node(g.get_type())
|
||||
var node = node_factory.create_node(g.get_template_name() if g.is_template() else "", g.get_type())
|
||||
if node != null:
|
||||
node.name = "node_"+g.name
|
||||
add_node(node)
|
||||
|
@ -55,9 +55,9 @@
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="40.459032"
|
||||
inkscape:cx="12.31719"
|
||||
inkscape:cy="41.781829"
|
||||
inkscape:zoom="7.152214"
|
||||
inkscape:cx="122.70346"
|
||||
inkscape:cy="36.247815"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="true"
|
||||
@ -605,5 +605,42 @@
|
||||
sodipodi:end="0.0018129957"
|
||||
sodipodi:open="true"
|
||||
d="m 15.411452,304.10377 a 7.4148879,7.4346347 0 0 1 -7.4502054,7.39166 7.4148879,7.4346347 0 0 1 -7.37939334,-7.46273 7.4148879,7.4346347 0 0 1 7.43561054,-7.40642 7.4148879,7.4346347 0 0 1 7.3941002,7.44808" />
|
||||
<rect
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.85721886;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
|
||||
id="rect908"
|
||||
width="2.8650246"
|
||||
height="9.0406466"
|
||||
x="16.686302"
|
||||
y="302.37292"
|
||||
ry="0" />
|
||||
<rect
|
||||
ry="0"
|
||||
y="297.67682"
|
||||
x="20.606815"
|
||||
height="13.736778"
|
||||
width="2.8650253"
|
||||
id="rect910"
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#4e4e4e;stroke-width:0.85721886;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||
<rect
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#a9a9a9;stroke-width:0.85721886;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
|
||||
id="rect912"
|
||||
width="2.8650246"
|
||||
height="11.116821"
|
||||
x="24.527328"
|
||||
y="300.29675"
|
||||
ry="0" />
|
||||
<rect
|
||||
ry="0"
|
||||
y="304.64682"
|
||||
x="28.447844"
|
||||
height="6.7667418"
|
||||
width="2.8650246"
|
||||
id="rect914"
|
||||
style="opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.85721886;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
id="path4598-6-2"
|
||||
d="m 23.868329,296.57635 -1.921422,2.02005 -1.696117,-2.29125 a 5.4420629,5.5494302 0 0 0 -1.121274,0.45417 l 0.351782,2.79921 -2.800271,-0.0759 a 5.4420629,5.5494302 0 0 0 -0.336482,1.1114 5.4420629,5.5494302 0 0 0 -0.01172,0.0755 l 2.348852,1.45452 -1.783847,2.16058 a 5.4420629,5.5494302 0 0 0 0.705845,1.02986 l 2.546602,-0.95339 0.540183,2.74829 a 5.4420629,5.5494302 0 0 0 1.239119,0.0834 l 0.851353,-2.6077 2.440798,1.2812 a 5.4420629,5.5494302 0 0 0 0.843823,-0.92816 l -1.472574,-2.31072 2.525556,-1.15689 a 5.4420629,5.5494302 0 0 0 -0.176525,-1.23851 l -2.720271,-0.26982 0.695042,-2.76445 a 5.4420629,5.5494302 0 0 0 -1.048452,-0.62144 z m -1.905851,3.7062 a 1.3605156,1.3873574 0 0 1 1.075273,1.62703 1.3605156,1.3873574 0 0 1 -1.595552,1.09649 1.3605156,1.3873574 0 0 1 -1.075275,-1.62703 1.3605156,1.3873574 0 0 1 1.595554,-1.09649 z"
|
||||
style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.34617221;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 42 KiB |
@ -2289,6 +2289,50 @@
|
||||
"tree_item": "Filter/AdjustHSV",
|
||||
"type": "adjust_hsv"
|
||||
},
|
||||
{
|
||||
"collapsed": true,
|
||||
"icon": "filter_tones",
|
||||
"name": "tones",
|
||||
"parameters": {
|
||||
"in_max": {
|
||||
"a": 1,
|
||||
"b": 1,
|
||||
"g": 1,
|
||||
"r": 1,
|
||||
"type": "Color"
|
||||
},
|
||||
"in_mid": {
|
||||
"a": 0.5,
|
||||
"b": 0.5,
|
||||
"g": 0.5,
|
||||
"r": 0.5,
|
||||
"type": "Color"
|
||||
},
|
||||
"in_min": {
|
||||
"a": 0,
|
||||
"b": 0,
|
||||
"g": 0,
|
||||
"r": 0,
|
||||
"type": "Color"
|
||||
},
|
||||
"out_max": {
|
||||
"a": 1,
|
||||
"b": 1,
|
||||
"g": 1,
|
||||
"r": 1,
|
||||
"type": "Color"
|
||||
},
|
||||
"out_min": {
|
||||
"a": 0,
|
||||
"b": 0,
|
||||
"g": 0,
|
||||
"r": 0,
|
||||
"type": "Color"
|
||||
}
|
||||
},
|
||||
"tree_item": "Filter/Tones",
|
||||
"type": "tones"
|
||||
},
|
||||
{
|
||||
"collapsed": true,
|
||||
"icon": "filter_greyscale",
|
||||
|
BIN
material_maker/library/base/filter_tones.png
Normal file
BIN
material_maker/library/base/filter_tones.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 776 B |
@ -462,7 +462,7 @@ func make_selected_nodes_editable() -> void:
|
||||
var selected_nodes = get_selected_nodes()
|
||||
if !selected_nodes.empty():
|
||||
for n in selected_nodes:
|
||||
if n.generator.toggle_editable():
|
||||
if n.generator.toggle_editable() and n.has_method("update_node"):
|
||||
n.update_node()
|
||||
|
||||
func add_to_user_library() -> void:
|
||||
|
@ -2,13 +2,16 @@ extends Node
|
||||
|
||||
var includes
|
||||
|
||||
func create_node(type) -> Node:
|
||||
func create_node(model : String, type : String) -> Node:
|
||||
var node_type = null
|
||||
var node = null
|
||||
var file_name = "res://material_maker/nodes/"+type+".tscn"
|
||||
var file_name = "res://material_maker/nodes/"+model+".tscn"
|
||||
if ! ResourceLoader.exists(file_name):
|
||||
file_name = "res://material_maker/nodes/"+type+".tscn"
|
||||
if ResourceLoader.exists(file_name):
|
||||
var node_type = load(file_name)
|
||||
if node_type != null:
|
||||
node = node_type.instance()
|
||||
node_type = load(file_name)
|
||||
if node_type != null:
|
||||
node = node_type.instance()
|
||||
if node == null:
|
||||
node = preload("res://material_maker/nodes/generic.tscn").instance()
|
||||
return node
|
||||
|
170
material_maker/nodes/tones.gd
Normal file
170
material_maker/nodes/tones.gd
Normal file
@ -0,0 +1,170 @@
|
||||
extends MMGraphNodeBase
|
||||
|
||||
class Cursor:
|
||||
extends Control
|
||||
|
||||
var color : Color
|
||||
var top : bool = true
|
||||
var position : float
|
||||
|
||||
const WIDTH : int = 8
|
||||
const HEIGHT : int = 8
|
||||
|
||||
func _init(c, p, t = true):
|
||||
color = c
|
||||
position = p
|
||||
top = t
|
||||
|
||||
func _ready() -> void:
|
||||
rect_position.y = -2 if top else get_parent().rect_size.y+2-HEIGHT
|
||||
set_value(position)
|
||||
rect_size = Vector2(WIDTH, HEIGHT)
|
||||
|
||||
func _draw() -> void:
|
||||
var polygon : PoolVector2Array
|
||||
if top:
|
||||
polygon = PoolVector2Array([Vector2(0, 0), Vector2(WIDTH/2, HEIGHT), Vector2(WIDTH, 0), Vector2(0, 0)])
|
||||
else:
|
||||
polygon = PoolVector2Array([Vector2(0, HEIGHT), Vector2(WIDTH/2, 0), Vector2(WIDTH, HEIGHT), Vector2(0, HEIGHT)])
|
||||
var c = color
|
||||
c.a = 1.0
|
||||
draw_colored_polygon(polygon, c)
|
||||
var outline_color = 0.0 if position > 0.5 else 1.0
|
||||
draw_polyline(polygon, Color(outline_color, outline_color, outline_color), 1.0, true)
|
||||
|
||||
func _gui_input(ev) -> void:
|
||||
if ev is InputEventMouseMotion && (ev.button_mask & 1) != 0:
|
||||
rect_position.x += ev.relative.x
|
||||
rect_position.x = min(max(-0.5*WIDTH, rect_position.x), get_parent().rect_size.x-0.5*WIDTH)
|
||||
update_value((rect_position.x+0.5*WIDTH)/get_parent().rect_size.x)
|
||||
|
||||
func update_value(p : float) -> void:
|
||||
if p != position:
|
||||
set_value(p)
|
||||
get_parent().get_parent().update_value(self, position)
|
||||
update()
|
||||
|
||||
func set_value(v : float):
|
||||
position = v
|
||||
rect_position.x = position * get_parent().rect_size.x - 0.5*WIDTH
|
||||
|
||||
var cursor_in_min : Cursor
|
||||
var cursor_in_mid : Cursor
|
||||
var cursor_in_max : Cursor
|
||||
var cursor_out_min : Cursor
|
||||
var cursor_out_max : Cursor
|
||||
|
||||
func _ready() -> void:
|
||||
var slot_color = mm_io_types.types["rgba"].color
|
||||
var slot_type = mm_io_types.types["rgba"].slot_type
|
||||
set_slot(0, true, slot_type, slot_color, true, slot_type, slot_color)
|
||||
cursor_in_min = Cursor.new(Color(0.0, 0.0, 0.0), 0.0)
|
||||
$Histogram.add_child(cursor_in_min)
|
||||
cursor_in_mid = Cursor.new(Color(0.5, 0.5, 0.5), 0.5)
|
||||
$Histogram.add_child(cursor_in_mid)
|
||||
cursor_in_max = Cursor.new(Color(1.0, 1.0, 1.0), 1.0)
|
||||
$Histogram.add_child(cursor_in_max)
|
||||
cursor_out_min = Cursor.new(Color(0.0, 0.0, 0.0), 0.0, false)
|
||||
$Histogram.add_child(cursor_out_min)
|
||||
cursor_out_max = Cursor.new(Color(1.0, 1.0, 1.0), 1.0, false)
|
||||
$Histogram.add_child(cursor_out_max)
|
||||
|
||||
func set_generator(g) -> void:
|
||||
.set_generator(g)
|
||||
generator.connect("parameter_changed", self, "on_parameter_changed")
|
||||
_on_Mode_item_selected(0)
|
||||
|
||||
func on_parameter_changed(p, v) -> void:
|
||||
if p == "__input_changed__":
|
||||
var source = generator.get_source(0)
|
||||
var result = source.generator.render(source.output_index, 128, true)
|
||||
while result is GDScriptFunctionState:
|
||||
result = yield(result, "completed")
|
||||
result.copy_to_texture($Histogram.get_image_texture())
|
||||
result.release()
|
||||
|
||||
func get_parameter(n : String) -> float:
|
||||
var value = generator.get_parameter(n)
|
||||
match $Bar/Mode.selected:
|
||||
1:
|
||||
return value.r
|
||||
2:
|
||||
return value.g
|
||||
3:
|
||||
return value.b
|
||||
4:
|
||||
return value.a
|
||||
return (value.r+value.g+value.b)/3.0
|
||||
|
||||
func _on_Mode_item_selected(_id):
|
||||
cursor_in_min.set_value(get_parameter("in_min"))
|
||||
cursor_in_mid.set_value(get_parameter("in_mid"))
|
||||
cursor_in_max.set_value(get_parameter("in_max"))
|
||||
cursor_out_min.set_value(get_parameter("out_min"))
|
||||
cursor_out_max.set_value(get_parameter("out_max"))
|
||||
|
||||
func set_parameter(n : String, v : float, d : float) -> void:
|
||||
var value = generator.get_parameter(n)
|
||||
match $Bar/Mode.selected:
|
||||
0:
|
||||
value.r = v
|
||||
value.g = v
|
||||
value.b = v
|
||||
value.a = d
|
||||
1:
|
||||
value.r = v
|
||||
2:
|
||||
value.g = v
|
||||
3:
|
||||
value.b = v
|
||||
4:
|
||||
value.a = v
|
||||
generator.set_parameter(n, value)
|
||||
|
||||
func update_value(control : Cursor, value : float) -> void:
|
||||
match control:
|
||||
cursor_in_min:
|
||||
set_parameter("in_min", value, 0)
|
||||
cursor_in_mid:
|
||||
set_parameter("in_mid", value, 0.5)
|
||||
cursor_in_max:
|
||||
set_parameter("in_max", value, 1)
|
||||
cursor_out_min:
|
||||
set_parameter("out_min", value, 0)
|
||||
cursor_out_max:
|
||||
set_parameter("out_max", value, 1)
|
||||
get_parent().send_changed_signal()
|
||||
|
||||
func _on_Auto_pressed():
|
||||
var histogram = $Histogram.get_histogram_texture().get_data()
|
||||
histogram.lock()
|
||||
var in_min : int = -1
|
||||
var in_mid : int = -1
|
||||
var in_mid_value : float = 0
|
||||
var in_max : int = -1
|
||||
var histogram_size = histogram.get_size().x
|
||||
for i in range(histogram_size):
|
||||
var color : Color = histogram.get_pixel(i, 0)
|
||||
var value : float
|
||||
match $Bar/Mode.selected:
|
||||
0:
|
||||
value = (color.r+color.g+color.b)/3.0
|
||||
1:
|
||||
value = color.r
|
||||
2:
|
||||
value = color.g
|
||||
3:
|
||||
value = color.b
|
||||
4:
|
||||
value = color.a
|
||||
if value > 0.0:
|
||||
if in_min == -1:
|
||||
in_min = i
|
||||
in_max = i
|
||||
if in_mid_value < value:
|
||||
in_mid = i
|
||||
in_mid_value = value
|
||||
histogram.unlock()
|
||||
cursor_in_min.update_value(in_min/(histogram_size-1))
|
||||
cursor_in_mid.update_value(in_mid/(histogram_size-1))
|
||||
cursor_in_max.update_value(in_max/(histogram_size-1))
|
103
material_maker/nodes/tones.tscn
Normal file
103
material_maker/nodes/tones.tscn
Normal file
@ -0,0 +1,103 @@
|
||||
[gd_scene load_steps=5 format=2]
|
||||
|
||||
[ext_resource path="res://material_maker/nodes/tones.gd" type="Script" id=1]
|
||||
[ext_resource path="res://material_maker/widgets/histogram/histogram.tscn" type="PackedScene" id=2]
|
||||
[ext_resource path="res://material_maker/icons/icons.svg" type="Texture" id=3]
|
||||
|
||||
[sub_resource type="AtlasTexture" id=1]
|
||||
flags = 4
|
||||
atlas = ExtResource( 3 )
|
||||
region = Rect2( 16, 80, 16, 16 )
|
||||
|
||||
[node name="Tones" type="GraphNode"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 2.75074
|
||||
margin_top = 1.78928
|
||||
margin_right = -1053.25
|
||||
margin_bottom = -529.211
|
||||
title = "Tones"
|
||||
show_close = true
|
||||
slot/0/left_enabled = true
|
||||
slot/0/left_type = 0
|
||||
slot/0/left_color = Color( 0, 0.396078, 1, 1 )
|
||||
slot/0/right_enabled = true
|
||||
slot/0/right_type = 0
|
||||
slot/0/right_color = Color( 0, 0.415686, 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 )
|
||||
slot/3/left_enabled = false
|
||||
slot/3/left_type = 0
|
||||
slot/3/left_color = Color( 1, 1, 1, 1 )
|
||||
slot/3/right_enabled = false
|
||||
slot/3/right_type = 0
|
||||
slot/3/right_color = Color( 1, 1, 1, 1 )
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Bar" type="HBoxContainer" parent="."]
|
||||
margin_left = 16.0
|
||||
margin_top = 24.0
|
||||
margin_right = 208.0
|
||||
margin_bottom = 44.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Mode" type="OptionButton" parent="Bar"]
|
||||
margin_right = 172.0
|
||||
margin_bottom = 20.0
|
||||
size_flags_horizontal = 3
|
||||
text = "Luminance"
|
||||
items = [ "Luminance", null, false, 0, null, "Red", null, false, 1, null, "Green", null, false, 2, null, "Blue", null, false, 3, null, "Alpha", null, false, 4, null ]
|
||||
selected = 0
|
||||
|
||||
[node name="Auto" type="TextureButton" parent="Bar"]
|
||||
margin_left = 176.0
|
||||
margin_top = 2.0
|
||||
margin_right = 192.0
|
||||
margin_bottom = 18.0
|
||||
hint_tooltip = "Set levels automatically"
|
||||
size_flags_vertical = 4
|
||||
texture_normal = SubResource( 1 )
|
||||
|
||||
[node name="Spacer1" type="Control" parent="."]
|
||||
margin_left = 16.0
|
||||
margin_top = 45.0
|
||||
margin_right = 208.0
|
||||
margin_bottom = 49.0
|
||||
rect_min_size = Vector2( 0, 4 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Histogram" parent="." instance=ExtResource( 2 )]
|
||||
margin_left = 16.0
|
||||
margin_top = 50.0
|
||||
margin_right = 208.0
|
||||
margin_bottom = 178.0
|
||||
rect_min_size = Vector2( 192, 128 )
|
||||
|
||||
[node name="Spacer2" type="Control" parent="."]
|
||||
margin_left = 16.0
|
||||
margin_top = 179.0
|
||||
margin_right = 208.0
|
||||
margin_bottom = 183.0
|
||||
rect_min_size = Vector2( 0, 4 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
[connection signal="item_selected" from="Bar/Mode" to="." method="_on_Mode_item_selected"]
|
||||
[connection signal="pressed" from="Bar/Auto" to="." method="_on_Auto_pressed"]
|
10
material_maker/widgets/histogram/histogram.gd
Normal file
10
material_maker/widgets/histogram/histogram.gd
Normal file
@ -0,0 +1,10 @@
|
||||
extends Control
|
||||
|
||||
func update_histogram() -> void:
|
||||
pass
|
||||
|
||||
func get_image_texture() -> ImageTexture:
|
||||
return $ViewportImage/ColorRect.material.get_shader_param("tex")
|
||||
|
||||
func get_histogram_texture() -> ImageTexture:
|
||||
return $Control.material.get_shader_param("tex")
|
157
material_maker/widgets/histogram/histogram.tscn
Normal file
157
material_maker/widgets/histogram/histogram.tscn
Normal file
@ -0,0 +1,157 @@
|
||||
[gd_scene load_steps=14 format=2]
|
||||
|
||||
[ext_resource path="res://material_maker/widgets/histogram/histogram.gd" type="Script" id=1]
|
||||
|
||||
[sub_resource type="Shader" id=1]
|
||||
resource_local_to_scene = true
|
||||
code = "shader_type canvas_item;
|
||||
render_mode blend_disabled;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
void fragment() {
|
||||
COLOR = texture(tex, UV);
|
||||
}
|
||||
"
|
||||
|
||||
[sub_resource type="ImageTexture" id=2]
|
||||
resource_local_to_scene = true
|
||||
|
||||
[sub_resource type="ShaderMaterial" id=3]
|
||||
resource_local_to_scene = true
|
||||
shader = SubResource( 1 )
|
||||
shader_param/tex = SubResource( 2 )
|
||||
|
||||
[sub_resource type="Shader" id=4]
|
||||
code = "shader_type canvas_item;
|
||||
render_mode blend_disabled;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
void fragment() {
|
||||
vec4 sum = vec4(0.0);
|
||||
for (int i = 0; i < 128; ++i) {
|
||||
sum += step(abs(texture(tex, vec2(UV.x, float(i)/127.0))-UV.y), vec4(0.02));
|
||||
}
|
||||
COLOR = sum/255.0;
|
||||
}
|
||||
"
|
||||
|
||||
[sub_resource type="ViewportTexture" id=5]
|
||||
viewport_path = NodePath("ViewportImage")
|
||||
|
||||
[sub_resource type="ShaderMaterial" id=6]
|
||||
resource_local_to_scene = true
|
||||
shader = SubResource( 4 )
|
||||
shader_param/tex = SubResource( 5 )
|
||||
|
||||
[sub_resource type="Shader" id=7]
|
||||
code = "shader_type canvas_item;
|
||||
render_mode blend_disabled;
|
||||
|
||||
uniform sampler2D tex;
|
||||
|
||||
void fragment() {
|
||||
vec4 sum = vec4(0.0);
|
||||
for (int i = 0; i < 128; ++i) {
|
||||
sum += texture(tex, vec2(float(i)/127.0, UV.x));
|
||||
}
|
||||
COLOR = sum/255.0;
|
||||
}"
|
||||
|
||||
[sub_resource type="ViewportTexture" id=8]
|
||||
viewport_path = NodePath("ViewportHistogram1")
|
||||
|
||||
[sub_resource type="ShaderMaterial" id=9]
|
||||
resource_local_to_scene = true
|
||||
shader = SubResource( 7 )
|
||||
shader_param/tex = SubResource( 8 )
|
||||
|
||||
[sub_resource type="Shader" id=10]
|
||||
code = "shader_type canvas_item;
|
||||
|
||||
uniform sampler2D tex;
|
||||
render_mode blend_disabled;
|
||||
|
||||
void fragment() {
|
||||
if (abs(fract(UV.y+0.05)) < 0.1) {
|
||||
COLOR = vec4(vec3(UV.x), 1.0);
|
||||
} else {
|
||||
vec4 highest = vec4(0.0);
|
||||
for (int i = 0; i < 128; ++i) {
|
||||
highest = max(highest, texture(tex, vec2(float(i)/128.0, 0.0)));
|
||||
}
|
||||
vec4 value = step(vec4(0.95-UV.y)*highest/0.9, texture(tex, vec2(UV.x, 0.0)));
|
||||
float alpha = step(0.1, dot(value, vec4(1.0)));
|
||||
COLOR = vec4(mix(value.rgb, vec3(0.5), 0.3*value.a), alpha);
|
||||
}
|
||||
}"
|
||||
|
||||
[sub_resource type="ViewportTexture" id=11]
|
||||
flags = 4
|
||||
viewport_path = NodePath("ViewportHistogram2")
|
||||
|
||||
[sub_resource type="ShaderMaterial" id=12]
|
||||
resource_local_to_scene = true
|
||||
shader = SubResource( 10 )
|
||||
shader_param/tex = SubResource( 11 )
|
||||
|
||||
[node name="Histogram" type="Control"]
|
||||
margin_right = 64.0
|
||||
margin_bottom = 64.0
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="ViewportImage" type="Viewport" parent="."]
|
||||
size = Vector2( 256, 256 )
|
||||
transparent_bg = true
|
||||
hdr = false
|
||||
usage = 0
|
||||
render_target_v_flip = true
|
||||
render_target_update_mode = 3
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="ViewportImage"]
|
||||
material = SubResource( 3 )
|
||||
margin_right = 256.0
|
||||
margin_bottom = 128.0
|
||||
rect_min_size = Vector2( 256, 256 )
|
||||
|
||||
[node name="ViewportHistogram1" type="Viewport" parent="."]
|
||||
size = Vector2( 128, 128 )
|
||||
own_world = true
|
||||
transparent_bg = true
|
||||
hdr = false
|
||||
usage = 0
|
||||
render_target_v_flip = true
|
||||
render_target_update_mode = 3
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="ViewportHistogram1"]
|
||||
material = SubResource( 6 )
|
||||
margin_right = 128.0
|
||||
margin_bottom = 128.0
|
||||
rect_min_size = Vector2( 128, 128 )
|
||||
|
||||
[node name="ViewportHistogram2" type="Viewport" parent="."]
|
||||
size = Vector2( 128, 2 )
|
||||
transparent_bg = true
|
||||
disable_3d = true
|
||||
keep_3d_linear = true
|
||||
usage = 0
|
||||
render_target_v_flip = true
|
||||
render_target_update_mode = 3
|
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="ViewportHistogram2"]
|
||||
material = SubResource( 9 )
|
||||
margin_right = 128.0
|
||||
margin_bottom = 2.0
|
||||
rect_min_size = Vector2( 128, 2 )
|
||||
|
||||
[node name="Control" type="ColorRect" parent="."]
|
||||
material = SubResource( 12 )
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
Loading…
Reference in New Issue
Block a user