Release/v5 #10

Merged
ChaoticByte merged 5 commits from release/v5 into main 2024-12-19 18:47:52 +00:00
23 changed files with 252 additions and 227 deletions

View file

@ -1,5 +1,5 @@
<h1 align=center>GlitchApp</h1> <h1 align=center>Fragmented</h1>
![screenshot](./screenshot.png) ![screenshot](./screenshot.png)
@ -9,30 +9,39 @@
- Linux - Linux
You can find the latest releases [here](https://github.com/ChaoticByte/GlitchApp/releases/latest). You can find the latest releases [here](https://github.com/ChaoticByte/Fragmented/releases/latest).
## Usage ## Usage
The application includes presets. You can use them as a starting-point to write your own filters. The repo includes examples. 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. 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 ```glsl
//!load <name> <filepath> //!load <name> <filepath>
uniform sampler2D <name>; uniform sampler2D <name>;
``` ```
With this you can load additional images into your shader. Have a look at the `mix.gdshader` example:
Have a look at the `Mix` preset:
```glsl ```glsl
shader_type canvas_item; shader_type canvas_item;
//!load img2 ./icon.png //!load ./swamp.jpg
//!load+ img2 ./overlay.jpg
uniform sampler2D img2: repeat_enable, filter_nearest; uniform sampler2D img2: repeat_enable, filter_nearest;
void fragment() { void fragment() {
COLOR = mix(COLOR, texture(img2, UV), .5); COLOR = mix(COLOR, texture(img2, UV), .2);
} }
``` ```

5
examples/CREDITS.md Normal file
View 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/)

View file

@ -1,5 +1,7 @@
shader_type canvas_item; shader_type canvas_item;
//!load ./swamp.jpg
const vec2 offset_r = vec2(-0.002, -0.002); const vec2 offset_r = vec2(-0.002, -0.002);
const vec2 offset_g = vec2(0., 0.); const vec2 offset_g = vec2(0., 0.);
const vec2 offset_b = vec2(0.002, 0.002); const vec2 offset_b = vec2(0.002, 0.002);

View file

@ -1,10 +1,10 @@
shader_type canvas_item; shader_type canvas_item;
//!load ./swamp.jpg
void fragment() { void fragment() {
vec4 tex = texture(TEXTURE , UV);
float b = (COLOR.r + COLOR.g + COLOR.b) / 3.0; float b = (COLOR.r + COLOR.g + COLOR.b) / 3.0;
COLOR.r = b; COLOR.r = b;
COLOR.g = b; COLOR.g = b;
COLOR.b = b; COLOR.b = b;
COLOR.a = tex.a;
} }

View file

@ -1,5 +1,7 @@
shader_type canvas_item; shader_type canvas_item;
//!load ./swamp.jpg
// Settings // Settings
const float threshold = 0.5; const float threshold = 0.5;
// //

View file

@ -1,8 +1,10 @@
shader_type canvas_item; shader_type canvas_item;
//!load img2 ./icon.png //!load ./swamp.jpg
//!load+ img2 ./overlay.jpg
uniform sampler2D img2: repeat_enable, filter_nearest; uniform sampler2D img2: repeat_enable, filter_nearest;
void fragment() { void fragment() {
COLOR = mix(COLOR, texture(img2, UV), .5); COLOR = mix(COLOR, texture(img2, UV), .2);
} }

BIN
examples/overlay.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 896 KiB

View 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

View file

@ -1,5 +1,7 @@
shader_type canvas_item; shader_type canvas_item;
//!load ./swamp.jpg
const float strength = 0.1; const float strength = 0.1;
void fragment() { void fragment() {

BIN
examples/swamp.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 477 KiB

34
examples/swamp.jpg.import Normal file
View 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

View file

@ -8,7 +8,7 @@ custom_features=""
export_filter="all_resources" export_filter="all_resources"
include_filter="" include_filter=""
exclude_filter="" exclude_filter=""
export_path="dist/GlitchApp.x86_64" export_path="dist/Fragmented.x86_64"
encryption_include_filters="" encryption_include_filters=""
encryption_exclude_filters="" encryption_exclude_filters=""
encrypt_pck=false encrypt_pck=false

View file

@ -10,16 +10,15 @@ config_version=5
[application] [application]
config/name="Glitch" config/name="Fragmented"
config/version="v4.0" config/version="v5.0"
run/main_scene="res://scenes/main.tscn" run/main_scene="res://scenes/main.tscn"
config/features=PackedStringArray("4.2", "Mobile") config/features=PackedStringArray("4.3", "Mobile")
run/low_processor_mode=true run/low_processor_mode=true
config/icon="res://icon.png" config/icon="res://icon.png"
[autoload] [autoload]
ShaderPresets="*res://src/presets/Presets.gd"
Globals="*res://src/Globals.gd" Globals="*res://src/Globals.gd"
[display] [display]
@ -28,6 +27,7 @@ window/size/viewport_width=1280
window/size/viewport_height=720 window/size/viewport_height=720
window/size/mode=2 window/size/mode=2
window/energy_saving/keep_screen_on=false window/energy_saving/keep_screen_on=false
window/vsync/vsync_mode=0
[editor_plugins] [editor_plugins]
@ -38,15 +38,15 @@ enabled=PackedStringArray()
zoom_out={ zoom_out={
"deadzone": 0.5, "deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":16,"position":Vector2(244, 15),"global_position":Vector2(248, 56),"factor":1.0,"button_index":5,"canceled":false,"pressed":true,"double_click":false,"script":null) "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":16,"position":Vector2(244, 15),"global_position":Vector2(248, 56),"factor":1.0,"button_index":5,"canceled":false,"pressed":true,"double_click":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":45,"physical_keycode":0,"key_label":0,"unicode":45,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":45,"physical_keycode":0,"key_label":0,"unicode":45,"location":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194435,"key_label":0,"unicode":45,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194435,"key_label":0,"unicode":45,"location":0,"echo":false,"script":null)
] ]
} }
zoom_in={ zoom_in={
"deadzone": 0.5, "deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":8,"position":Vector2(270, 19),"global_position":Vector2(274, 60),"factor":1.0,"button_index":4,"canceled":false,"pressed":true,"double_click":false,"script":null) "events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":8,"position":Vector2(270, 19),"global_position":Vector2(274, 60),"factor":1.0,"button_index":4,"canceled":false,"pressed":true,"double_click":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":43,"physical_keycode":0,"key_label":0,"unicode":43,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":43,"physical_keycode":0,"key_label":0,"unicode":43,"location":0,"echo":false,"script":null)
, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194437,"key_label":0,"unicode":43,"echo":false,"script":null) , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":true,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194437,"key_label":0,"unicode":43,"location":0,"echo":false,"script":null)
] ]
} }
drag={ drag={
@ -56,12 +56,12 @@ drag={
} }
apply_shader={ apply_shader={
"deadzone": 0.5, "deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194336,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null) "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":4194336,"physical_keycode":0,"key_label":0,"unicode":0,"location":0,"echo":false,"script":null)
] ]
} }
save_shader={ save_shader={
"deadzone": 0.5, "deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"key_label":0,"unicode":115,"echo":false,"script":null) "events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":true,"meta_pressed":false,"pressed":false,"keycode":83,"physical_keycode":0,"key_label":0,"unicode":115,"location":0,"echo":false,"script":null)
] ]
} }
@ -70,4 +70,5 @@ save_shader={
renderer/rendering_method="mobile" renderer/rendering_method="mobile"
textures/vram_compression/import_etc2_astc=true textures/vram_compression/import_etc2_astc=true
textures/lossless_compression/force_png=true textures/lossless_compression/force_png=true
shader_compiler/shader_cache/enabled=false
environment/defaults/default_clear_color=Color(0, 0, 0, 1) environment/defaults/default_clear_color=Color(0, 0, 0, 1)

View file

@ -2,7 +2,7 @@
[ext_resource type="Script" path="res://src/Main.gd" id="1_2625y"] [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/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="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/UIAppVersion.gd" id="5_o1ggv"]
[ext_resource type="Script" path="res://src/Editor.gd" id="7_g8bap"] [ext_resource type="Script" path="res://src/Editor.gd" id="7_g8bap"]
@ -18,6 +18,7 @@ shader = ExtResource("4_ty3qx")
script = ExtResource("1_2625y") script = ExtResource("1_2625y")
[node name="ImageViewport" type="SubViewport" parent="."] [node name="ImageViewport" type="SubViewport" parent="."]
unique_name_in_owner = true
disable_3d = true disable_3d = true
transparent_bg = true transparent_bg = true
canvas_item_default_texture_filter = 0 canvas_item_default_texture_filter = 0
@ -25,8 +26,10 @@ render_target_update_mode = 4
script = ExtResource("2_hvo65") script = ExtResource("2_hvo65")
[node name="ImageSprite" type="Sprite2D" parent="ImageViewport"] [node name="ImageSprite" type="Sprite2D" parent="ImageViewport"]
unique_name_in_owner = true
[node name="ImageViewportDisplay" type="Sprite2D" parent="."] [node name="ImageViewportDisplay" type="Sprite2D" parent="."]
unique_name_in_owner = true
texture = SubResource("ViewportTexture_lct1c") texture = SubResource("ViewportTexture_lct1c")
script = ExtResource("3_n4itb") script = ExtResource("3_n4itb")
@ -42,6 +45,7 @@ grow_vertical = 2
focus_mode = 2 focus_mode = 2
[node name="UserInterfaceContainer" type="Control" parent="UI_Layer"] [node name="UserInterfaceContainer" type="Control" parent="UI_Layer"]
unique_name_in_owner = true
layout_mode = 3 layout_mode = 3
anchor_right = 0.225 anchor_right = 0.225
anchor_bottom = 1.0 anchor_bottom = 1.0
@ -63,87 +67,32 @@ color = Color(1, 1, 1, 0)
[node name="AppName" type="Label" parent="UI_Layer/UserInterfaceContainer"] [node name="AppName" type="Label" parent="UI_Layer/UserInterfaceContainer"]
layout_mode = 0 layout_mode = 0
offset_left = 24.0 offset_left = 24.0
offset_top = 24.0 offset_top = 16.0
offset_right = 208.0 offset_right = 208.0
offset_bottom = 56.0 offset_bottom = 48.0
theme_override_font_sizes/font_size = 20 theme_override_font_sizes/font_size = 20
text = "GlitchApp text = "Fragmented"
"
vertical_alignment = 2 vertical_alignment = 2
[node name="AppVersion" type="Label" parent="UI_Layer/UserInterfaceContainer"] [node name="AppVersion" type="Label" parent="UI_Layer/UserInterfaceContainer"]
layout_mode = 0 layout_mode = 0
offset_left = 128.0 offset_left = 152.0
offset_top = 24.0 offset_top = 17.0
offset_right = 208.0 offset_right = 208.0
offset_bottom = 56.0 offset_bottom = 47.0
theme_override_font_sizes/font_size = 14 theme_override_font_sizes/font_size = 14
text = "v0 text = "v0
" "
vertical_alignment = 2 vertical_alignment = 2
script = ExtResource("5_o1ggv") 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"] [node name="Editor" type="Control" parent="UI_Layer/UserInterfaceContainer"]
layout_mode = 1 layout_mode = 1
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0
anchor_bottom = 1.0 anchor_bottom = 1.0
offset_left = 24.0 offset_left = 24.0
offset_top = 80.0 offset_top = 64.0
offset_right = -24.0 offset_right = -24.0
offset_bottom = -24.0 offset_bottom = -24.0
grow_horizontal = 2 grow_horizontal = 2
@ -151,8 +100,9 @@ grow_vertical = 2
script = ExtResource("7_g8bap") script = ExtResource("7_g8bap")
[node name="OpenShaderDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer/Editor"] [node name="OpenShaderDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer/Editor"]
unique_name_in_owner = true
title = "Load Shader" title = "Load Shader"
size = Vector2i(521, 159) size = Vector2i(521, 175)
ok_button_text = "Open" ok_button_text = "Open"
mode_overrides_title = false mode_overrides_title = false
file_mode = 0 file_mode = 0
@ -161,28 +111,27 @@ filters = PackedStringArray("*.gdshader")
use_native_dialog = true use_native_dialog = true
[node name="SaveShaderDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer/Editor"] [node name="SaveShaderDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer/Editor"]
unique_name_in_owner = true
title = "Save Shader" title = "Save Shader"
size = Vector2i(661, 159) size = Vector2i(661, 175)
ok_button_text = "Save" ok_button_text = "Save"
mode_overrides_title = false mode_overrides_title = false
access = 2 access = 2
filters = PackedStringArray("*.gdshader") filters = PackedStringArray("*.gdshader")
use_native_dialog = true use_native_dialog = true
[node name="Label" type="Label" parent="UI_Layer/UserInterfaceContainer/Editor"] [node name="SaveImageDialog" type="FileDialog" parent="UI_Layer/UserInterfaceContainer/Editor"]
layout_mode = 0 unique_name_in_owner = true
offset_right = 104.0 title = "Export Image"
offset_bottom = 32.0 size = Vector2i(661, 175)
text = "Load Preset: " ok_button_text = "Save"
vertical_alignment = 1 mode_overrides_title = false
access = 2
[node name="PresetOptions" type="OptionButton" parent="UI_Layer/UserInterfaceContainer/Editor"] filters = PackedStringArray("*.png")
layout_mode = 0 use_native_dialog = true
offset_left = 104.0
offset_right = 240.0
offset_bottom = 32.0
[node name="CodeEdit" type="CodeEdit" parent="UI_Layer/UserInterfaceContainer/Editor"] [node name="CodeEdit" type="CodeEdit" parent="UI_Layer/UserInterfaceContainer/Editor"]
unique_name_in_owner = true
layout_mode = 1 layout_mode = 1
anchors_preset = 15 anchors_preset = 15
anchor_right = 1.0 anchor_right = 1.0
@ -208,48 +157,55 @@ auto_brace_completion_highlight_matching = true
[node name="OpenShaderButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"] [node name="OpenShaderButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"]
layout_mode = 1 layout_mode = 1
anchors_preset = 1 offset_right = 56.0
anchor_left = 1.0
anchor_right = 1.0
offset_left = -216.0
offset_right = -160.0
offset_bottom = 32.0 offset_bottom = 32.0
grow_horizontal = 0
text = "Open" text = "Open"
[node name="SaveShaderButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"] [node name="SaveShaderButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"]
layout_mode = 1 layout_mode = 1
anchors_preset = 1 offset_left = 64.0
anchor_left = 1.0 offset_right = 120.0
anchor_right = 1.0
offset_left = -152.0
offset_right = -96.0
offset_bottom = 32.0 offset_bottom = 32.0
grow_horizontal = 0
text = "Save" text = "Save"
[node name="ApplyShaderButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"] [node name="ApplyShaderButton" type="Button" parent="UI_Layer/UserInterfaceContainer/Editor"]
layout_mode = 1 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 anchors_preset = 1
anchor_left = 1.0 anchor_left = 1.0
anchor_right = 1.0 anchor_right = 1.0
offset_left = -88.0 offset_left = -120.0
offset_bottom = 32.0 offset_bottom = 32.0
grow_horizontal = 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="."] [node name="Camera" type="Camera2D" parent="."]
unique_name_in_owner = true
script = ExtResource("8_mls06") 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/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="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="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/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/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/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"]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 669 KiB

Before After
Before After

View file

@ -2,8 +2,9 @@ extends Camera2D
var drag = false var drag = false
@onready var user_interface_container = get_parent().get_node("UI_Layer/UserInterfaceContainer") @onready var user_interface_container = %UserInterfaceContainer
@onready var image_viewport = get_parent().get_node("ImageViewport") @onready var image_viewport = %ImageViewport
@onready var image_viewport_display = %ImageViewportDisplay
func _input(event): func _input(event):
if event.is_action_pressed("zoom_out") && !Globals.camera_freeze: 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() var old_mouse_pos = get_global_mouse_position()
zoom *= 1.2 zoom *= 1.2
global_position += old_mouse_pos - get_global_mouse_position() global_position += old_mouse_pos - get_global_mouse_position()
image_viewport_display.update_zoom_texture_filter(zoom)
func zoom_out(): func zoom_out():
var old_mouse_pos = get_global_mouse_position() var old_mouse_pos = get_global_mouse_position()
zoom *= 1/1.2 zoom *= 1/1.2
global_position += old_mouse_pos - get_global_mouse_position() global_position += old_mouse_pos - get_global_mouse_position()
image_viewport_display.update_zoom_texture_filter(zoom)
func _on_fit_image_button_pressed(): func _on_fit_image_button_pressed():
fit_image() fit_image()

View file

@ -1,11 +1,8 @@
extends Control extends Control
@onready var preset_options = $PresetOptions @onready var code_editor = %CodeEdit
@onready var code_editor = $CodeEdit @onready var open_shader_dialog = %OpenShaderDialog
@onready var open_shader_dialog = $OpenShaderDialog @onready var save_shader_dialog = %SaveShaderDialog
@onready var save_shader_dialog = $SaveShaderDialog
var selected_preset_name = ShaderPresets.default_preset
var last_save_filepath = ""
# # # # # # # # # # # # # # # # # # # # # #
# GDShader keywords # # GDShader keywords #
@ -189,35 +186,17 @@ func _input(event):
accept_event() # Event is now handled. accept_event() # Event is now handled.
_on_save_shader_button_pressed() _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(): 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 code_editor.text = Globals.shader.code
func _on_open_shader_button_pressed(): func _on_open_shader_button_pressed():
open_shader_dialog.show() open_shader_dialog.show()
func _on_save_shader_button_pressed(): func _on_save_shader_button_pressed():
if last_save_filepath == "": if Globals.last_shader_savepath == "":
save_shader_dialog.current_file = selected_preset_name + "_custom.gdshader" save_shader_dialog.current_file = "shader.gdshader"
else: else:
save_shader_dialog.current_path = last_save_filepath save_shader_dialog.current_path = Globals.last_shader_savepath
save_shader_dialog.show() save_shader_dialog.show()
func _on_open_shader_dialog_file_selected(path: String): 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.cwd = path.substr(0, path.rfind("/"))
Globals.target_viewport.update() Globals.target_viewport.update()
update() update()
last_save_filepath = path Globals.last_shader_savepath = path
func _on_save_shader_dialog_file_selected(path): func _on_save_shader_dialog_file_selected(path):
print("Save ", path) print("Save ", path)
@ -240,7 +219,7 @@ func _on_save_shader_dialog_file_selected(path):
file.store_string(content) file.store_string(content)
if "/" in path: # update current working directory if "/" in path: # update current working directory
Globals.cwd = path.substr(0, path.rfind("/")) Globals.cwd = path.substr(0, path.rfind("/"))
last_save_filepath = path Globals.last_shader_savepath = path
func _on_apply_shader_button_pressed(): func _on_apply_shader_button_pressed():
var shader = Shader.new() var shader = Shader.new()

View file

@ -1,6 +1,8 @@
extends Node extends Node
var camera_freeze = false 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 target_viewport: SubViewport
var cwd = "." var cwd = "."
var last_image_savepath = ""
var last_shader_savepath = ""

View file

@ -1,46 +1,71 @@
extends SubViewport extends SubViewport
@onready var image_sprite = $ImageSprite @onready var camera = %Camera
@onready var image_sprite = %ImageSprite
var image_original_tex: ImageTexture var image_original_tex: ImageTexture
var image_result: Image var image_result: Image
var load_uniform_regex: RegEx var load_regex: RegEx
var load_additional_regex: RegEx
var last_tex_path = ""
func _ready(): func _ready():
load_uniform_regex = RegEx.new() load_regex = RegEx.new()
load_uniform_regex.compile(r'\/\/!load\s(\w*)\s(.*)') 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): func load_texture(path):
image_original_tex = ImageTexture.create_from_image(image) print("Load ", path)
image_sprite.texture = image_original_tex var img = Image.new()
image_sprite.offset = image_original_tex.get_size() / 2 var err = img.load(path)
size = image_original_tex.get_size() 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(): func update():
if image_original_tex != null: # load images from //!load directive -> TEXTURE
image_sprite.texture = image_original_tex var regex_match = load_regex.search(Globals.shader.code)
var mat = ShaderMaterial.new() if regex_match == null: # Error!
mat.shader = Globals.shader print("Didn't find any load directives!")
# load images from //!load directives and apply them to return
# the material as shader parameters var tex_path = get_absolute_path(regex_match.strings[1])
for m in load_uniform_regex.search_all(Globals.shader.code): load_texture(tex_path) # load every time
# this only works for Linux! if tex_path != last_tex_path:
var img_path = m.strings[2] camera.fit_image()
if !img_path.begins_with("/"): last_tex_path = tex_path
img_path = Globals.cwd + "/" + img_path.lstrip("./") if Globals.last_image_savepath == "":
# Globals.last_image_savepath = tex_path
print("Load ", img_path) image_sprite.texture = image_original_tex
var u_image = Image.load_from_file(img_path) var mat = ShaderMaterial.new()
mat.set_shader_parameter( mat.shader = Globals.shader
m.strings[1], # uniform param name # load images from //!load+ directives and apply them to
ImageTexture.create_from_image(u_image)) # the material as shader parameters
# assign material for m in load_additional_regex.search_all(Globals.shader.code):
image_sprite.material = mat # this only works for Linux!
# Get viewport texture var img_path = get_absolute_path(m.strings[2])
await RenderingServer.frame_post_draw # for good measure #
image_result = get_texture().get_image() print("Load ", img_path)
image_sprite.material = null var u_image = Image.load_from_file(img_path)
image_sprite.texture = ImageTexture.create_from_image(image_result) 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(): func get_result():
return image_result return image_result

View file

@ -1,9 +1,7 @@
extends Sprite2D extends Sprite2D
@onready var camera = get_parent().get_node("Camera") func update_zoom_texture_filter(zoom: Vector2):
if zoom.x >= 1.5:
func _process(_delta):
if camera.zoom.x >= 1.5:
texture_filter = TEXTURE_FILTER_NEAREST_WITH_MIPMAPS texture_filter = TEXTURE_FILTER_NEAREST_WITH_MIPMAPS
else: else:
texture_filter = TEXTURE_FILTER_LINEAR texture_filter = TEXTURE_FILTER_LINEAR

View file

@ -1,33 +1,16 @@
extends Node2D extends Node2D
@onready var camera = $Camera @onready var image_viewport = %ImageViewport
@onready var image_viewport = $ImageViewport @onready var ui_control_filesave = %SaveImageDialog
@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 = ""
func _ready(): func _ready():
DisplayServer.window_set_min_size(Vector2i(900, 500))
Globals.target_viewport = image_viewport 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(): func _on_save_image_button_pressed():
if image_viewport.get_result() != null: 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() ui_control_filesave.show()
func _on_save_image_dialog_file_selected(path): func _on_save_image_dialog_file_selected(path):
@ -36,4 +19,4 @@ func _on_save_image_dialog_file_selected(path):
if err != OK: if err != OK:
print("An error occured!") print("An error occured!")
else: else:
last_save_filepath = path Globals.last_image_savepath = path

View file

@ -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"

View file

@ -1,5 +1,7 @@
shader_type canvas_item; shader_type canvas_item;
//!load /path/to/your/image
void fragment() { void fragment() {
// Called for every pixel the material is visible on. // Called for every pixel the material is visible on.
} }