Release/v5 #10
21 changed files with 231 additions and 205 deletions
21
README.md
21
README.md
|
@ -13,23 +13,32 @@ You can find the latest releases [here](https://github.com/ChaoticByte/Fragmente
|
|||
|
||||
## Usage
|
||||
|
||||
The application includes presets. You can use them as a starting-point to write your own filters.
|
||||
Just load an image, apply a preset, edit the code and hit `F5` to see the changes.
|
||||
The repo includes examples. You can use them as a starting-point to write your own filters.
|
||||
Just load an image using `//!load`, edit the shader code and hit `F5` to see the changes.
|
||||
|
||||
### Load additional images using the `//!load` directive
|
||||
### Load TEXTURE using the `//!load` directive
|
||||
|
||||
```glsl
|
||||
//!load <filepath>
|
||||
```
|
||||
|
||||
The image file will be read and available as the `TEXTURE` variable.
|
||||
|
||||
#### Load additional images
|
||||
|
||||
```glsl
|
||||
//!load <name> <filepath>
|
||||
uniform sampler2D <name>;
|
||||
```
|
||||
|
||||
With this you can load additional images into your shader.
|
||||
Have a look at the `Mix` preset:
|
||||
Have a look at the `mix.gdshader` example:
|
||||
|
||||
```glsl
|
||||
shader_type canvas_item;
|
||||
|
||||
//!load img2 ./icon.png
|
||||
//!load ./example1.png
|
||||
|
||||
//!load+ img2 ./example2.jpg
|
||||
uniform sampler2D img2: repeat_enable, filter_nearest;
|
||||
|
||||
void fragment() {
|
||||
|
|
5
examples/CREDITS.md
Normal file
5
examples/CREDITS.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
|
||||
# Example Images
|
||||
|
||||
- swamp.jpg by [clfr21](https://pixabay.com/de/users/clfr21-6530007/)
|
||||
- overlay.jpg by [Humusak](https://pixabay.com/de/users/humusak-137455/)
|
|
@ -1,5 +1,7 @@
|
|||
shader_type canvas_item;
|
||||
|
||||
//!load ./swamp.jpg
|
||||
|
||||
const vec2 offset_r = vec2(-0.002, -0.002);
|
||||
const vec2 offset_g = vec2(0., 0.);
|
||||
const vec2 offset_b = vec2(0.002, 0.002);
|
|
@ -1,10 +1,10 @@
|
|||
shader_type canvas_item;
|
||||
|
||||
//!load ./swamp.jpg
|
||||
|
||||
void fragment() {
|
||||
vec4 tex = texture(TEXTURE , UV);
|
||||
float b = (COLOR.r + COLOR.g + COLOR.b) / 3.0;
|
||||
COLOR.r = b;
|
||||
COLOR.g = b;
|
||||
COLOR.b = b;
|
||||
COLOR.a = tex.a;
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
shader_type canvas_item;
|
||||
|
||||
//!load ./swamp.jpg
|
||||
|
||||
// Settings
|
||||
const float threshold = 0.5;
|
||||
//
|
|
@ -1,8 +1,10 @@
|
|||
shader_type canvas_item;
|
||||
|
||||
//!load img2 ./icon.png
|
||||
//!load ./swamp.jpg
|
||||
|
||||
//!load+ img2 ./overlay.jpg
|
||||
uniform sampler2D img2: repeat_enable, filter_nearest;
|
||||
|
||||
void fragment() {
|
||||
COLOR = mix(COLOR, texture(img2, UV), .5);
|
||||
COLOR = mix(COLOR, texture(img2, UV), .2);
|
||||
}
|
BIN
examples/overlay.jpg
Normal file
BIN
examples/overlay.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 896 KiB |
34
examples/overlay.jpg.import
Normal file
34
examples/overlay.jpg.import
Normal file
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://8101nnc8cx4o"
|
||||
path="res://.godot/imported/overlay.jpg-b6d13e0def59877969c9eda02fa4244e.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://examples/overlay.jpg"
|
||||
dest_files=["res://.godot/imported/overlay.jpg-b6d13e0def59877969c9eda02fa4244e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
|
@ -1,5 +1,7 @@
|
|||
shader_type canvas_item;
|
||||
|
||||
//!load ./swamp.jpg
|
||||
|
||||
const float strength = 0.1;
|
||||
|
||||
void fragment() {
|
BIN
examples/swamp.jpg
Normal file
BIN
examples/swamp.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 477 KiB |
34
examples/swamp.jpg.import
Normal file
34
examples/swamp.jpg.import
Normal file
|
@ -0,0 +1,34 @@
|
|||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://ckjb0agn5btv7"
|
||||
path="res://.godot/imported/swamp.jpg-8e3eac7e7aacce65638e712310cdb35c.ctex"
|
||||
metadata={
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://examples/swamp.jpg"
|
||||
dest_files=["res://.godot/imported/swamp.jpg-8e3eac7e7aacce65638e712310cdb35c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=false
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=1
|
|
@ -27,6 +27,7 @@ window/size/viewport_width=1280
|
|||
window/size/viewport_height=720
|
||||
window/size/mode=2
|
||||
window/energy_saving/keep_screen_on=false
|
||||
window/vsync/vsync_mode=0
|
||||
|
||||
[editor_plugins]
|
||||
|
||||
|
@ -69,4 +70,5 @@ save_shader={
|
|||
renderer/rendering_method="mobile"
|
||||
textures/vram_compression/import_etc2_astc=true
|
||||
textures/lossless_compression/force_png=true
|
||||
shader_compiler/shader_cache/enabled=false
|
||||
environment/defaults/default_clear_color=Color(0, 0, 0, 1)
|
||||
|
|
135
scenes/main.tscn
135
scenes/main.tscn
|
@ -2,7 +2,7 @@
|
|||
|
||||
[ext_resource type="Script" path="res://src/Main.gd" id="1_2625y"]
|
||||
[ext_resource type="Script" path="res://src/ImageViewport.gd" id="2_hvo65"]
|
||||
[ext_resource type="Script" path="res://src/ImageViewportDisplays.gd" id="3_n4itb"]
|
||||
[ext_resource type="Script" path="res://src/ImageViewportDisplay.gd" id="3_n4itb"]
|
||||
[ext_resource type="Shader" path="res://src/ui_background.gdshader" id="4_ty3qx"]
|
||||
[ext_resource type="Script" path="res://src/UIAppVersion.gd" id="5_o1ggv"]
|
||||
[ext_resource type="Script" path="res://src/Editor.gd" id="7_g8bap"]
|
||||
|
@ -18,6 +18,7 @@ shader = ExtResource("4_ty3qx")
|
|||
script = ExtResource("1_2625y")
|
||||
|
||||
[node name="ImageViewport" type="SubViewport" parent="."]
|
||||
unique_name_in_owner = true
|
||||
disable_3d = true
|
||||
transparent_bg = true
|
||||
canvas_item_default_texture_filter = 0
|
||||
|
@ -25,8 +26,10 @@ render_target_update_mode = 4
|
|||
script = ExtResource("2_hvo65")
|
||||
|
||||
[node name="ImageSprite" type="Sprite2D" parent="ImageViewport"]
|
||||
unique_name_in_owner = true
|
||||
|
||||
[node name="ImageViewportDisplay" type="Sprite2D" parent="."]
|
||||
unique_name_in_owner = true
|
||||
texture = SubResource("ViewportTexture_lct1c")
|
||||
script = ExtResource("3_n4itb")
|
||||
|
||||
|
@ -42,6 +45,7 @@ grow_vertical = 2
|
|||
focus_mode = 2
|
||||
|
||||
[node name="UserInterfaceContainer" type="Control" parent="UI_Layer"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 3
|
||||
anchor_right = 0.225
|
||||
anchor_bottom = 1.0
|
||||
|
@ -82,60 +86,6 @@ text = "v0
|
|||
vertical_alignment = 2
|
||||
script = ExtResource("5_o1ggv")
|
||||
|
||||
[node name="OpenImageDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer"]
|
||||
title = "Load Image"
|
||||
size = Vector2i(521, 159)
|
||||
ok_button_text = "Open"
|
||||
mode_overrides_title = false
|
||||
file_mode = 0
|
||||
access = 2
|
||||
use_native_dialog = true
|
||||
|
||||
[node name="SaveImageDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer"]
|
||||
title = "Export Image"
|
||||
size = Vector2i(661, 159)
|
||||
ok_button_text = "Save"
|
||||
mode_overrides_title = false
|
||||
access = 2
|
||||
filters = PackedStringArray("*.png")
|
||||
use_native_dialog = true
|
||||
|
||||
[node name="OpenImageButton" type="Button" parent="UI_Layer/UserInterfaceContainer"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -360.0
|
||||
offset_top = 24.0
|
||||
offset_right = -248.0
|
||||
offset_bottom = 56.0
|
||||
grow_horizontal = 0
|
||||
text = "Load Image"
|
||||
|
||||
[node name="SaveImageButton" type="Button" parent="UI_Layer/UserInterfaceContainer"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -240.0
|
||||
offset_top = 23.0
|
||||
offset_right = -120.0
|
||||
offset_bottom = 55.0
|
||||
grow_horizontal = 0
|
||||
text = "Export Image"
|
||||
|
||||
[node name="FitImageButton" type="Button" parent="UI_Layer/UserInterfaceContainer"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -112.0
|
||||
offset_top = 24.0
|
||||
offset_right = -24.0
|
||||
offset_bottom = 56.0
|
||||
grow_horizontal = 0
|
||||
text = "Fit Image"
|
||||
|
||||
[node name="Editor" type="Control" parent="UI_Layer/UserInterfaceContainer"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
|
@ -150,8 +100,9 @@ grow_vertical = 2
|
|||
script = ExtResource("7_g8bap")
|
||||
|
||||
[node name="OpenShaderDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer/Editor"]
|
||||
unique_name_in_owner = true
|
||||
title = "Load Shader"
|
||||
size = Vector2i(521, 159)
|
||||
size = Vector2i(521, 175)
|
||||
ok_button_text = "Open"
|
||||
mode_overrides_title = false
|
||||
file_mode = 0
|
||||
|
@ -160,28 +111,27 @@ filters = PackedStringArray("*.gdshader")
|
|||
use_native_dialog = true
|
||||
|
||||
[node name="SaveShaderDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer/Editor"]
|
||||
unique_name_in_owner = true
|
||||
title = "Save Shader"
|
||||
size = Vector2i(661, 159)
|
||||
size = Vector2i(661, 175)
|
||||
ok_button_text = "Save"
|
||||
mode_overrides_title = false
|
||||
access = 2
|
||||
filters = PackedStringArray("*.gdshader")
|
||||
use_native_dialog = true
|
||||
|
||||
[node name="Label" type="Label" parent="UI_Layer/UserInterfaceContainer/Editor"]
|
||||
layout_mode = 0
|
||||
offset_right = 104.0
|
||||
offset_bottom = 32.0
|
||||
text = "Load Preset: "
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="PresetOptions" type="OptionButton" parent="UI_Layer/UserInterfaceContainer/Editor"]
|
||||
layout_mode = 0
|
||||
offset_left = 104.0
|
||||
offset_right = 240.0
|
||||
offset_bottom = 32.0
|
||||
[node name="SaveImageDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer/Editor"]
|
||||
unique_name_in_owner = true
|
||||
title = "Export Image"
|
||||
size = Vector2i(661, 175)
|
||||
ok_button_text = "Save"
|
||||
mode_overrides_title = false
|
||||
access = 2
|
||||
filters = PackedStringArray("*.png")
|
||||
use_native_dialog = true
|
||||
|
||||
[node name="CodeEdit" type="CodeEdit" parent="UI_Layer/UserInterfaceContainer/Editor"]
|
||||
unique_name_in_owner = true
|
||||
layout_mode = 1
|
||||
anchors_preset = 15
|
||||
anchor_right = 1.0
|
||||
|
@ -207,48 +157,55 @@ auto_brace_completion_highlight_matching = true
|
|||
|
||||
[node name="OpenShaderButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -216.0
|
||||
offset_right = -160.0
|
||||
offset_right = 56.0
|
||||
offset_bottom = 32.0
|
||||
grow_horizontal = 0
|
||||
text = "Open"
|
||||
|
||||
[node name="SaveShaderButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -152.0
|
||||
offset_right = -96.0
|
||||
offset_left = 64.0
|
||||
offset_right = 120.0
|
||||
offset_bottom = 32.0
|
||||
grow_horizontal = 0
|
||||
text = "Save"
|
||||
|
||||
[node name="ApplyShaderButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"]
|
||||
layout_mode = 1
|
||||
offset_left = 128.0
|
||||
offset_right = 216.0
|
||||
offset_bottom = 32.0
|
||||
text = "Apply (F5)"
|
||||
|
||||
[node name="SaveImageButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -88.0
|
||||
offset_left = -120.0
|
||||
offset_bottom = 32.0
|
||||
grow_horizontal = 0
|
||||
text = "Apply (F5)"
|
||||
text = "Export Image"
|
||||
|
||||
[node name="FitImageButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"]
|
||||
layout_mode = 1
|
||||
anchors_preset = 1
|
||||
anchor_left = 1.0
|
||||
anchor_right = 1.0
|
||||
offset_left = -216.0
|
||||
offset_right = -128.0
|
||||
offset_bottom = 32.0
|
||||
grow_horizontal = 0
|
||||
text = "Fit Image"
|
||||
|
||||
[node name="Camera" type="Camera2D" parent="."]
|
||||
unique_name_in_owner = true
|
||||
script = ExtResource("8_mls06")
|
||||
|
||||
[connection signal="file_selected" from="UI_Layer/UserInterfaceContainer/OpenImageDialog" to="." method="_on_open_image_dialog_file_selected"]
|
||||
[connection signal="file_selected" from="UI_Layer/UserInterfaceContainer/SaveImageDialog" to="." method="_on_save_image_dialog_file_selected"]
|
||||
[connection signal="pressed" from="UI_Layer/UserInterfaceContainer/OpenImageButton" to="." method="_on_open_image_button_pressed"]
|
||||
[connection signal="pressed" from="UI_Layer/UserInterfaceContainer/SaveImageButton" to="." method="_on_save_image_button_pressed"]
|
||||
[connection signal="pressed" from="UI_Layer/UserInterfaceContainer/FitImageButton" to="Camera" method="_on_fit_image_button_pressed"]
|
||||
[connection signal="file_selected" from="UI_Layer/UserInterfaceContainer/Editor/OpenShaderDialog" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_open_shader_dialog_file_selected"]
|
||||
[connection signal="file_selected" from="UI_Layer/UserInterfaceContainer/Editor/SaveShaderDialog" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_save_shader_dialog_file_selected"]
|
||||
[connection signal="item_selected" from="UI_Layer/UserInterfaceContainer/Editor/PresetOptions" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_preset_options_item_selected"]
|
||||
[connection signal="file_selected" from="UI_Layer/UserInterfaceContainer/Editor/SaveImageDialog" to="." method="_on_save_image_dialog_file_selected"]
|
||||
[connection signal="code_completion_requested" from="UI_Layer/UserInterfaceContainer/Editor/CodeEdit" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_code_edit_code_completion_requested"]
|
||||
[connection signal="pressed" from="UI_Layer/UserInterfaceContainer/Editor/OpenShaderButton" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_open_shader_button_pressed"]
|
||||
[connection signal="pressed" from="UI_Layer/UserInterfaceContainer/Editor/SaveShaderButton" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_save_shader_button_pressed"]
|
||||
[connection signal="pressed" from="UI_Layer/UserInterfaceContainer/Editor/ApplyShaderButton" to="UI_Layer/UserInterfaceContainer/Editor" method="_on_apply_shader_button_pressed"]
|
||||
[connection signal="pressed" from="UI_Layer/UserInterfaceContainer/Editor/SaveImageButton" to="." method="_on_save_image_button_pressed"]
|
||||
[connection signal="pressed" from="UI_Layer/UserInterfaceContainer/Editor/FitImageButton" to="Camera" method="_on_fit_image_button_pressed"]
|
||||
|
|
|
@ -2,8 +2,9 @@ extends Camera2D
|
|||
|
||||
var drag = false
|
||||
|
||||
@onready var user_interface_container = get_parent().get_node("UI_Layer/UserInterfaceContainer")
|
||||
@onready var image_viewport = get_parent().get_node("ImageViewport")
|
||||
@onready var user_interface_container = %UserInterfaceContainer
|
||||
@onready var image_viewport = %ImageViewport
|
||||
@onready var image_viewport_display = %ImageViewportDisplay
|
||||
|
||||
func _input(event):
|
||||
if event.is_action_pressed("zoom_out") && !Globals.camera_freeze:
|
||||
|
@ -32,11 +33,13 @@ func zoom_in():
|
|||
var old_mouse_pos = get_global_mouse_position()
|
||||
zoom *= 1.2
|
||||
global_position += old_mouse_pos - get_global_mouse_position()
|
||||
image_viewport_display.update_zoom_texture_filter(zoom)
|
||||
|
||||
func zoom_out():
|
||||
var old_mouse_pos = get_global_mouse_position()
|
||||
zoom *= 1/1.2
|
||||
global_position += old_mouse_pos - get_global_mouse_position()
|
||||
image_viewport_display.update_zoom_texture_filter(zoom)
|
||||
|
||||
func _on_fit_image_button_pressed():
|
||||
fit_image()
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
extends Control
|
||||
|
||||
@onready var preset_options = $PresetOptions
|
||||
@onready var code_editor = $CodeEdit
|
||||
@onready var open_shader_dialog = $OpenShaderDialog
|
||||
@onready var save_shader_dialog = $SaveShaderDialog
|
||||
var selected_preset_name = ShaderPresets.default_preset
|
||||
var last_save_filepath = ""
|
||||
@onready var code_editor = %CodeEdit
|
||||
@onready var open_shader_dialog = %OpenShaderDialog
|
||||
@onready var save_shader_dialog = %SaveShaderDialog
|
||||
|
||||
# # # # # # # # # # #
|
||||
# GDShader keywords #
|
||||
|
@ -189,35 +186,17 @@ func _input(event):
|
|||
accept_event() # Event is now handled.
|
||||
_on_save_shader_button_pressed()
|
||||
|
||||
func _on_preset_options_item_selected(index):
|
||||
selected_preset_name = preset_options.get_item_text(index)
|
||||
Globals.shader = ShaderPresets.presets[selected_preset_name]
|
||||
Globals.target_viewport.update()
|
||||
update()
|
||||
last_save_filepath = ""
|
||||
|
||||
func update():
|
||||
preset_options.clear()
|
||||
# the following lines are weird af
|
||||
var presets: Array[String] = []
|
||||
var current_p_idx = 0
|
||||
for p in ShaderPresets.presets:
|
||||
presets.append(p)
|
||||
if p == selected_preset_name:
|
||||
current_p_idx = len(presets) - 1
|
||||
preset_options.add_item(p)
|
||||
preset_options.select(current_p_idx)
|
||||
# weirdness ends here
|
||||
code_editor.text = Globals.shader.code
|
||||
|
||||
func _on_open_shader_button_pressed():
|
||||
open_shader_dialog.show()
|
||||
|
||||
func _on_save_shader_button_pressed():
|
||||
if last_save_filepath == "":
|
||||
save_shader_dialog.current_file = selected_preset_name + "_custom.gdshader"
|
||||
if Globals.last_shader_savepath == "":
|
||||
save_shader_dialog.current_file = "shader.gdshader"
|
||||
else:
|
||||
save_shader_dialog.current_path = last_save_filepath
|
||||
save_shader_dialog.current_path = Globals.last_shader_savepath
|
||||
save_shader_dialog.show()
|
||||
|
||||
func _on_open_shader_dialog_file_selected(path: String):
|
||||
|
@ -231,7 +210,7 @@ func _on_open_shader_dialog_file_selected(path: String):
|
|||
Globals.cwd = path.substr(0, path.rfind("/"))
|
||||
Globals.target_viewport.update()
|
||||
update()
|
||||
last_save_filepath = path
|
||||
Globals.last_shader_savepath = path
|
||||
|
||||
func _on_save_shader_dialog_file_selected(path):
|
||||
print("Save ", path)
|
||||
|
@ -240,7 +219,7 @@ func _on_save_shader_dialog_file_selected(path):
|
|||
file.store_string(content)
|
||||
if "/" in path: # update current working directory
|
||||
Globals.cwd = path.substr(0, path.rfind("/"))
|
||||
last_save_filepath = path
|
||||
Globals.last_shader_savepath = path
|
||||
|
||||
func _on_apply_shader_button_pressed():
|
||||
var shader = Shader.new()
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
extends Node
|
||||
|
||||
var camera_freeze = false
|
||||
@onready var shader: Shader = ShaderPresets.presets[ShaderPresets.default_preset]
|
||||
@onready var shader: Shader = load("res://src/shaders/empty.gdshader")
|
||||
var target_viewport: SubViewport
|
||||
var cwd = "."
|
||||
var last_image_savepath = ""
|
||||
var last_shader_savepath = ""
|
||||
|
|
|
@ -1,46 +1,71 @@
|
|||
extends SubViewport
|
||||
|
||||
@onready var image_sprite = $ImageSprite
|
||||
@onready var camera = %Camera
|
||||
@onready var image_sprite = %ImageSprite
|
||||
|
||||
var image_original_tex: ImageTexture
|
||||
var image_result: Image
|
||||
var load_uniform_regex: RegEx
|
||||
var load_regex: RegEx
|
||||
var load_additional_regex: RegEx
|
||||
var last_tex_path = ""
|
||||
|
||||
func _ready():
|
||||
load_uniform_regex = RegEx.new()
|
||||
load_uniform_regex.compile(r'\/\/!load\s(\w*)\s(.*)')
|
||||
load_regex = RegEx.new()
|
||||
load_additional_regex = RegEx.new()
|
||||
load_regex.compile(r'\/\/!load\s(.*)')
|
||||
load_additional_regex.compile(r'\/\/!load\+\s(\w*)\s(.*)')
|
||||
|
||||
func set_original_image(image: Image):
|
||||
image_original_tex = ImageTexture.create_from_image(image)
|
||||
image_sprite.texture = image_original_tex
|
||||
image_sprite.offset = image_original_tex.get_size() / 2
|
||||
size = image_original_tex.get_size()
|
||||
func load_texture(path):
|
||||
print("Load ", path)
|
||||
var img = Image.new()
|
||||
var err = img.load(path)
|
||||
if err == OK:
|
||||
image_original_tex = ImageTexture.create_from_image(img)
|
||||
image_sprite.texture = image_original_tex
|
||||
image_sprite.offset = image_original_tex.get_size() / 2
|
||||
size = image_original_tex.get_size()
|
||||
else:
|
||||
print("An error occured!")
|
||||
|
||||
func get_absolute_path(p: String) -> String:
|
||||
if !p.begins_with("/"):
|
||||
return Globals.cwd + "/" + p.lstrip("./")
|
||||
return p
|
||||
|
||||
func update():
|
||||
if image_original_tex != null:
|
||||
image_sprite.texture = image_original_tex
|
||||
var mat = ShaderMaterial.new()
|
||||
mat.shader = Globals.shader
|
||||
# load images from //!load directives and apply them to
|
||||
# the material as shader parameters
|
||||
for m in load_uniform_regex.search_all(Globals.shader.code):
|
||||
# this only works for Linux!
|
||||
var img_path = m.strings[2]
|
||||
if !img_path.begins_with("/"):
|
||||
img_path = Globals.cwd + "/" + img_path.lstrip("./")
|
||||
#
|
||||
print("Load ", img_path)
|
||||
var u_image = Image.load_from_file(img_path)
|
||||
mat.set_shader_parameter(
|
||||
m.strings[1], # uniform param name
|
||||
ImageTexture.create_from_image(u_image))
|
||||
# assign material
|
||||
image_sprite.material = mat
|
||||
# Get viewport texture
|
||||
await RenderingServer.frame_post_draw # for good measure
|
||||
image_result = get_texture().get_image()
|
||||
image_sprite.material = null
|
||||
image_sprite.texture = ImageTexture.create_from_image(image_result)
|
||||
# load images from //!load directive -> TEXTURE
|
||||
var regex_match = load_regex.search(Globals.shader.code)
|
||||
if regex_match == null: # Error!
|
||||
print("Didn't find any load directives!")
|
||||
return
|
||||
var tex_path = get_absolute_path(regex_match.strings[1])
|
||||
load_texture(tex_path) # load every time
|
||||
if tex_path != last_tex_path:
|
||||
camera.fit_image()
|
||||
last_tex_path = tex_path
|
||||
if Globals.last_image_savepath == "":
|
||||
Globals.last_image_savepath = tex_path
|
||||
image_sprite.texture = image_original_tex
|
||||
var mat = ShaderMaterial.new()
|
||||
mat.shader = Globals.shader
|
||||
# load images from //!load+ directives and apply them to
|
||||
# the material as shader parameters
|
||||
for m in load_additional_regex.search_all(Globals.shader.code):
|
||||
# this only works for Linux!
|
||||
var img_path = get_absolute_path(m.strings[2])
|
||||
#
|
||||
print("Load ", img_path)
|
||||
var u_image = Image.load_from_file(img_path)
|
||||
mat.set_shader_parameter(
|
||||
m.strings[1], # uniform param name
|
||||
ImageTexture.create_from_image(u_image))
|
||||
# assign material
|
||||
image_sprite.material = mat
|
||||
# Get viewport texture
|
||||
await RenderingServer.frame_post_draw # for good measure
|
||||
image_result = get_texture().get_image()
|
||||
image_sprite.material = null
|
||||
image_sprite.texture = ImageTexture.create_from_image(image_result)
|
||||
|
||||
func get_result():
|
||||
return image_result
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
extends Sprite2D
|
||||
|
||||
@onready var camera = get_parent().get_node("Camera")
|
||||
|
||||
func _process(_delta):
|
||||
if camera.zoom.x >= 1.5:
|
||||
func update_zoom_texture_filter(zoom: Vector2):
|
||||
if zoom.x >= 1.5:
|
||||
texture_filter = TEXTURE_FILTER_NEAREST_WITH_MIPMAPS
|
||||
else:
|
||||
texture_filter = TEXTURE_FILTER_LINEAR
|
28
src/Main.gd
28
src/Main.gd
|
@ -1,33 +1,15 @@
|
|||
extends Node2D
|
||||
|
||||
@onready var camera = $Camera
|
||||
@onready var image_viewport = $ImageViewport
|
||||
@onready var ui_container = $UI_Layer/UserInterfaceContainer
|
||||
@onready var ui_control_fileopen = $UI_Layer/UserInterfaceContainer/OpenImageDialog
|
||||
@onready var ui_control_filesave = $UI_Layer/UserInterfaceContainer/SaveImageDialog
|
||||
var last_save_filepath = ""
|
||||
@onready var image_viewport = %ImageViewport
|
||||
@onready var ui_control_filesave = %SaveImageDialog
|
||||
|
||||
|
||||
func _ready():
|
||||
Globals.target_viewport = image_viewport
|
||||
|
||||
func _on_open_image_button_pressed():
|
||||
ui_control_fileopen.show()
|
||||
|
||||
func _on_open_image_dialog_file_selected(path):
|
||||
print("Load ", path)
|
||||
var img = Image.new()
|
||||
var err = img.load(path)
|
||||
if err == OK:
|
||||
image_viewport.set_original_image(img)
|
||||
image_viewport.update()
|
||||
camera.fit_image()
|
||||
last_save_filepath = path
|
||||
else:
|
||||
print("An error occured!")
|
||||
|
||||
func _on_save_image_button_pressed():
|
||||
if image_viewport.get_result() != null:
|
||||
ui_control_filesave.current_path = last_save_filepath
|
||||
ui_control_filesave.current_path = Globals.last_image_savepath
|
||||
ui_control_filesave.show()
|
||||
|
||||
func _on_save_image_dialog_file_selected(path):
|
||||
|
@ -36,4 +18,4 @@ func _on_save_image_dialog_file_selected(path):
|
|||
if err != OK:
|
||||
print("An error occured!")
|
||||
else:
|
||||
last_save_filepath = path
|
||||
Globals.last_image_savepath = path
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
extends Node
|
||||
|
||||
const dir = "res://src/presets/shaders/"
|
||||
|
||||
@onready var presets = {
|
||||
"Empty": load(dir + "empty.gdshader"),
|
||||
"Greyscale": load(dir + "greyscale.gdshader"),
|
||||
"Lowpass": load(dir + "lowpass.gdshader"),
|
||||
"Channel Offset": load(dir + "channel_offset.gdshader"),
|
||||
"RGB -> UV Distort": load(dir + "rgb_uv_distort.gdshader"),
|
||||
"Mix": load(dir + "mix.gdshader")
|
||||
}
|
||||
|
||||
var default_preset: String = "Empty"
|
|
@ -1,5 +1,7 @@
|
|||
shader_type canvas_item;
|
||||
|
||||
//!load /path/to/your/image
|
||||
|
||||
void fragment() {
|
||||
// Called for every pixel the material is visible on.
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue