From 09aa7c2315d57ea9e312b1fef85ff7bbf061b473 Mon Sep 17 00:00:00 2001 From: Korin <92170697+ItsKorin@users.noreply.github.com> Date: Sun, 26 May 2024 17:09:26 +0200 Subject: [PATCH] Files updated with fixed Pixelate effect and new Palette effect. --- addons/post_processing/AboutShaders.txt | 1 + addons/post_processing/assets/ascii.png | Bin 0 -> 196 bytes .../post_processing/assets/ascii.png.import | 34 ++ .../post_processing/assets/green_palette.png | Bin 0 -> 105 bytes .../assets/green_palette.png.import | 34 ++ .../assets/interesting_palette.png | Bin 0 -> 126 bytes .../assets/interesting_palette.png.import | 34 ++ addons/post_processing/assets/lens_aura.png | Bin 0 -> 20293 bytes .../assets/lens_aura.png.import | 34 ++ addons/post_processing/assets/lens_divine.png | Bin 0 -> 26290 bytes .../assets/lens_divine.png.import | 34 ++ addons/post_processing/assets/lens_flare.gd | 35 ++ addons/post_processing/node/children/CRT.tscn | 40 +++ .../node/children/ChromaticAberration.tscn | 20 ++ .../node/children/analog_monitor.tscn | 29 ++ .../post_processing/node/children/ascii.tscn | 24 ++ .../post_processing/node/children/bloom.tscn | 38 +++ .../post_processing/node/children/blur.tscn | 20 ++ .../node/children/circular_waves.tscn | 30 ++ .../node/children/color_correction.tscn | 20 ++ .../node/children/fish_eye.tscn | 25 ++ .../post_processing/node/children/glitch.tscn | 24 ++ .../post_processing/node/children/grain.tscn | 19 ++ .../node/children/kaleidoscope.gdshader | 309 ++++++++++++++++++ .../node/children/outline.gdshader | 41 +++ .../node/children/outline.tscn | 21 ++ .../node/children/palette.tscn | 18 + .../node/children/pixelate.tscn | 19 ++ .../node/children/screen_shake.tscn | 22 ++ .../node/children/speed_lines.tscn | 36 ++ .../node/children/vignette.tscn | 21 ++ addons/post_processing/node/post_process.gd | 182 +++++++++++ addons/post_processing/node/post_process.svg | 9 + .../node/post_process.svg.import | 38 +++ addons/post_processing/plugin.cfg | 7 + addons/post_processing/plugin.gd | 10 + .../resource/fish_eye_example.tres | 49 +++ .../resource/no_effects_example.tres | 49 +++ .../resource/post_processing_configuration.gd | 242 ++++++++++++++ .../shaders/CLREDIT.gdshaderinc | 0 addons/post_processing/shaders/CRT.gdshader | 230 +++++++++++++ .../shaders/LensFlares.gdshader | 93 ++++++ .../shaders/analog_monitor.gdshader | 278 ++++++++++++++++ addons/post_processing/shaders/ascii.gdshader | 37 +++ addons/post_processing/shaders/bloom.gdshader | 53 +++ addons/post_processing/shaders/blur.gdshader | 10 + .../shaders/chromatic.gdshader | 12 + .../shaders/circularwaves.gdshader | 50 +++ .../shaders/color_correction.gdshader | 19 ++ .../post_processing/shaders/dither.gdshader | 76 +++++ .../post_processing/shaders/fish_eye.gdshader | 49 +++ .../post_processing/shaders/glitch.gdshader | 49 +++ addons/post_processing/shaders/grain.gdshader | 20 ++ .../post_processing/shaders/painted.gdshader | 20 ++ .../shaders/palette_limiter.gdshader | 33 ++ .../post_processing/shaders/pixelate.gdshader | 23 ++ .../post_processing/shaders/post_process.svg | 9 + .../shaders/post_process.svg.import | 37 +++ .../shaders/screen_shake.gdshader | 24 ++ .../shaders/speed_lines.gdshader | 59 ++++ .../post_processing/shaders/vignette.gdshader | 23 ++ addons/post_processing/shaders/water.gdshader | 48 +++ 62 files changed, 2820 insertions(+) create mode 100644 addons/post_processing/AboutShaders.txt create mode 100644 addons/post_processing/assets/ascii.png create mode 100644 addons/post_processing/assets/ascii.png.import create mode 100644 addons/post_processing/assets/green_palette.png create mode 100644 addons/post_processing/assets/green_palette.png.import create mode 100644 addons/post_processing/assets/interesting_palette.png create mode 100644 addons/post_processing/assets/interesting_palette.png.import create mode 100644 addons/post_processing/assets/lens_aura.png create mode 100644 addons/post_processing/assets/lens_aura.png.import create mode 100644 addons/post_processing/assets/lens_divine.png create mode 100644 addons/post_processing/assets/lens_divine.png.import create mode 100644 addons/post_processing/assets/lens_flare.gd create mode 100644 addons/post_processing/node/children/CRT.tscn create mode 100644 addons/post_processing/node/children/ChromaticAberration.tscn create mode 100644 addons/post_processing/node/children/analog_monitor.tscn create mode 100644 addons/post_processing/node/children/ascii.tscn create mode 100644 addons/post_processing/node/children/bloom.tscn create mode 100644 addons/post_processing/node/children/blur.tscn create mode 100644 addons/post_processing/node/children/circular_waves.tscn create mode 100644 addons/post_processing/node/children/color_correction.tscn create mode 100644 addons/post_processing/node/children/fish_eye.tscn create mode 100644 addons/post_processing/node/children/glitch.tscn create mode 100644 addons/post_processing/node/children/grain.tscn create mode 100644 addons/post_processing/node/children/kaleidoscope.gdshader create mode 100644 addons/post_processing/node/children/outline.gdshader create mode 100644 addons/post_processing/node/children/outline.tscn create mode 100644 addons/post_processing/node/children/palette.tscn create mode 100644 addons/post_processing/node/children/pixelate.tscn create mode 100644 addons/post_processing/node/children/screen_shake.tscn create mode 100644 addons/post_processing/node/children/speed_lines.tscn create mode 100644 addons/post_processing/node/children/vignette.tscn create mode 100644 addons/post_processing/node/post_process.gd create mode 100644 addons/post_processing/node/post_process.svg create mode 100644 addons/post_processing/node/post_process.svg.import create mode 100644 addons/post_processing/plugin.cfg create mode 100644 addons/post_processing/plugin.gd create mode 100644 addons/post_processing/resource/fish_eye_example.tres create mode 100644 addons/post_processing/resource/no_effects_example.tres create mode 100644 addons/post_processing/resource/post_processing_configuration.gd create mode 100644 addons/post_processing/shaders/CLREDIT.gdshaderinc create mode 100644 addons/post_processing/shaders/CRT.gdshader create mode 100644 addons/post_processing/shaders/LensFlares.gdshader create mode 100644 addons/post_processing/shaders/analog_monitor.gdshader create mode 100644 addons/post_processing/shaders/ascii.gdshader create mode 100644 addons/post_processing/shaders/bloom.gdshader create mode 100644 addons/post_processing/shaders/blur.gdshader create mode 100644 addons/post_processing/shaders/chromatic.gdshader create mode 100644 addons/post_processing/shaders/circularwaves.gdshader create mode 100644 addons/post_processing/shaders/color_correction.gdshader create mode 100644 addons/post_processing/shaders/dither.gdshader create mode 100644 addons/post_processing/shaders/fish_eye.gdshader create mode 100644 addons/post_processing/shaders/glitch.gdshader create mode 100644 addons/post_processing/shaders/grain.gdshader create mode 100644 addons/post_processing/shaders/painted.gdshader create mode 100644 addons/post_processing/shaders/palette_limiter.gdshader create mode 100644 addons/post_processing/shaders/pixelate.gdshader create mode 100644 addons/post_processing/shaders/post_process.svg create mode 100644 addons/post_processing/shaders/post_process.svg.import create mode 100644 addons/post_processing/shaders/screen_shake.gdshader create mode 100644 addons/post_processing/shaders/speed_lines.gdshader create mode 100644 addons/post_processing/shaders/vignette.gdshader create mode 100644 addons/post_processing/shaders/water.gdshader diff --git a/addons/post_processing/AboutShaders.txt b/addons/post_processing/AboutShaders.txt new file mode 100644 index 0000000..23e8859 --- /dev/null +++ b/addons/post_processing/AboutShaders.txt @@ -0,0 +1 @@ +Hey, you may notice that when exploring the /shaders/ directory there are some unused shaders, that means that they either are worked on or werent properly removed! diff --git a/addons/post_processing/assets/ascii.png b/addons/post_processing/assets/ascii.png new file mode 100644 index 0000000000000000000000000000000000000000..f2b6acba02f90c9a315f0ae90ea4d47b16f8a90d GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^4L~fw0VEiH8*79Bscugf#}JR>SEmN@F$nUwJpVVn z?ziK{?h|Uc!ap2S;;g5X;KLx@q0^Oy6Bu%mmLQe`C=o`i5b uWZ1C2#ZK&xx5C?&tF3p|CrqF8`WAEEk2N8C8b7&#oagE4=d#Wzp$P!7ibg#E literal 0 HcmV?d00001 diff --git a/addons/post_processing/assets/ascii.png.import b/addons/post_processing/assets/ascii.png.import new file mode 100644 index 0000000..be17bfa --- /dev/null +++ b/addons/post_processing/assets/ascii.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://5rj5tlylm7bt" +path="res://.godot/imported/ascii.png-152231094f5e4e2669cec888e3c259a5.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/post_processing/assets/ascii.png" +dest_files=["res://.godot/imported/ascii.png-152231094f5e4e2669cec888e3c259a5.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 diff --git a/addons/post_processing/assets/green_palette.png b/addons/post_processing/assets/green_palette.png new file mode 100644 index 0000000000000000000000000000000000000000..503a34fa27a96abc01c40bc96b7dff06cadd0ce9 GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^Y(UJ&0V4mNy#E2jDGqXXVpw-h<|UA$Z0T%nZMC5}JUs3Hj0|jko@Zbv$l_G$@0=J2RL$V&>gTe~DWQo00EZVI AcK`qY literal 0 HcmV?d00001 diff --git a/addons/post_processing/assets/green_palette.png.import b/addons/post_processing/assets/green_palette.png.import new file mode 100644 index 0000000..85cb6cf --- /dev/null +++ b/addons/post_processing/assets/green_palette.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dovbwkiwlo153" +path="res://.godot/imported/green_palette.png-6c780678de384f7686b5b49556c64591.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/post_processing/assets/green_palette.png" +dest_files=["res://.godot/imported/green_palette.png-6c780678de384f7686b5b49556c64591.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 diff --git a/addons/post_processing/assets/interesting_palette.png b/addons/post_processing/assets/interesting_palette.png new file mode 100644 index 0000000000000000000000000000000000000000..18ebfbc46956ca4f67054e5f1350539ef163771a GIT binary patch literal 126 zcmeAS@N?(olHy`uVBq!ia0vp^JV4CI!3HE>z4o^Raf*Z7ofy`glX(f`n0dN5hDe07 z9yH`_FkoOg@VaTD*FjOg2(6_m5(%lfO*}7(!zZYOx!xB$*RO80tW8?HY<<-S=6wqV X_Pm^TawpIP22WQ%mvv4FO$-bG#=9l9 literal 0 HcmV?d00001 diff --git a/addons/post_processing/assets/interesting_palette.png.import b/addons/post_processing/assets/interesting_palette.png.import new file mode 100644 index 0000000..e346b1b --- /dev/null +++ b/addons/post_processing/assets/interesting_palette.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://nf2dcuadvrh7" +path="res://.godot/imported/interesting_palette.png-f0563a3abea2f173a022c18d0ec48433.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/post_processing/assets/interesting_palette.png" +dest_files=["res://.godot/imported/interesting_palette.png-f0563a3abea2f173a022c18d0ec48433.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 diff --git a/addons/post_processing/assets/lens_aura.png b/addons/post_processing/assets/lens_aura.png new file mode 100644 index 0000000000000000000000000000000000000000..e97e394a7e1b867463fe5da8032785f567194b10 GIT binary patch literal 20293 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 literal 0 HcmV?d00001 diff --git a/addons/post_processing/assets/lens_aura.png.import b/addons/post_processing/assets/lens_aura.png.import new file mode 100644 index 0000000..c91b123 --- /dev/null +++ b/addons/post_processing/assets/lens_aura.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://3ee7ii2w44gd" +path="res://.godot/imported/lens_aura.png-e27f19e14a0272728e7b44bd21dd8800.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/post_processing/assets/lens_aura.png" +dest_files=["res://.godot/imported/lens_aura.png-e27f19e14a0272728e7b44bd21dd8800.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 diff --git a/addons/post_processing/assets/lens_divine.png b/addons/post_processing/assets/lens_divine.png new file mode 100644 index 0000000000000000000000000000000000000000..b0f98381755d1e35387c500aec15a97544584c22 GIT binary patch literal 26290 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�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≫VK;ly>Erk~y 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 literal 0 HcmV?d00001 diff --git a/addons/post_processing/assets/lens_divine.png.import b/addons/post_processing/assets/lens_divine.png.import new file mode 100644 index 0000000..4dcba9f --- /dev/null +++ b/addons/post_processing/assets/lens_divine.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dhlg318yf5dvo" +path="res://.godot/imported/lens_divine.png-f89592ebc844543be1487a3ee051ee93.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/post_processing/assets/lens_divine.png" +dest_files=["res://.godot/imported/lens_divine.png-f89592ebc844543be1487a3ee051ee93.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 diff --git a/addons/post_processing/assets/lens_flare.gd b/addons/post_processing/assets/lens_flare.gd new file mode 100644 index 0000000..ce5c59c --- /dev/null +++ b/addons/post_processing/assets/lens_flare.gd @@ -0,0 +1,35 @@ +extends CanvasLayer + +# In your main scene script + +var camera = null +var light_source = null +var light_pos_world = null +var screen_pos = null +var light_pos_screen = null +var material = null + +func _ready(): + # Get camera node automatically based on type + camera = get_tree().get_root().find_child("Camera3D", true, true) # Searches entire scene tree + if not camera: + print("Warning: No Camera node found in scene!") + return + + # Get first light node (adjust if you need a specific light) + light_source = get_tree().get_root().find_child("Light3D", true, true) # Searches entire scene tree + if not light_source: + print("Warning: No Light node found in scene!") + return + +func _physics_process(delta): + if not camera or not light_source: + return # Skip if camera or light not found + + # Calculate and set light position as before + light_pos_world = light_source.global_transform.origin + screen_pos = camera.project_world_ray(light_pos_world) + light_pos_screen = screen_pos / screen_pos.w + + material = $data.material + material.set_uniform("LightPositionWorldSpace", light_pos_screen) diff --git a/addons/post_processing/node/children/CRT.tscn b/addons/post_processing/node/children/CRT.tscn new file mode 100644 index 0000000..d562993 --- /dev/null +++ b/addons/post_processing/node/children/CRT.tscn @@ -0,0 +1,40 @@ +[gd_scene load_steps=3 format=3 uid="uid://mfrkdk8k6ojn"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/CRT.gdshader" id="1_7bog5"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_ju4eq"] +shader = ExtResource("1_7bog5") +shader_parameter/overlay = false +shader_parameter/scanlines_opacity = 0.4 +shader_parameter/scanlines_width = 0.25 +shader_parameter/grille_opacity = 0.3 +shader_parameter/resolution = Vector2(640, 480) +shader_parameter/pixelate = true +shader_parameter/roll = true +shader_parameter/roll_speed = 8.0 +shader_parameter/roll_size = 15.0 +shader_parameter/roll_variation = 1.8 +shader_parameter/distort_intensity = 0.05 +shader_parameter/noise_opacity = 0.4 +shader_parameter/noise_speed = 5.0 +shader_parameter/static_noise_intensity = 0.06 +shader_parameter/aberration = 0.03 +shader_parameter/brightness = 1.4 +shader_parameter/discolor = true +shader_parameter/warp_amount = 1.0 +shader_parameter/clip_warp = false +shader_parameter/vignette_intensity = 0.4 +shader_parameter/vignette_opacity = 0.5 + +[node name="CRT" type="CanvasLayer"] +layer = 103 +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_ju4eq") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/children/ChromaticAberration.tscn b/addons/post_processing/node/children/ChromaticAberration.tscn new file mode 100644 index 0000000..0491e51 --- /dev/null +++ b/addons/post_processing/node/children/ChromaticAberration.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=3 format=3 uid="uid://ccxkudlhbgmv7"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/chromatic.gdshader" id="1_qxjen"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_ke5y5"] +shader = ExtResource("1_qxjen") +shader_parameter/offset = 5.23 + +[node name="ChromaticAberration" type="CanvasLayer"] +visible = false +layer = 102 + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_ke5y5") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/children/analog_monitor.tscn b/addons/post_processing/node/children/analog_monitor.tscn new file mode 100644 index 0000000..eacf31a --- /dev/null +++ b/addons/post_processing/node/children/analog_monitor.tscn @@ -0,0 +1,29 @@ +[gd_scene load_steps=3 format=3 uid="uid://ctdvjs742haos"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/analog_monitor.gdshader" id="1_yo3om"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_s1g6v"] +shader = ExtResource("1_yo3om") +shader_parameter/res = Vector2(256, 256) +shader_parameter/mask_type = 0 +shader_parameter/bloom_type = 1 +shader_parameter/hardScan = -8.0 +shader_parameter/hardPix = -2.0 +shader_parameter/hardBloomScan = -2.0 +shader_parameter/hardBloomPix = -1.5 +shader_parameter/bloomAmount = 2.12 +shader_parameter/warp = Vector2(64, 24) +shader_parameter/maskDark = 0.5 +shader_parameter/maskLight = 1.5 + +[node name="AnalogMonitor" type="CanvasLayer"] +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_s1g6v") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/children/ascii.tscn b/addons/post_processing/node/children/ascii.tscn new file mode 100644 index 0000000..59f0ff0 --- /dev/null +++ b/addons/post_processing/node/children/ascii.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=4 format=3 uid="uid://k8tnsut5pohj"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/ascii.gdshader" id="1_bp3vh"] +[ext_resource type="Texture2D" uid="uid://5rj5tlylm7bt" path="res://addons/post_processing/assets/ascii.png" id="2_qs7p5"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_ppj3i"] +shader = ExtResource("1_bp3vh") +shader_parameter/ascii_size = Vector2(5, 10) +shader_parameter/available_columns = 10 +shader_parameter/max_columns = 16 +shader_parameter/ascii_tex = ExtResource("2_qs7p5") + +[node name="Ascii" type="CanvasLayer"] +layer = 99 +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_ppj3i") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/children/bloom.tscn b/addons/post_processing/node/children/bloom.tscn new file mode 100644 index 0000000..fe6ab3e --- /dev/null +++ b/addons/post_processing/node/children/bloom.tscn @@ -0,0 +1,38 @@ +[gd_scene load_steps=3 format=3 uid="uid://dvpfe511myfg5"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/bloom.gdshader" id="1_qyxdw"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_qv2yl"] +shader = ExtResource("1_qyxdw") +shader_parameter/BlurAmount = null +shader_parameter/FlareThreshold = null +shader_parameter/Flares = null +shader_parameter/FlareSpacing = null +shader_parameter/Intensity = null +shader_parameter/Saturation_ = null +shader_parameter/FalloffStart = null +shader_parameter/FalloffEnd = null + +[node name="Bloom" type="CanvasLayer"] + +[node name="SubViewportContainer" type="SubViewportContainer" parent="."] +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +stretch = true + +[node name="SubViewport" type="SubViewport" parent="SubViewportContainer"] +handle_input_locally = false +size = Vector2i(1152, 648) +render_target_update_mode = 4 + +[node name="TextureRect" type="ColorRect" parent="."] +z_index = 105 +material = SubResource("ShaderMaterial_qv2yl") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/addons/post_processing/node/children/blur.tscn b/addons/post_processing/node/children/blur.tscn new file mode 100644 index 0000000..6b434b2 --- /dev/null +++ b/addons/post_processing/node/children/blur.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=3 format=3 uid="uid://cxsuld87nxd0v"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/blur.gdshader" id="1_6v1pv"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_efbmf"] +shader = ExtResource("1_6v1pv") +shader_parameter/lod = 4.615 + +[node name="Blur" type="CanvasLayer"] +layer = 101 +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_efbmf") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/children/circular_waves.tscn b/addons/post_processing/node/children/circular_waves.tscn new file mode 100644 index 0000000..989a8b8 --- /dev/null +++ b/addons/post_processing/node/children/circular_waves.tscn @@ -0,0 +1,30 @@ +[gd_scene load_steps=5 format=3 uid="uid://b0770lwctcbti"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/circularwaves.gdshader" id="1_s8hqx"] + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_mq5id"] + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_bheeo"] +noise = SubResource("FastNoiseLite_mq5id") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_6bcgb"] +shader = ExtResource("1_s8hqx") +shader_parameter/amplitude = 0.99 +shader_parameter/frequency = 15.0 +shader_parameter/rippleRate = 7.7 +shader_parameter/waveAmplitude = 0.1 +shader_parameter/waveFrequency = 4.39 +shader_parameter/blendingAmount = 0.6 +shader_parameter/noise = SubResource("NoiseTexture2D_bheeo") + +[node name="CircularWaves" type="CanvasLayer"] +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_6bcgb") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/children/color_correction.tscn b/addons/post_processing/node/children/color_correction.tscn new file mode 100644 index 0000000..e978c23 --- /dev/null +++ b/addons/post_processing/node/children/color_correction.tscn @@ -0,0 +1,20 @@ +[gd_scene load_steps=3 format=3 uid="uid://q8472v8awese"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/color_correction.gdshader" id="1_cf4sj"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_nmxm8"] +shader = ExtResource("1_cf4sj") +shader_parameter/tint = Color(1, 1, 1, 1) +shader_parameter/brightness = 0.0 +shader_parameter/saturation = 0.0 + +[node name="ColorCorrection" type="CanvasLayer"] +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_nmxm8") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/addons/post_processing/node/children/fish_eye.tscn b/addons/post_processing/node/children/fish_eye.tscn new file mode 100644 index 0000000..bf97bd7 --- /dev/null +++ b/addons/post_processing/node/children/fish_eye.tscn @@ -0,0 +1,25 @@ +[gd_scene load_steps=3 format=3 uid="uid://c5qv7q54m4xn6"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/fish_eye.gdshader" id="1_eks6e"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_v56sw"] +shader = ExtResource("1_eks6e") +shader_parameter/aspect = 1.0 +shader_parameter/distortion = 1.0 +shader_parameter/radius = 1.0 +shader_parameter/alpha = 1.0 +shader_parameter/crop = 1.0 +shader_parameter/crop_color = Color(0, 0, 0, 1) + +[node name="FishEye" type="CanvasLayer"] +layer = 103 +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_v56sw") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/children/glitch.tscn b/addons/post_processing/node/children/glitch.tscn new file mode 100644 index 0000000..a4edafd --- /dev/null +++ b/addons/post_processing/node/children/glitch.tscn @@ -0,0 +1,24 @@ +[gd_scene load_steps=3 format=3 uid="uid://dwioerk4ps6rr"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/glitch.gdshader" id="1_3euvy"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_gdr74"] +shader = ExtResource("1_3euvy") +shader_parameter/range = 0.05 +shader_parameter/noiseQuality = 250.0 +shader_parameter/noiseIntensity = 0.0088 +shader_parameter/offsetIntensity = 0.03 +shader_parameter/colorOffsetIntensity = 1.3 + +[node name="Glitch" type="CanvasLayer"] +layer = 104 +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_gdr74") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/children/grain.tscn b/addons/post_processing/node/children/grain.tscn new file mode 100644 index 0000000..670d9ea --- /dev/null +++ b/addons/post_processing/node/children/grain.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=3 format=3 uid="uid://b2fkqs44w2304"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/grain.gdshader" id="1_wos36"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_wb4vw"] +render_priority = 0 +shader = ExtResource("1_wos36") + +[node name="Grain" type="CanvasLayer"] +visible = false + +[node name="ColorRect" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_wb4vw") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/children/kaleidoscope.gdshader b/addons/post_processing/node/children/kaleidoscope.gdshader new file mode 100644 index 0000000..08328b9 --- /dev/null +++ b/addons/post_processing/node/children/kaleidoscope.gdshader @@ -0,0 +1,309 @@ +shader_type canvas_item; + +// CC0: Truchet + Kaleidoscope FTW +// Bit of experimenting with kaleidoscopes and truchet turned out nice +// Quite similar to an earlier shader I did but I utilized a different truchet pattern this time + +uniform float animate_speed = 0.25; +uniform float resolution = 1.0; + +// License: Unknown, author: Unknown, found: don't remember +vec4 alphaBlend(vec4 back, vec4 front) { + float w = front.w + back.w*(1.0-front.w); + vec3 xyz = (front.xyz*front.w + back.xyz*back.w*(1.0-front.w))/w; + return w > 0.0 ? vec4(xyz, w) : vec4(0.0); + +} +mat2 ROT(float a){ + return mat2(vec2(cos(a),sin(a)),vec2(-sin(a),cos(a))); +} +float PCOS(float x){ + return 0.5+0.5*cos(x); +} + +// License: Unknown, author: Unknown, found: don't remember +vec3 alphaBlend34(vec3 back, vec4 front) { + return mix(back, front.xyz, front.w); +} + +// License: Unknown, author: Unknown, found: don't remember +float hashf(float co) { + return fract(sin(co*12.9898) * 13758.5453); +} + +// License: Unknown, author: Unknown, found: don't remember +float hashv(vec2 p) { + float a = dot(p, vec2 (127.1, 311.7)); + return fract(sin (a)*43758.5453123); +} + +// License: Unknown, author: Unknown, found: don't remember +float tanh_approx(float x) { + // Found this somewhere on the interwebs + // return tanh(x); + float x2 = x*x; + return clamp(x*(27.0 + x2)/(27.0+9.0*x2), -1.0, 1.0); +} + +// License: MIT, author: Inigo Quilez, found: https://www.iquilezles.org/www/articles/smin/smin.htm +float pmin(float a, float b, float k) { + float h = clamp(0.5+0.5*(b-a)/k, 0.0, 1.0); + return mix(b, a, h) - k*h*(1.0-h); +} + +// License: MIT, author: Inigo Quilez, found: https://www.iquilezles.org/www/index.htm +vec3 postProcess(vec3 col, vec2 q) { + col = clamp(col, 0.0, 1.0); + col = pow(col, vec3(1.0/2.2)); + col = col*0.6+0.4*col*col*(3.0-2.0*col); + col = mix(col, vec3(dot(col, vec3(0.33))), -0.4); + col *=0.5+0.5*pow(19.0*q.x*q.y*(1.0-q.x)*(1.0-q.y),0.7); + return col; +} + +float pmax(float a, float b, float k) { + return -pmin(-a, -b, k); +} + +float pabs(float a, float k) { + return pmax(a, -a, k); +} + +vec2 toPolar(vec2 p) { + return vec2(length(p), atan(p.y, p.x)); +} + +vec2 toRect(vec2 p) { + return vec2(p.x*cos(p.y), p.x*sin(p.y)); +} + +// License: MIT OR CC-BY-NC-4.0, author: mercury, found: https://mercury.sexy/hg_sdf/ +float modMirror1(inout float p, float size) { + float halfsize = size*0.5; + float c = floor((p + halfsize)/size); + p = mod(p + halfsize,size) - halfsize; + p *= mod(c, 2.0)*2.0 - 1.0; + return c; +} + +float smoothKaleidoscope(inout vec2 p, float sm, float rep) { + vec2 hp = p; + + vec2 hpp = toPolar(hp); + float rn = modMirror1(hpp.y, 2.0*PI/rep); + + float sa = PI/rep - pabs(PI/rep - abs(hpp.y), sm); + hpp.y = sign(hpp.y)*(sa); + + hp = toRect(hpp); + + p = hp; + + return rn; +} + +// The path function +vec3 offset(float z) { + float a = z; + vec2 p = -0.075*(vec2(cos(a), sin(a*sqrt(2.0))) + vec2(cos(a*sqrt(0.75)), sin(a*sqrt(0.5)))); + return vec3(p, z); +} + +// The derivate of the path function +// Used to generate where we are looking +vec3 doffset(float z) { + float eps = 0.1; + return 0.5*(offset(z + eps) - offset(z - eps))/eps; +} + +// The second derivate of the path function +// Used to generate tilt +vec3 ddoffset(float z) { + float eps = 0.1; + return 0.125*(doffset(z + eps) - doffset(z - eps))/eps; +} + +vec2 cell_df(float r, vec2 np, vec2 mp, vec2 off) { + + vec2 n0 = normalize(vec2(1.0, 1.0)); + vec2 n1 = normalize(vec2(1.0, -1.0)); + + np += off; + mp -= off; + + float hh = hashv(np); + float h0 = hh; + + vec2 p0 = mp; + p0 = abs(p0); + p0 -= 0.5; + float d0 = length(p0); + float d1 = abs(d0-r); + + float dot0 = dot(n0, mp); + float dot1 = dot(n1, mp); + + float d2 = abs(dot0); + float t2 = dot1; + d2 = abs(t2) > sqrt(0.5) ? d0 : d2; + + float d3 = abs(dot1); + float t3 = dot0; + d3 = abs(t3) > sqrt(0.5) ? d0 : d3; + + + float d = d0; + d = min(d, d1); + if (h0 > .85) + { + d = min(d, d2); + d = min(d, d3); + } + else if(h0 > 0.5) + { + d = min(d, d2); + } + else if(h0 > 0.15) + { + d = min(d, d3); + } + + return vec2(d, (d0-r)); +} + +vec2 truchet_df(float r, vec2 p) { + vec2 np = floor(p+0.5); + vec2 mp = fract(p+0.5) - 0.5; + return cell_df(r, np, mp, vec2(0.0)); +} + +vec4 plane(vec3 ro, vec3 rd, vec3 pp, vec3 off, float aa, float n) { + float h_ = hashf(n); + float h0 = fract(1777.0*h_); + float h1 = fract(2087.0*h_); + float h2 = fract(2687.0*h_); + float h3 = fract(3167.0*h_); + float h4 = fract(3499.0*h_); + + float l = length(pp - ro); + + vec3 hn; + vec2 p = (pp-off*vec3(1.0, 1.0, 0.0)).xy; + p *= ROT(0.5*(h4 - 0.5)*TIME); + float rep = 2.0*round(mix(5.0, 30.0, h2)); + float sm = 0.05*20.0/rep; + float sn = smoothKaleidoscope(p, sm, rep); + p *= ROT(2.0*PI*h0+0.025*TIME); + float z = mix(0.2, 0.4, h3); + p /= z; + p+=0.5+floor(h1*1000.0); + float tl = tanh_approx(0.33*l); + float r = mix(0.30, 0.45, PCOS(0.1*n)); + vec2 d2 = truchet_df(r, p); + d2 *= z; + float d = d2.x; + float lw =0.025*z; + d -= lw; + + vec3 col = mix(vec3(1.0), vec3(0.0), smoothstep(aa, -aa, d)); + col = mix(col, vec3(0.0), smoothstep(mix(1.0, -0.5, tl), 1.0, sin(PI*100.0*d))); +// float t0 = smoothstep(aa, -aa, -d2.y-lw); + col = mix(col, vec3(0.0), step(d2.y, 0.0)); + //float t = smoothstep(3.0*lw, 0.0, -d2.y); +// float t = smoothstep(aa, -aa, -d2.y-lw); + float t = smoothstep(aa, -aa, -d2.y-3.0*lw)*mix(0.5, 1.0, smoothstep(aa, -aa, -d2.y-lw)); + return vec4(col, t); +} + +vec3 skyColor(vec3 ro, vec3 rd) { + float d = pow(max(dot(rd, vec3(0.0, 0.0, 1.0)), 0.0), 20.0); + return vec3(d); +} + + +vec3 color(vec3 ww, vec3 uu, vec3 vv, vec3 ro, vec2 p){ + float lp = length(p); + vec2 np = p + 1.0/vec2(1920.0*resolution,1080.0*resolution) ; + float rdd = (2.0+1.0*tanh_approx(lp)); +// float rdd = 2.0; + vec3 rd = normalize(p.x*uu + p.y*vv + rdd*ww); + vec3 nrd = normalize(np.x*uu + np.y*vv + rdd*ww); + + float planeDist = 1.0-0.25; + int furthest = 6; + int fadeFrom = max(furthest-5, 0); + + float fadeDist = planeDist*float(furthest - fadeFrom); + float nz = floor(ro.z / planeDist); + + vec3 skyCol = skyColor(ro, rd); + + + vec4 acol = vec4(0.0); + float cutOff = 0.95; + bool cutOut = false; + + // Steps from nearest to furthest plane and accumulates the color + for (int i = 1; i <= furthest; ++i) { + float pz = planeDist*nz + planeDist*float(i); + + float pd = (pz - ro.z)/rd.z; + + if (pd > 0.0 && acol.w < cutOff) { + vec3 pp = ro + rd*pd; + vec3 npp = ro + nrd*pd; + + float aa = 3.0*length(pp - npp); + + vec3 off = offset(pp.z); + + vec4 pcol = plane(ro, rd, pp, off, aa, nz+float(i)); + + float nz1 = pp.z-ro.z; + float fadeIn = smoothstep(planeDist*float(furthest), planeDist*float(fadeFrom), nz1); + float fadeOut = smoothstep(0.0, planeDist*0.1, nz1); + pcol.xyz = mix(skyCol, pcol.xyz, fadeIn); + pcol.w *= fadeOut; + pcol = clamp(pcol, 0.0, 1.0); + + acol = alphaBlend(pcol, acol); + } else { + cutOut = true; + break; + } + + } + + vec3 col = alphaBlend34(skyCol, acol); +// To debug cutouts due to transparency +// col += cutOut ? vec3(1.0, -1.0, 0.0) : vec3(0.0); + return col; +} +vec3 effect(vec2 p, vec2 q) { + float tm = TIME*animate_speed; + vec3 ro = offset(tm); + vec3 dro = doffset(tm); + vec3 ddro = ddoffset(tm); + + vec3 ww = normalize(dro); + vec3 uu = normalize(cross(normalize(vec3(0.0,1.0,0.0)+ddro), ww)); + vec3 vv = normalize(cross(ww, uu)); + + vec3 col = color(ww, uu, vv, ro, p); + + return col; +} +void fragment(){ + + + + vec2 q = FRAGCOORD.xy/(1.0 / SCREEN_PIXEL_SIZE).xy; + vec2 p = -1. + 2. * q; + p.x *= (1.0 / SCREEN_PIXEL_SIZE).x/(1.0 / SCREEN_PIXEL_SIZE).y; + + vec3 col = effect(p, q); + col *= smoothstep(0.0, 4.0, TIME); + col = postProcess(col, q); + + COLOR = vec4(col, 1.0); +} \ No newline at end of file diff --git a/addons/post_processing/node/children/outline.gdshader b/addons/post_processing/node/children/outline.gdshader new file mode 100644 index 0000000..84f453e --- /dev/null +++ b/addons/post_processing/node/children/outline.gdshader @@ -0,0 +1,41 @@ +// NekotoArts YouTube: https://www.youtube.com/channel/UCD7K_FECPHTF0z5okAVlh0g +// Adapted from https://www.shadertoy.com/view/ldsfRn + +shader_type canvas_item; + +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap; + +uniform vec4 edge_color : source_color = vec4(0.0, 0.0, 0.0, 1.0); +uniform float threshold = 0.0; +uniform float blend = 0.01; + +float getGrayScale(sampler2D sampler, vec2 coods){ + vec4 color = texture(sampler,coods); + float gray = (color.r + color.g + color.b)/3.0; + return gray; +} + +void fragment(){ + vec2 delta = vec2(0.0,0.003); + vec2 iResolution = 1.0 / SCREEN_PIXEL_SIZE; + float m = max(iResolution.x,iResolution.y); + vec2 texCoords = SCREEN_UV; + + vec3 screen_color = texture(SCREEN_TEXTURE, SCREEN_UV).rgb; + + float c1y = getGrayScale(SCREEN_TEXTURE, texCoords.xy-delta/2.0); + float c2y = getGrayScale(SCREEN_TEXTURE, texCoords.xy+delta/2.0); + + float c1x = getGrayScale(SCREEN_TEXTURE, texCoords.xy-delta.yx/2.0); + float c2x = getGrayScale(SCREEN_TEXTURE, texCoords.xy+delta.yx/2.0); + + float dcdx = (c2x - c1x)/(delta.y*10.0); + float dcdy = (c2y - c1y)/(delta.y*10.0); + + vec2 dcdi = vec2(dcdx,dcdy); + float edge = length(dcdi)/10.0; + edge = 1.0 - edge; + edge = smoothstep(threshold, threshold + blend, edge); + + COLOR.rgb = mix(edge_color.rgb, screen_color.rgb, edge); +} \ No newline at end of file diff --git a/addons/post_processing/node/children/outline.tscn b/addons/post_processing/node/children/outline.tscn new file mode 100644 index 0000000..41833d5 --- /dev/null +++ b/addons/post_processing/node/children/outline.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=3 format=3 uid="uid://c0d4h1un0350r"] + +[ext_resource type="Shader" path="res://addons/post_processing/node/children/outline.gdshader" id="1_x8jvf"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_yuki3"] +shader = ExtResource("1_x8jvf") +shader_parameter/edge_color = Color(0, 0, 0, 1) +shader_parameter/threshold = 0.0 +shader_parameter/blend = 0.1 + +[node name="Outline" type="CanvasLayer"] +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_yuki3") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/children/palette.tscn b/addons/post_processing/node/children/palette.tscn new file mode 100644 index 0000000..0d096df --- /dev/null +++ b/addons/post_processing/node/children/palette.tscn @@ -0,0 +1,18 @@ +[gd_scene load_steps=4 format=3 uid="uid://b31wqmjq3q7ad"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/palette_limiter.gdshader" id="1_e4qfa"] +[ext_resource type="Texture2D" uid="uid://nf2dcuadvrh7" path="res://addons/post_processing/assets/interesting_palette.png" id="2_y1cuq"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_x8ge8"] +shader = ExtResource("1_e4qfa") +shader_parameter/palette = ExtResource("2_y1cuq") + +[node name="Palette" type="CanvasLayer"] + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_x8ge8") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 diff --git a/addons/post_processing/node/children/pixelate.tscn b/addons/post_processing/node/children/pixelate.tscn new file mode 100644 index 0000000..6db2a24 --- /dev/null +++ b/addons/post_processing/node/children/pixelate.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=3 format=3 uid="uid://bs1yan5h4eao8"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/pixelate.gdshader" id="1_yebq2"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_gfycf"] +shader = ExtResource("1_yebq2") +shader_parameter/pixelSize = 7 + +[node name="Pixelate" type="CanvasLayer"] +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_gfycf") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/children/screen_shake.tscn b/addons/post_processing/node/children/screen_shake.tscn new file mode 100644 index 0000000..d7a8f58 --- /dev/null +++ b/addons/post_processing/node/children/screen_shake.tscn @@ -0,0 +1,22 @@ +[gd_scene load_steps=3 format=3 uid="uid://b7k7vdwyhgqpd"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/screen_shake.gdshader" id="1_62rht"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_4rxg5"] +shader = ExtResource("1_62rht") +shader_parameter/ShakeStrength = 0.1 +shader_parameter/FactorA = Vector2(100, 100) +shader_parameter/FactorB = Vector2(1, 1) +shader_parameter/magnitude = Vector2(0.01, 0.01) + +[node name="ScreenShake" type="CanvasLayer"] +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_4rxg5") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/children/speed_lines.tscn b/addons/post_processing/node/children/speed_lines.tscn new file mode 100644 index 0000000..ed52456 --- /dev/null +++ b/addons/post_processing/node/children/speed_lines.tscn @@ -0,0 +1,36 @@ +[gd_scene load_steps=5 format=3 uid="uid://whsu0j72038r"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/speed_lines.gdshader" id="1_2cyj1"] + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_oyufo"] +noise_type = 3 +frequency = 0.212 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_yebuf"] +width = 1080 +height = 1080 +seamless = true +noise = SubResource("FastNoiseLite_oyufo") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_uouvn"] +shader = ExtResource("1_2cyj1") +shader_parameter/line_color = Color(1, 1, 1, 0.768627) +shader_parameter/line_count = 2.0 +shader_parameter/line_density = 0.056 +shader_parameter/line_faloff = 0.0 +shader_parameter/mask_size = 0.333 +shader_parameter/mask_edge = 0.372 +shader_parameter/animation_speed = 20.0 +shader_parameter/noise = SubResource("NoiseTexture2D_yebuf") + +[node name="SpeedLines" type="CanvasLayer"] +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_uouvn") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/children/vignette.tscn b/addons/post_processing/node/children/vignette.tscn new file mode 100644 index 0000000..a6259aa --- /dev/null +++ b/addons/post_processing/node/children/vignette.tscn @@ -0,0 +1,21 @@ +[gd_scene load_steps=3 format=3 uid="uid://crm7gskny246i"] + +[ext_resource type="Shader" path="res://addons/post_processing/shaders/vignette.gdshader" id="1_1fqty"] + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_jiuwk"] +shader = ExtResource("1_1fqty") +shader_parameter/vignette_intensity = 1.48 +shader_parameter/vignette_opacity = 1.0 +shader_parameter/vignette_rgb = Color(0, 0, 0, 1) + +[node name="Vignette" type="CanvasLayer"] +visible = false + +[node name="data" type="ColorRect" parent="."] +material = SubResource("ShaderMaterial_jiuwk") +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 diff --git a/addons/post_processing/node/post_process.gd b/addons/post_processing/node/post_process.gd new file mode 100644 index 0000000..05d97b3 --- /dev/null +++ b/addons/post_processing/node/post_process.gd @@ -0,0 +1,182 @@ +@tool +extends CanvasLayer + +@export_category("Post Process") +@export var configuration : PostProcessingConfiguration +@export var dynamically_update : bool = true + +func update_shaders() -> void: + if not configuration: + return + for child in get_children(): + var data : ColorRect = child.get_child(0) + if data: + _update_shader_parameters(child.name, data.material) + child.visible = _check_shader_visibility(child.name) + return + +func _update_shader_parameters( _name : String, _material : Material) -> void: + match _name: + "Palette": + _material.set_shader_parameter("palette", configuration.PalettePalette) + "Pixelate": + _material.set_shader_parameter("pixelSize", configuration.PixelatePixelSize) + "ColorCorrection": + _material.set_shader_parameter("tint", configuration.ColorCorrectionTint) + _material.set_shader_parameter("brightness", configuration.ColorCorrectionBrightness) + _material.set_shader_parameter("saturation", configuration.ColorCorrectionSaturation) + "ChromaticAberration": + _material.set_shader_parameter("offset", configuration.StrenghtCA) + "Blur": + _material.set_shader_parameter("lod", configuration.L_O_D) + "FishEye": + _material.set_shader_parameter("aspect", configuration.FishEyeAspect) + _material.set_shader_parameter("distortion", configuration.FishEyeDistortion) + _material.set_shader_parameter("radius", configuration.FishEyeRadius) + _material.set_shader_parameter("alpha", configuration.FishEyeAlpha) + _material.set_shader_parameter("crop", configuration.FishEyeCrop) + _material.set_shader_parameter("crop_color", configuration.FishEyeCropColor) + "Vignette": + _material.set_shader_parameter("vignette_intensity", configuration.VignetteIntensity) + _material.set_shader_parameter("vignette_opacity", configuration.VignetteOpacity) + _material.set_shader_parameter("vignette_rgb", configuration.VignetteR_G_B) + "Glitch": + _material.set_shader_parameter("range", configuration.GlitchRange) + _material.set_shader_parameter("noiseQuality", configuration.GlitchNoiseQuality) + _material.set_shader_parameter("noiseIntensity", configuration.GlitchIntenity) + _material.set_shader_parameter("offsetIntensity", configuration.GlitchOffset) + _material.set_shader_parameter("colorOffsetIntensity", configuration.GlitchColorOffset) + "Outline": + _material.set_shader_parameter("edge_color", configuration.OutlineColor) + _material.set_shader_parameter("threshold", configuration.OutlineThreshold) + _material.set_shader_parameter("blend", configuration.OutlineBlend) + "ScreenShake": + _material.set_shader_parameter("ShakeStrength", configuration.ScreenShakePower) + "AnalogMonitor": + _material.set_shader_parameter("res", configuration.AnalogMonitorResolution) + "Grain": + _material.set_shader_parameter("strength", configuration.GrainPower) + "CircularWaves": + _material.set_shader_parameter("amplitude", configuration.CircularWavesAmplitude) + _material.set_shader_parameter("frequency", configuration.CircularWavesFrequency) + _material.set_shader_parameter("rippleRate", configuration.CircularWavesRippleRate) + "SpeedLines": + _material.set_shader_parameter("line_color", configuration.SpeedLinesColor) + _material.set_shader_parameter("line_count", configuration.SpeedLinesCount) + _material.set_shader_parameter("line_density", configuration.SpeedLineDensity) + _material.set_shader_parameter("animation_speed", configuration.SpeedLineSpeed) + "Ascii": + _material.set_shader_parameter("ascii_size", configuration.ASCIISize) + "CRT": + _material.set_shader_parameter("overlay", configuration.overlay) + _material.set_shader_parameter("scanlines_opacity", configuration.scanlines_opacity) + _material.set_shader_parameter("scanlines_width", configuration.scanlines_width) + _material.set_shader_parameter("grille_opacity", configuration.grille_opacity) + _material.set_shader_parameter("pixelate", configuration.pixelate) + _material.set_shader_parameter("roll_size", configuration.roll_size) + _material.set_shader_parameter("roll_variation", configuration.roll_variation) + _material.set_shader_parameter("distort_intensity", configuration.distort_intensity) + _material.set_shader_parameter("noise_opacity", configuration.noise_opacity) + _material.set_shader_parameter("noise_speed", configuration.noise_speed) + _material.set_shader_parameter("static_noise_intensity", configuration.static_noise_intensity) + _material.set_shader_parameter("aberration", configuration.aberration) + _material.set_shader_parameter("brightness", configuration.brightness) + _material.set_shader_parameter("discolor", configuration.discolor) + _material.set_shader_parameter("warp_amount", configuration.warp_amount) + _material.set_shader_parameter("clip_warp", configuration.clip_warp) + _material.set_shader_parameter("vignette_intensity", configuration.vignette_intensity) + _material.set_shader_parameter("vignette_opacity", configuration.vignette_opacity) + + +func _check_shader_visibility(_name: String) -> bool: + if _name.begins_with("Palette"): + return true if configuration.Palette else false + if _name.begins_with("Pixelate"): + return true if configuration.Pixelate else false + if _name.begins_with("ColorCorrection"): + return true if configuration.ColorCorrection else false + if _name.begins_with("ChromaticAberration"): + return true if configuration.ChromaticAberration else false + + if _name.begins_with("Blur"): + return true if configuration.Blur else false + + if _name.begins_with("FishEye"): + return true if configuration.FishEye else false + + if _name.begins_with("Vignette"): + return true if configuration.Vignette else false + + if _name.begins_with("Glitch"): + return true if configuration.Glitch else false + + if _name.begins_with("Outline"): + return true if configuration.Outline else false + + if _name.begins_with("ScreenShake"): + return true if configuration.ScreenShake else false + + if _name.begins_with("AnalogMonitor"): + return true if configuration.AnalogMonitor else false + + if _name.begins_with("Grain"): + return true if configuration.Grain else false + + if _name.begins_with("CircularWaves"): + return true if configuration.CircularWaves else false + + if _name.begins_with("SpeedLines"): + return true if configuration.SpeedLines else false + + if _name.begins_with("Ascii"): + return true if configuration.ASCII else false + + if _name.begins_with("CRT"): + return true if configuration.CRT else false + # get_children() returning all _names leading Always to: + push_error("#Undefined type Post Processing addon - verify it has been properly integrated.") + return false # bad! + +func _enter_tree(): + + _add_canvas_layer_children("res://addons/post_processing/node/children/ChromaticAberration.tscn", "CA") + _add_canvas_layer_children("res://addons/post_processing/node/children/blur.tscn", "BL") + _add_canvas_layer_children("res://addons/post_processing/node/children/fish_eye.tscn", "FEYE") + _add_canvas_layer_children("res://addons/post_processing/node/children/vignette.tscn", "VIN") + _add_canvas_layer_children("res://addons/post_processing/node/children/glitch.tscn", "GLI") + _add_canvas_layer_children("res://addons/post_processing/node/children/outline.tscn", "OUT") + _add_canvas_layer_children("res://addons/post_processing/node/children/screen_shake.tscn", "SCR_SHK") + _add_canvas_layer_children("res://addons/post_processing/node/children/analog_monitor.tscn", "ANL_MON") + _add_canvas_layer_children("res://addons/post_processing/node/children/grain.tscn", "GRN") + _add_canvas_layer_children("res://addons/post_processing/node/children/circular_waves.tscn", "CIR_WAV") + _add_canvas_layer_children("res://addons/post_processing/node/children/speed_lines.tscn", "SDP_LIN") + _add_canvas_layer_children("res://addons/post_processing/node/children/ascii.tscn", "ASCII") + _add_canvas_layer_children("res://addons/post_processing/node/children/CRT.tscn", "CRT") + _add_canvas_layer_children("res://addons/post_processing/node/children/color_correction.tscn", "CC") + _add_canvas_layer_children("res://addons/post_processing/node/children/pixelate.tscn", "PXL") + _add_canvas_layer_children("res://addons/post_processing/node/children/palette.tscn", "PLT") + + update_shaders() + +func _add_canvas_layer_children(_path : String, _name: String) -> void: + var child_instance = load(_path).instantiate() + add_child(child_instance) + var material_instance = child_instance.get_children()[0].material.duplicate() + child_instance.get_children()[0].material = material_instance + print_debug("Successfully added child canvas-layer: " + _name + " to PostProcess addon node.") + +func _process(delta): + if not configuration: + return + if Engine.is_editor_hint(): + if dynamically_update: + update_shaders() + else: + if configuration.reload: + configuration.reload = false + update_shaders() + else: + update_shaders() + if configuration.reload: + configuration.reload = false + update_shaders() diff --git a/addons/post_processing/node/post_process.svg b/addons/post_processing/node/post_process.svg new file mode 100644 index 0000000..7d0b52c --- /dev/null +++ b/addons/post_processing/node/post_process.svg @@ -0,0 +1,9 @@ + + Projekt bez nazwy (2) + + + + + + \ No newline at end of file diff --git a/addons/post_processing/node/post_process.svg.import b/addons/post_processing/node/post_process.svg.import new file mode 100644 index 0000000..bb039eb --- /dev/null +++ b/addons/post_processing/node/post_process.svg.import @@ -0,0 +1,38 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://c76ob2amhl0ln" +path="res://.godot/imported/post_process.svg-a28c497815b0e679908309d25a9b379d.ctex" +metadata={ +"has_editor_variant": true, +"vram_texture": false +} + +[deps] + +source_file="res://addons/post_processing/node/post_process.svg" +dest_files=["res://.godot/imported/post_process.svg-a28c497815b0e679908309d25a9b379d.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 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=true diff --git a/addons/post_processing/plugin.cfg b/addons/post_processing/plugin.cfg new file mode 100644 index 0000000..ad4350d --- /dev/null +++ b/addons/post_processing/plugin.cfg @@ -0,0 +1,7 @@ +[plugin] + +name="PostProcessing" +description="Simple Post Processing Plugin" +author="Korin" +version="0.1.0" +script="plugin.gd" diff --git a/addons/post_processing/plugin.gd b/addons/post_processing/plugin.gd new file mode 100644 index 0000000..beda896 --- /dev/null +++ b/addons/post_processing/plugin.gd @@ -0,0 +1,10 @@ +@tool +extends EditorPlugin + + +func _enter_tree(): + add_custom_type("PostProcess", "CanvasLayer", load("res://addons/post_processing/node/post_process.gd"), load("res://addons/post_processing/node/post_process.svg")) + + +func _exit_tree(): + remove_custom_type("PostProcess") diff --git a/addons/post_processing/resource/fish_eye_example.tres b/addons/post_processing/resource/fish_eye_example.tres new file mode 100644 index 0000000..d70d980 --- /dev/null +++ b/addons/post_processing/resource/fish_eye_example.tres @@ -0,0 +1,49 @@ +[gd_resource type="Resource" script_class="PostProcessingConfiguration" load_steps=2 format=3 uid="uid://dg8amcb0jcyas"] + +[ext_resource type="Script" path="res://addons/post_processing/resource/post_processing_configuration.gd" id="1_3y12k"] + +[resource] +script = ExtResource("1_3y12k") +reload = false +ASCII = false +ASCIISize = Vector2(4, 9) +ChromaticAberration = false +StrenghtCA = 1.0 +Blur = false +L_O_D = 1.0 +FishEye = true +FishEyeAspect = 1.0 +FishEyeDistortion = 0.5 +FishEyeRadius = 1.0 +FishEyeAlpha = 1.0 +FishEyeCrop = 1.0 +FishEyeCropColor = Color(0, 0, 0, 1) +Vignette = false +VignetteIntensity = 0.4 +VignetteOpacity = 0.5 +VignetteR_G_B = Color(0, 0, 0, 1) +Glitch = false +GlitchRange = 0.05 +GlitchNoiseQuality = 250.0 +GlitchIntenity = 0.0088 +GlitchOffset = 0.03 +GlitchColorOffset = 1.3 +Outline = false +OutlineColor = Color(0, 0, 0, 1) +OutlineThreshold = 0.0 +OutlineBlend = 0.01 +ScreenShake = false +ScreenShakePower = 0.1 +AnalogMonitor = false +AnalogMonitorResolution = Vector2(256, 256) +Grain = false +GrainPower = 75 +CircularWaves = false +CircularWavesAmplitude = 2.0 +CircularWavesFrequency = 12.69 +CircularWavesRippleRate = 9.2 +SpeedLines = false +SpeedLinesColor = Color(1, 1, 1, 1) +SpeedLinesCount = 2 +SpeedLineDensity = 0.072 +SpeedLineSpeed = 20 diff --git a/addons/post_processing/resource/no_effects_example.tres b/addons/post_processing/resource/no_effects_example.tres new file mode 100644 index 0000000..3348330 --- /dev/null +++ b/addons/post_processing/resource/no_effects_example.tres @@ -0,0 +1,49 @@ +[gd_resource type="Resource" script_class="PostProcessingConfiguration" load_steps=2 format=3 uid="uid://c0dsfxhwb8bwe"] + +[ext_resource type="Script" path="res://addons/post_processing/resource/post_processing_configuration.gd" id="1_6y0uy"] + +[resource] +script = ExtResource("1_6y0uy") +reload = false +ASCII = false +ASCIISize = Vector2(4, 9) +ChromaticAberration = false +StrenghtCA = 1.0 +Blur = false +L_O_D = 1.0 +FishEye = false +FishEyeAspect = 1.0 +FishEyeDistortion = 1.0 +FishEyeRadius = 1.0 +FishEyeAlpha = 1.0 +FishEyeCrop = 1.0 +FishEyeCropColor = Color(0, 0, 0, 1) +Vignette = false +VignetteIntensity = 0.4 +VignetteOpacity = 0.5 +VignetteR_G_B = Color(0, 0, 0, 1) +Glitch = false +GlitchRange = 0.05 +GlitchNoiseQuality = 250.0 +GlitchIntenity = 0.0088 +GlitchOffset = 0.03 +GlitchColorOffset = 1.3 +Outline = false +OutlineColor = Color(0, 0, 0, 1) +OutlineThreshold = 0.0 +OutlineBlend = 0.01 +ScreenShake = false +ScreenShakePower = 0.1 +AnalogMonitor = false +AnalogMonitorResolution = Vector2(256, 256) +Grain = false +GrainPower = 75 +CircularWaves = false +CircularWavesAmplitude = 2.0 +CircularWavesFrequency = 12.69 +CircularWavesRippleRate = 9.2 +SpeedLines = false +SpeedLinesColor = Color(1, 1, 1, 1) +SpeedLinesCount = 2 +SpeedLineDensity = 0.072 +SpeedLineSpeed = 20 diff --git a/addons/post_processing/resource/post_processing_configuration.gd b/addons/post_processing/resource/post_processing_configuration.gd new file mode 100644 index 0000000..f961e51 --- /dev/null +++ b/addons/post_processing/resource/post_processing_configuration.gd @@ -0,0 +1,242 @@ +class_name PostProcessingConfiguration extends Resource + +# post-processing-config based system by loufe +@export_group("Settings") +@export var reload: bool +@export_group("Visual Effects") +@export_subgroup("ASCII (No Color)") +@export var ASCII: bool +@export var ASCIISize: Vector2 = Vector2(4,9): + set(value): + ASCIISize = value + reload = true +@export_subgroup("Chromatic Aberration") +@export var ChromaticAberration: bool +@export var StrenghtCA: float = 1: + set(value): + StrenghtCA = value + reload = true +@export_subgroup("Blur") +@export var Blur: bool +@export_range(0.0, 5) var L_O_D = 1.0: + set(value): + L_O_D = value + reload = true +@export_subgroup("Fish Eye") +@export var FishEye: bool +@export var FishEyeAspect = 1.0: + set(value): + FishEyeAspect = value + reload = true +@export var FishEyeDistortion = 1.0: + set(value): + FishEyeDistortion = value + reload = true +@export var FishEyeRadius = 1.0: + set(value): + FishEyeRadius = value + reload = true +@export var FishEyeAlpha = 1.0: + set(value): + FishEyeAlpha = value + reload = true +@export var FishEyeCrop = 1.0: + set(value): + FishEyeCrop = value + reload = true +@export var FishEyeCropColor = Color.BLACK: + set(value): + FishEyeCropColor = value + reload = true +@export_subgroup("Vignette") +@export var Vignette: bool +@export var VignetteIntensity = 0.4: + set(value): + VignetteIntensity = value + reload = true +@export_range(0.0, 1.0) var VignetteOpacity = 0.5: + set(value): + VignetteOpacity = value + reload = true +@export var VignetteR_G_B: Color = Color(0.0, 0.0, 0.0, 1.0): + set(value): + VignetteR_G_B = value + reload = true +@export_subgroup("Glitch") +@export var Glitch: bool +@export_range(0.0, 0.1, 0.005) var GlitchRange = 0.05: + set(value): + GlitchRange = value + reload = true +@export_range(0.0, 300, 0.1) var GlitchNoiseQuality = 250.0: + set(value): + GlitchNoiseQuality = value + reload = true +@export_range(-0.6, 0.6, 0.0010) var GlitchIntenity = 0.0088: + set(value): + GlitchIntenity = value + reload = true +@export_range(-0.1, 0.1, 0.001) var GlitchOffset = 0.03: + set(value): + GlitchOffset = value + reload = true +@export_range(0.0, 5.0, 0.001) var GlitchColorOffset = 1.3: + set(value): + GlitchColorOffset = value + reload = true +@export_subgroup("Outline") +@export var Outline: bool +@export var OutlineColor: Color = Color(0.0, 0.0, 0.0, 1.0): + set(value): + OutlineColor = value + reload = true +@export_range(0.0, 1.0) var OutlineThreshold = 0.0: + set(value): + OutlineThreshold = value + reload = true +@export_range(0.0, 1.0) var OutlineBlend = 0.01: + set(value): + OutlineBlend = value + reload = true +@export_subgroup("Grain") +@export var Grain: bool +@export_range(0, 150, 0.1) var GrainPower = 75: + set(value): + GrainPower = value + reload = true +@export_subgroup("Circular Waves") +@export var CircularWaves: bool +@export_range(0,2, 0.01) var CircularWavesAmplitude = 2.0: + set(value): + CircularWavesAmplitude = value + reload = true +@export_range(0, 15, 0.01) var CircularWavesFrequency = 12.69: + set(value): + CircularWavesFrequency = value + reload = true +@export_range(0.5, 150.0, 0.1) var CircularWavesRippleRate = 9.2: + set(value): + CircularWavesRippleRate = value + reload = true +@export_subgroup("Speed Lines") +@export var SpeedLines: bool +@export var SpeedLinesColor: Color = Color.WHITE: + set(value): + SpeedLinesColor = value + reload = true +@export_range(0,2, 0.05) var SpeedLinesCount = 2: + set(value): + SpeedLinesCount = value + reload = true +@export_range(0.0, 1.0) var SpeedLineDensity = 0.072: + set(value): + SpeedLineDensity = value + reload = true +@export_range(1.0, 40.0, 1.0) var SpeedLineSpeed = 20: + set(value): + SpeedLineSpeed = value + reload = true + +@export_group("Display") +@export_subgroup("Color Correction") +@export var ColorCorrection: bool +@export var ColorCorrectionTint : Color +@export_range(-1.0, 1.0) var ColorCorrectionBrightness : float = 0 +@export_range(-1.0, 1.0) var ColorCorrectionSaturation : float = 0 +@export_subgroup("Palette") +@export var Palette : bool +@export var PalettePalette : Texture2D +@export_subgroup("Pixelate") +@export var Pixelate : bool +@export_range(0, 64) var PixelatePixelSize = 8 +@export_subgroup("CRT") +@export var CRT: bool +@export var overlay : bool = false: + set(value): + overlay = value + reload = true +@export_range(0.0, 1.0) var scanlines_opacity : float = 0.4: + set(value): + scanlines_opacity = value + reload = true +@export_range(0.0, 0.5) var scanlines_width : float = 0.25: + set(value): + scanlines_width = value + reload = true +@export_range(0.0, 1.0) var grille_opacity : float = 0.3: + set(value): + grille_opacity = value + reload = true +@export var pixelate : bool = true: + set(value): + pixelate = value + reload = true +@export var roll_speed : float = 8.0: + set(value): + roll_speed = value + reload = true +@export_range(0.0, 100.0) var roll_size : float = 15.0: + set(value): + roll_size = value + reload = true +@export_range(0.1, 5.0) var roll_variation : float = 1.8: + set(value): + roll_variation = value + reload = true +@export_range(0.0, 0.2) var distort_intensity : float = 0.05: + set(value): + distort_intensity = value + reload = true +@export_range(0.0, 1.0) var noise_opacity : float = 0.4: + set(value): + noise_opacity = value + reload = true +@export var noise_speed : float = 5.0: + set(value): + noise_speed = value + reload = true +@export_range(0.0, 1.0) var static_noise_intensity : float = 0.06: + set(value): + static_noise_intensity = value + reload = true +@export_range(-1.0, 1.0) var aberration : float = 0.03: + set(value): + aberration = value + reload = true +@export var brightness : float = 1.4: + set(value): + brightness = value + reload = true +@export var discolor : bool = true: + set(value): + discolor = value + reload = true +@export_range(0.0, 5.0) var warp_amount : float = 1.0: + set(value): + warp_amount = value + reload = true +@export var clip_warp : bool = false: + set(value): + clip_warp = value + reload = true +@export var vignette_intensity : float = 0.4: + set(value): + vignette_intensity = value + reload = true +@export_range(0.0, 1.0) var vignette_opacity : float = 0.5: + set(value): + vignette_opacity = value + reload = true +@export_subgroup("Analog Monitor") +@export var AnalogMonitor: bool +@export var AnalogMonitorResolution = Vector2(256, 256): + set(value): + AnalogMonitorResolution = value + reload = true +@export_group("Other") +@export_subgroup("Screen Shake") +@export var ScreenShake: bool +@export var ScreenShakePower = 0.1: + set(value): + ScreenShakePower = value + reload = true diff --git a/addons/post_processing/shaders/CLREDIT.gdshaderinc b/addons/post_processing/shaders/CLREDIT.gdshaderinc new file mode 100644 index 0000000..e69de29 diff --git a/addons/post_processing/shaders/CRT.gdshader b/addons/post_processing/shaders/CRT.gdshader new file mode 100644 index 0000000..45f6061 --- /dev/null +++ b/addons/post_processing/shaders/CRT.gdshader @@ -0,0 +1,230 @@ +/* +Shader from Godot Shaders - the free shader library. +godotshaders.com/shader/VHS-and-CRT-monitor-effect + +This shader is under CC0 license. Feel free to use, improve and +change this shader according to your needs and consider sharing +the modified result to godotshaders.com. +*/ + +shader_type canvas_item; + +//*** IMPORTANT! ***/ +// - If you are using this shader to affect the node it is applied to set 'overlay' to false (unchecked in the instepctor). +// - If you are using this shader as an overlay, and want the shader to affect the nodes below in the Scene hierarchy, +// set 'overlay' to true (checked in the inspector). +// On Mac there is potentially a bug causing this to not work properly. If that is the case and you want to use the shader as an overlay +// change all "overlay ? SCREEN_TEXTURE : TEXTURE" to only "SCREEN_TEXTURE" on lines 129-140, and "vec2 uv = overlay ? warp(SCREEN_UV) : warp(UV);" +// to "vec2 uv = warp(SCREEN_UV);" on line 98. +uniform bool overlay = false; +uniform sampler2D SCREEN_TEXTURE : source_color, hint_screen_texture, filter_nearest; + +uniform float scanlines_opacity : hint_range(0.0, 1.0) = 0.4; +uniform float scanlines_width : hint_range(0.0, 0.5) = 0.25; +uniform float grille_opacity : hint_range(0.0, 1.0) = 0.3; +uniform vec2 resolution = vec2(640.0, 480.0); // Set the number of rows and columns the texture will be divided in. Scanlines and grille will make a square based on these values + +uniform bool pixelate = true; // Fill each square ("pixel") with a sampled color, creating a pixel look and a more accurate representation of how a CRT monitor would work. + +uniform bool roll = true; +uniform float roll_speed = 8.0; // Positive values are down, negative are up +uniform float roll_size : hint_range(0.0, 100.0) = 15.0; +uniform float roll_variation : hint_range(0.1, 5.0) = 1.8; // This valie is not an exact science. You have to play around with the value to find a look you like. How this works is explained in the code below. +uniform float distort_intensity : hint_range(0.0, 0.2) = 0.05; // The distortion created by the rolling effect. + +uniform float noise_opacity : hint_range(0.0, 1.0) = 0.4; +uniform float noise_speed = 5.0; // There is a movement in the noise pattern that can be hard to see first. This sets the speed of that movement. + +uniform float static_noise_intensity : hint_range(0.0, 1.0) = 0.06; + +uniform float aberration : hint_range(-1.0, 1.0) = 0.03; // Chromatic aberration, a distortion on each color channel. +uniform float brightness = 1.4; // When adding scanline gaps and grille the image can get very dark. Brightness tries to compensate for that. +uniform bool discolor = true; // Add a discolor effect simulating a VHS + +uniform float warp_amount :hint_range(0.0, 5.0) = 1.0; // Warp the texture edges simulating the curved glass of a CRT monitor or old TV. +uniform bool clip_warp = false; + +uniform float vignette_intensity = 0.4; // Size of the vignette, how far towards the middle it should go. +uniform float vignette_opacity : hint_range(0.0, 1.0) = 0.5; + +// Used by the noise functin to generate a pseudo random value between 0.0 and 1.0 +vec2 random(vec2 uv){ + uv = vec2( dot(uv, vec2(127.1,311.7) ), + dot(uv, vec2(269.5,183.3) ) ); + return -1.0 + 2.0 * fract(sin(uv) * 43758.5453123); +} + +// Generate a Perlin noise used by the distortion effects +float noise(vec2 uv) { + vec2 uv_index = floor(uv); + vec2 uv_fract = fract(uv); + + vec2 blur = smoothstep(0.0, 1.0, uv_fract); + + return mix( mix( dot( random(uv_index + vec2(0.0,0.0) ), uv_fract - vec2(0.0,0.0) ), + dot( random(uv_index + vec2(1.0,0.0) ), uv_fract - vec2(1.0,0.0) ), blur.x), + mix( dot( random(uv_index + vec2(0.0,1.0) ), uv_fract - vec2(0.0,1.0) ), + dot( random(uv_index + vec2(1.0,1.0) ), uv_fract - vec2(1.0,1.0) ), blur.x), blur.y) * 0.5 + 0.5; +} + +// Takes in the UV and warps the edges, creating the spherized effect +vec2 warp(vec2 uv){ + vec2 delta = uv - 0.5; + float delta2 = dot(delta.xy, delta.xy); + float delta4 = delta2 * delta2; + float delta_offset = delta4 * warp_amount; + + return uv + delta * delta_offset; +} + +// Adds a black border to hide stretched pixel created by the warp effect +float border (vec2 uv){ + float radius = min(warp_amount, 0.08); + radius = max(min(min(abs(radius * 2.0), abs(1.0)), abs(1.0)), 1e-5); + vec2 abs_uv = abs(uv * 2.0 - 1.0) - vec2(1.0, 1.0) + radius; + float dist = length(max(vec2(0.0), abs_uv)) / radius; + float square = smoothstep(0.96, 1.0, dist); + return clamp(1.0 - square, 0.0, 1.0); +} + +// Adds a vignette shadow to the edges of the image +float vignette(vec2 uv){ + uv *= 1.0 - uv.xy; + float vignette = uv.x * uv.y * 15.0; + return pow(vignette, vignette_intensity * vignette_opacity); +} + +void fragment() +{ + vec2 uv = overlay ? warp(SCREEN_UV) : warp(UV); // Warp the uv. uv will be used in most cases instead of UV to keep the warping + vec2 text_uv = uv; + vec2 roll_uv = vec2(0.0); + float time = roll ? TIME : 0.0; + + + // Pixelate the texture based on the given resolution. + if (pixelate) + { + text_uv = ceil(uv * resolution) / resolution; + } + + // Create the rolling effect. We need roll_line a bit later to make the noise effect. + // That is why this runs if roll is true OR noise_opacity is over 0. + float roll_line = 0.0; + if (roll || noise_opacity > 0.0) + { + // Create the areas/lines where the texture will be distorted. + roll_line = smoothstep(0.3, 0.9, sin(uv.y * roll_size - (time * roll_speed) ) ); + // Create more lines of a different size and apply to the first set of lines. This creates a bit of variation. + roll_line *= roll_line * smoothstep(0.3, 0.9, sin(uv.y * roll_size * roll_variation - (time * roll_speed * roll_variation) ) ); + // Distort the UV where where the lines are + roll_uv = vec2(( roll_line * distort_intensity * (1.-UV.x)), 0.0); + } + + vec4 text; + if (roll) + { + // If roll is true distort the texture with roll_uv. The texture is split up into RGB to + // make some chromatic aberration. We apply the aberration to the red and green channels accorging to the aberration parameter + // and intensify it a bit in the roll distortion. + text.r = texture(SCREEN_TEXTURE, text_uv + roll_uv * 0.8 + vec2(aberration, 0.0) * .1).r; + text.g = texture(SCREEN_TEXTURE, text_uv + roll_uv * 1.2 - vec2(aberration, 0.0) * .1 ).g; + text.b = texture(SCREEN_TEXTURE, text_uv + roll_uv).b; + text.a = 1.0; + } + else + { + // If roll is false only apply the aberration without any distorion. The aberration values are very small so the .1 is only + // to make the slider in the Inspector less sensitive. + text.r = texture(SCREEN_TEXTURE, text_uv + vec2(aberration, 0.0) * .1).r; + text.g = texture(SCREEN_TEXTURE, text_uv - vec2(aberration, 0.0) * .1).g; + text.b = texture(SCREEN_TEXTURE, text_uv).b; + text.a = 1.0; + } + + float r = text.r; + float g = text.g; + float b = text.b; + + uv = warp(UV); + + // CRT monitors don't have pixels but groups of red, green and blue dots or lines, called grille. We isolate the texture's color channels + // and divide it up in 3 offsetted lines to show the red, green and blue colors next to each other, with a small black gap between. + if (grille_opacity > 0.0){ + + float g_r = smoothstep(0.85, 0.95, abs(sin(uv.x * (resolution.x * 3.14159265)))); + r = mix(r, r * g_r, grille_opacity); + + float g_g = smoothstep(0.85, 0.95, abs(sin(1.05 + uv.x * (resolution.x * 3.14159265)))); + g = mix(g, g * g_g, grille_opacity); + + float b_b = smoothstep(0.85, 0.95, abs(sin(2.1 + uv.x * (resolution.x * 3.14159265)))); + b = mix(b, b * b_b, grille_opacity); + + } + + // Apply the grille to the texture's color channels and apply Brightness. Since the grille and the scanlines (below) make the image very dark you + // can compensate by increasing the brightness. + text.r = clamp(r * brightness, 0.0, 1.0); + text.g = clamp(g * brightness, 0.0, 1.0); + text.b = clamp(b * brightness, 0.0, 1.0); + + // Scanlines are the horizontal lines that make up the image on a CRT monitor. + // Here we are actual setting the black gap between each line, which I guess is not the right definition of the word, but you get the idea + float scanlines = 0.5; + if (scanlines_opacity > 0.0) + { + // Same technique as above, create lines with sine and applying it to the texture. Smoothstep to allow setting the line size. + scanlines = smoothstep(scanlines_width, scanlines_width + 0.5, abs(sin(uv.y * (resolution.y * 3.14159265)))); + text.rgb = mix(text.rgb, text.rgb * vec3(scanlines), scanlines_opacity); + } + + // Apply the banded noise. + if (noise_opacity > 0.0) + { + // Generate a noise pattern that is very stretched horizontally, and animate it with noise_speed + float noise = smoothstep(0.4, 0.5, noise(uv * vec2(2.0, 200.0) + vec2(10.0, (TIME * (noise_speed))) ) ); + + // We use roll_line (set above) to define how big the noise should be vertically (multiplying cuts off all black parts). + // We also add in some basic noise with random() to break up the noise pattern above. The noise is sized according to + // the resolution value set in the inspector. If you don't like this look you can + // change "ceil(uv * resolution) / resolution" to only "uv" to make it less pixelated. Or multiply resolution with som value + // greater than 1.0 to make them smaller. + roll_line *= noise * scanlines * clamp(random((ceil(uv * resolution) / resolution) + vec2(TIME * 0.8, 0.0)).x + 0.8, 0.0, 1.0); + // Add it to the texture based on noise_opacity + text.rgb = clamp(mix(text.rgb, text.rgb + roll_line, noise_opacity), vec3(0.0), vec3(1.0)); + } + + // Apply static noise by generating it over the whole screen in the same way as above + if (static_noise_intensity > 0.0) + { + text.rgb += clamp(random((ceil(uv * resolution) / resolution) + fract(TIME)).x, 0.0, 1.0) * static_noise_intensity; + } + + // Apply a black border to hide imperfections caused by the warping. + // Also apply the vignette + text.rgb *= border(uv); + text.rgb *= vignette(uv); + // Hides the black border and make that area transparent. Good if you want to add the the texture on top an image of a TV or monitor. + if (clip_warp) + { + text.a = border(uv); + } + + // Apply discoloration to get a VHS look (lower saturation and higher contrast) + // You can play with the values below or expose them in the Inspector. + float saturation = 0.5; + float contrast = 1.2; + if (discolor) + { + // Saturation + vec3 greyscale = vec3(text.r + text.g + text.b) / 3.; + text.rgb = mix(text.rgb, greyscale, saturation); + + // Contrast + float midpoint = pow(0.5, 2.2); + text.rgb = (text.rgb - vec3(midpoint)) * contrast + midpoint; + } + + COLOR = text; +} \ No newline at end of file diff --git a/addons/post_processing/shaders/LensFlares.gdshader b/addons/post_processing/shaders/LensFlares.gdshader new file mode 100644 index 0000000..e908e46 --- /dev/null +++ b/addons/post_processing/shaders/LensFlares.gdshader @@ -0,0 +1,93 @@ +shader_type canvas_item; +render_mode blend_mix; + +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap; + +uniform vec2 sun_position = vec2(0.0); +uniform vec3 tint = vec3(1.4,1.2,1.0); +uniform sampler2D noise_texture; + +float noise_float(float t, vec2 texResolution) +{ + return texture(noise_texture,vec2(t,0.0)/texResolution).x; +} +float noise_vec2(vec2 t, vec2 texResolution) +{ + return texture(noise_texture,t/texResolution).x; +} + +vec3 lensflare(vec2 uv,vec2 pos, vec2 texResolution) +{ + vec2 main = uv-pos; + vec2 uvd = uv*(length(uv)); + + float ang = atan(main.x,main.y); + float dist = length(main); + dist = pow(dist,0.1); + + float n = noise_vec2(vec2(ang*16.0,dist*32.0), texResolution); + + // Do not need an artificial sun + //float f0 = 1.0/(length(uv-pos)*16.0+1.0); + //f0 = f0 + f0*(sin(noise_float(sin(ang*2.+pos.x)*4.0 - cos(ang*3.+pos.y), texResolution)*16.)*.1 + dist*.1 + .8); + + float f1 = max(0.01-pow(length(uv+1.2*pos),1.9),.0)*7.0; + + float f2 = max(1.0/(1.0+32.0*pow(length(uvd+0.8*pos),2.0)),.0)*00.25; + float f22 = max(1.0/(1.0+32.0*pow(length(uvd+0.85*pos),2.0)),.0)*00.23; + float f23 = max(1.0/(1.0+32.0*pow(length(uvd+0.9*pos),2.0)),.0)*00.21; + + vec2 uvx = mix(uv,uvd,-0.5); + + float f4 = max(0.01-pow(length(uvx+0.4*pos),2.4),.0)*6.0; + float f42 = max(0.01-pow(length(uvx+0.45*pos),2.4),.0)*5.0; + float f43 = max(0.01-pow(length(uvx+0.5*pos),2.4),.0)*3.0; + + uvx = mix(uv,uvd,-.4); + + float f5 = max(0.01-pow(length(uvx+0.2*pos),5.5),.0)*2.0; + float f52 = max(0.01-pow(length(uvx+0.4*pos),5.5),.0)*2.0; + float f53 = max(0.01-pow(length(uvx+0.6*pos),5.5),.0)*2.0; + + uvx = mix(uv,uvd,-0.5); + + float f6 = max(0.01-pow(length(uvx-0.3*pos),1.6),.0)*6.0; + float f62 = max(0.01-pow(length(uvx-0.325*pos),1.6),.0)*3.0; + float f63 = max(0.01-pow(length(uvx-0.35*pos),1.6),.0)*5.0; + + vec3 c = vec3(.0); + + c.r+=f2+f4+f5+f6; c.g+=f22+f42+f52+f62; c.b+=f23+f43+f53+f63; + c = c*1.3 - vec3(length(uvd)*.05); + + // Do not need an artificial sun + //c+=vec3(f0); + + return c; +} + +vec3 cc(vec3 color, float factor,float factor2) // color modifier +{ + float w = color.x+color.y+color.z; + return mix(color,vec3(w)*factor,w*factor2); +} + +void fragment() +{ + vec2 texResolution = 1.0 / TEXTURE_PIXEL_SIZE; + vec2 resolution = 1.0 / SCREEN_PIXEL_SIZE; + + vec2 uv = FRAGCOORD.xy / resolution.xy - 0.5; + uv.x *= resolution.x/resolution.y; //fix aspect ratio + vec2 mouse = (sun_position.xy / resolution.xy) - vec2(0.5, 0.5); + mouse.x *= resolution.x / resolution.y; //fix aspect ratio + + vec4 previousColor = texture(SCREEN_TEXTURE, SCREEN_UV); + + vec3 color = previousColor.rgb; + + color += tint * lensflare(uv, mouse.xy, texResolution); + color -= noise_vec2(FRAGCOORD.xy, texResolution)*.015; + color = cc(color,.5,.1); + COLOR = vec4(color,1.0); +} \ No newline at end of file diff --git a/addons/post_processing/shaders/analog_monitor.gdshader b/addons/post_processing/shaders/analog_monitor.gdshader new file mode 100644 index 0000000..da32851 --- /dev/null +++ b/addons/post_processing/shaders/analog_monitor.gdshader @@ -0,0 +1,278 @@ +//SHADER ORIGINALY CREADED BY "TimothyLottes" FROM SHADERTOY +//PORTED AND MODIFYED TO GODOT BY AHOPNESS (@ahopness) +//LICENSE : CC0 +//COMATIBLE WITH : GLES2, GLES3, WEBGL +//SHADERTOY LINK : https://www.shadertoy.com/view/MsjXzh + +// PUBLIC DOMAIN CRT STYLED SCAN-LINE SHADER +// +// by Timothy Lottes +// +// This is more along the style of a really good CGA arcade monitor. +// With RGB inputs instead of NTSC. +// The shadow mask example has the mask rotated 90 degrees for less chromatic aberration. +// +// Left it unoptimized to show the theory behind the algorithm. +// +// It is an example what I personally would want as a display option for pixel art games. +// Please take and use, change, or whatever. + +shader_type canvas_item; + +// Emulated input resolution. +uniform vec2 res; + +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap; + +// Mask type +// 0 = Very compressed TV style shadow mask +// 1 = Stretched VGA style shadow mask (same as prior shaders) +// 2 = VGA style shadow mask +uniform int mask_type :hint_range(0, 2) = 0; + +// Bloom Type +// 0 = Normalized exposure +// 1 = Aditive bloom +// 2 = No Bloom +uniform int bloom_type :hint_range(0, 2) = 0; + +// Hardness of scanline. +// -8.0 = soft +// -16.0 = medium +uniform float hardScan :hint_range(-12.0, -1.0) = -8.0; + +// Hardness of pixels in scanline. +// -2.0 = soft +// -4.0 = hard +uniform float hardPix :hint_range(-4.0, 0.0) = -2.0; + +// Hardness of short vertical bloom. +// -1.0 = wide to the point of clipping (bad) +// -1.5 = wide +// -4.0 = not very wide at all +uniform float hardBloomScan :hint_range(-4.0, 0.0) = -2.0; + +// Hardness of short horizontal bloom. +// -0.5 = wide to the point of clipping (bad) +// -1.0 = wide +// -2.0 = not very wide at all +uniform float hardBloomPix :hint_range(-2.0, 0.0) = -1.5; + +// Amount of small bloom effect. +// 1.0/1.0 = only bloom +// 1.0/16.0 = what I think is a good amount of small bloom +// 0.0 = no bloom +uniform float bloomAmount :hint_range(1.0, 16.0) = 16.0; + +// Display warp. +// 0.0 = none +// 1.0/8.0 = extreme +uniform vec2 warp = vec2(64.0, 24.0); + +// Amount of shadow mask. +uniform float maskDark :hint_range(0.0, 1.0) = 0.5; +uniform float maskLight :hint_range(1.0, 2.0) = 1.5; + +//------------------------------------------------------------------------ + +// sRGB to Linear. +// Assuing using sRGB typed textures this should not be needed. +float ToLinear1(float c){ return(c <= 0.04045) ? c / 12.92 : pow((c + 0.055) / 1.055, 2.4); } +vec3 ToLinear(vec3 c){ return vec3(ToLinear1(c.r), ToLinear1(c.g), ToLinear1(c.b)); } + +// Linear to sRGB. +// Assuing using sRGB typed textures this should not be needed. +float ToSrgb1(float c){ return(c < 0.0031308?c * 12.92 : 1.055 * pow(c, 0.41666) - 0.055); } +vec3 ToSrgb(vec3 c){ return vec3(ToSrgb1(c.r), ToSrgb1(c.g), ToSrgb1(c.b)); } + +// Nearest emulated sample given floating point position and texel offset. +// Also zero's off screen. +vec3 Fetch(vec2 pos, vec2 off, sampler2D iChannel0){ + pos = floor(pos * res + off) / res; + + if(max(abs(pos.x - 0.5), abs(pos.y - 0.5)) > 0.5){ + return vec3(0.0, 0.0, 0.0); + } + + return ToLinear(texture(iChannel0 , pos.xy , -16.0).rgb); +} + +// Distance in emulated pixels to nearest texel. +vec2 Dist(vec2 pos){ + pos = pos * res; + return - ((pos - floor(pos)) - vec2(0.5)); +} + +// 1D Gaussian. +float Gaus(float pos, float scale){ return exp2(scale * pos * pos); } + +// 3-tap Gaussian filter along horz line. +vec3 Horz3(vec2 pos, float off, sampler2D iChannel0){ + vec3 b = Fetch(pos, vec2(-1.0, off), iChannel0); + vec3 c = Fetch(pos, vec2( 0.0, off), iChannel0); + vec3 d = Fetch(pos, vec2( 1.0, off), iChannel0); + float dst = Dist(pos).x; + + // Convert distance to weight. + float scale = hardPix; + float wb = Gaus(dst - 1.0, scale); + float wc = Gaus(dst + 0.0, scale); + float wd = Gaus(dst + 1.0, scale); + + // Return filtered sample. + return (b * wb + c * wc + d * wd) / (wb + wc + wd); +} +// 5-tap Gaussian filter along horz line. +vec3 Horz5(vec2 pos, float off, sampler2D iChannel0){ + vec3 a = Fetch(pos, vec2(-2.0, off), iChannel0); + vec3 b = Fetch(pos, vec2(-1.0, off), iChannel0); + vec3 c = Fetch(pos, vec2( 0.0, off), iChannel0); + vec3 d = Fetch(pos, vec2( 1.0, off), iChannel0); + vec3 e = Fetch(pos, vec2( 2.0, off), iChannel0); + float dst = Dist(pos).x; + + // Convert distance to weight. + float scale = hardPix; + float wa = Gaus(dst - 2.0, scale); + float wb = Gaus(dst - 1.0, scale); + float wc = Gaus(dst + 0.0, scale); + float wd = Gaus(dst + 1.0, scale); + float we = Gaus(dst + 2.0, scale); + + // Return filtered sample. + return (a * wa + b * wb + c * wc + d * wd + e * we) / (wa + wb + wc + wd + we); +} +// 7-tap Gaussian filter along horz line. +vec3 Horz7(vec2 pos, float off, sampler2D iChannel0){ + vec3 a = Fetch(pos, vec2(-3.0, off), iChannel0); + vec3 b = Fetch(pos, vec2(-2.0, off), iChannel0); + vec3 c = Fetch(pos, vec2( 1.0, off), iChannel0); + vec3 d = Fetch(pos, vec2( 0.0, off), iChannel0); + vec3 e = Fetch(pos, vec2( 1.0, off), iChannel0); + vec3 f = Fetch(pos, vec2( 2.0, off), iChannel0); + vec3 g = Fetch(pos, vec2( 3.0, off), iChannel0); + float dst = Dist(pos).x; + + // Convert distance to weight. + float scale = hardBloomPix; + float wa = Gaus(dst - 3.0, scale); + float wb = Gaus(dst - 2.0, scale); + float wc = Gaus(dst - 1.0, scale); + float wd = Gaus(dst + 0.0, scale); + float we = Gaus(dst + 1.0, scale); + float wf = Gaus(dst + 2.0, scale); + float wg = Gaus(dst + 3.0, scale); + + // Return filtered sample. + return (a * wa + b * wb + c * wc + d * wd + e * we + f * wf + g * wg) / (wa + wb + wc + wd + we + wf + wg); +} + +// Return scanline weight. +float Scan(vec2 pos, float off){ + float dst = Dist(pos).y; + + return Gaus(dst + off, hardScan); +} + +// Return scanline weight for bloom. +float BloomScan(vec2 pos, float off){ + float dst = Dist(pos).y; + + return Gaus(dst + off, hardBloomScan); +} + +// Allow nearest three lines to effect pixel. +vec3 Tri(vec2 pos, sampler2D iChannel0){ + vec3 a = Horz3(pos,-1.0, iChannel0); + vec3 b = Horz5(pos, 0.0, iChannel0); + vec3 c = Horz3(pos, 1.0, iChannel0); + + float wa = Scan(pos,-1.0); + float wb = Scan(pos, 0.0); + float wc = Scan(pos, 1.0); + + return a * wa + b * wb + c * wc; +} + +// Small bloom. +vec3 Bloom(vec2 pos, sampler2D iChannel0){ + vec3 a = Horz5(pos,-2.0, iChannel0); + vec3 b = Horz7(pos,-1.0, iChannel0); + vec3 c = Horz7(pos, 0.0, iChannel0); + vec3 d = Horz7(pos, 1.0, iChannel0); + vec3 e = Horz5(pos, 2.0, iChannel0); + + float wa = BloomScan(pos,-2.0); + float wb = BloomScan(pos,-1.0); + float wc = BloomScan(pos, 0.0); + float wd = BloomScan(pos, 1.0); + float we = BloomScan(pos, 2.0); + + return a * wa + b * wb + c * wc + d * wd + e * we; +} + +// Distortion of scanlines, and end of screen alpha. +vec2 Warp(vec2 pos){ + pos = pos * 2.0 - 1.0; + pos *= vec2(1.0 + (pos.y * pos.y) * 1.0 / warp.x, 1.0 + (pos.x * pos.x) * 1.0/ warp.y); + + return pos * 0.5+0.5; +} + +vec3 Mask(vec2 pos){ + if (mask_type == 0){ + float line = maskLight; + float odd = 0.0; + + if(fract(pos.x / 6.0) < 0.5) odd = 1.0; + if(fract((pos.y + odd) / 2.0) < 0.5) line = maskDark; + pos.x = fract(pos.x / 3.0); + + vec3 mask = vec3(maskDark, maskDark, maskDark); + if(pos.x < 0.333)mask.r = maskLight; + else if(pos.x < 0.666)mask.g = maskLight; + else mask.b = maskLight; + + mask *= line; + return mask; + }else if (mask_type == 1){ + pos.x += pos.y * 3.0; + + vec3 mask = vec3(maskDark, maskDark, maskDark); + pos.x = fract(pos.x / 6.0); + if(pos.x < 0.333)mask.r = maskLight; + else if(pos.x < 0.666)mask.g = maskLight; + else mask.b = maskLight; + + return mask; + }else if (mask_type == 2){ + pos.xy = floor(pos.xy * vec2(1.0, 0.5)); + pos.x += pos.y * 3.0; + + vec3 mask = vec3(maskDark, maskDark, maskDark); + pos.x = fract(pos.x / 6.0); + if(pos.x < 0.333)mask.r = maskLight; + else if(pos.x < 0.666)mask.g = maskLight; + else mask.b = maskLight; + + return mask; + } + } + +// Draw dividing bars. +float Bar(float pos, float bar){ pos -= bar; return pos * pos < 4.0 ? 0.0 : 1.0; } + +// Entry. +void fragment(){ + vec2 pos = Warp(FRAGCOORD.xy / (1.0 / SCREEN_PIXEL_SIZE).xy); + + COLOR.rgb = Tri(pos, SCREEN_TEXTURE) * Mask(FRAGCOORD.xy); + if (bloom_type == 0){ + COLOR.rgb = mix(COLOR.rgb,Bloom(pos, SCREEN_TEXTURE), 1.0 / bloomAmount); + }else if (bloom_type == 1){ + COLOR.rgb += Bloom(pos, SCREEN_TEXTURE) * 1.0 / bloomAmount; + } + + COLOR.a = 1.0; + COLOR.rgb = ToSrgb(COLOR.rgb); +} \ No newline at end of file diff --git a/addons/post_processing/shaders/ascii.gdshader b/addons/post_processing/shaders/ascii.gdshader new file mode 100644 index 0000000..ad2baa1 --- /dev/null +++ b/addons/post_processing/shaders/ascii.gdshader @@ -0,0 +1,37 @@ +/* + アスキー文字エフェクトシェーダー by あるる(きのもと 結衣) @arlez80 + Ascii Effect Shader by Yui Kinomoto @arlez80 + + MIT License +*/ + +shader_type canvas_item; +render_mode unshaded; + +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap; + +const vec3 MONOCHROME_SCALE = vec3( 0.298912, 0.586611, 0.114478 ); + +uniform sampler2D ascii_tex : source_color; +uniform vec2 ascii_size = vec2( 8.0, 16.0 ); +uniform int available_columns = 10; +uniform int max_columns = 16; + +void fragment( ) +{ + vec2 screen_uv = floor( SCREEN_UV / SCREEN_PIXEL_SIZE / ascii_size ) * SCREEN_PIXEL_SIZE * ascii_size; + vec2 diff = ascii_size * SCREEN_PIXEL_SIZE; + vec4 color = ( + textureLod( SCREEN_TEXTURE, screen_uv, 0.0 ) + + textureLod( SCREEN_TEXTURE, screen_uv + vec2( 0.0, diff.y ), 0.0 ) + + textureLod( SCREEN_TEXTURE, screen_uv + vec2( diff.x, 0.0 ), 0.0 ) + + textureLod( SCREEN_TEXTURE, screen_uv + diff, 0.0 ) + ) / 4.0; + + vec2 ascii_uv = fract( SCREEN_UV / SCREEN_PIXEL_SIZE / ascii_size ); + ascii_uv.x = ( 1.0 - ascii_uv.x ) / float( max_columns ); + float col = floor( dot( color.rgb, MONOCHROME_SCALE ) * float( available_columns ) ) / float( available_columns ); + + COLOR = texture( ascii_tex, ascii_uv + vec2( col * ( float( available_columns ) / float( max_columns ) ), 0.0 ) ); +} + diff --git a/addons/post_processing/shaders/bloom.gdshader b/addons/post_processing/shaders/bloom.gdshader new file mode 100644 index 0000000..6139b44 --- /dev/null +++ b/addons/post_processing/shaders/bloom.gdshader @@ -0,0 +1,53 @@ +shader_type canvas_item; +render_mode blend_add; + +#include "CLREDIT.gdshaderinc" + +uniform lowp sampler2D Screen_Sample : hint_screen_texture, filter_linear_mipmap_anisotropic; +uniform lowp sampler2D FlareTex; // Texture for the lens flare + +uniform float BlurAmount; // Adjust blur intensity +uniform float FlareThreshold; // Threshold for brightness to consider flare +uniform int Flares; // Number of lens flares +uniform float FlareSpacing; // Separation between flares +uniform float Intensity; // Overall intensity of the effect +uniform float Saturation_; // Adjust color saturation (optional) +uniform float FalloffStart; // Controls falloff start distance from center (0-1) +uniform float FalloffEnd; // Controls falloff end distance from center (0-1) + +void fragment() { + //UV = SCREEN_UV; + + // Sample the scene color + vec3 SceneColor = texture(Screen_Sample, UV).rgb; + + // Calculate direction vector from screen center (static) + vec2 FlareDir = vec2(0.5) - UV; + + // Accumulate flare color with falloff + vec3 FinalFlare = vec3(0.0); + for (int i = 0; i < Flares; ++i) { + // Offset UV based on flare direction and index + vec2 SampleUV = fract(UV + FlareDir * (BlurAmount + vec2(float(i) * FlareSpacing))); + + // Sample the scene with blur in flare direction + vec3 BlurredScene = texture(Screen_Sample, SampleUV, BlurAmount).rgb; + + // Apply threshold to filter out dark areas + BlurredScene = ApplyThreshold(BlurredScene, FlareThreshold); // Adjust threshold as needed (optional) + + // Calculate distance from center for falloff + float Dist = distance(SampleUV, vec2(0.5)); + float Falloff = smoothstep(FalloffStart, FalloffEnd, Dist); + + // Apply weight and accumulate flare color + FinalFlare += BlurredScene * Falloff; + } + + // Apply lens flare texture + FinalFlare *= texture(FlareTex, UV).rgb; + + // Apply intensity and optional saturation adjustment + COLOR.rgb = FinalFlare * Intensity; + COLOR.rgb = Saturation(COLOR.rgb, Saturation_); // Adjust saturation as needed (optional) +} diff --git a/addons/post_processing/shaders/blur.gdshader b/addons/post_processing/shaders/blur.gdshader new file mode 100644 index 0000000..84b6f85 --- /dev/null +++ b/addons/post_processing/shaders/blur.gdshader @@ -0,0 +1,10 @@ +shader_type canvas_item; + +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap; + +uniform float lod: hint_range(0.0, 5) = 0.0; + +void fragment(){ + vec4 color = texture(SCREEN_TEXTURE, SCREEN_UV, lod); + COLOR = color; +} \ No newline at end of file diff --git a/addons/post_processing/shaders/chromatic.gdshader b/addons/post_processing/shaders/chromatic.gdshader new file mode 100644 index 0000000..147409a --- /dev/null +++ b/addons/post_processing/shaders/chromatic.gdshader @@ -0,0 +1,12 @@ +shader_type canvas_item; + +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture; + +uniform float offset = 1; + +void fragment(){ + vec4 green_channel = texture(SCREEN_TEXTURE, SCREEN_UV); + vec4 red_channel = texture(SCREEN_TEXTURE, vec2(SCREEN_UV.x + (offset * SCREEN_PIXEL_SIZE.x), SCREEN_UV.y)); + vec4 blue_channel = texture(SCREEN_TEXTURE, vec2(SCREEN_UV.x - (offset * SCREEN_PIXEL_SIZE.x), SCREEN_UV.y)); + COLOR = vec4(red_channel.r, green_channel.g, blue_channel.b, 1); +} \ No newline at end of file diff --git a/addons/post_processing/shaders/circularwaves.gdshader b/addons/post_processing/shaders/circularwaves.gdshader new file mode 100644 index 0000000..439f571 --- /dev/null +++ b/addons/post_processing/shaders/circularwaves.gdshader @@ -0,0 +1,50 @@ +shader_type canvas_item; + +// for circles +uniform float amplitude: hint_range(0, 2, 0.01) = 2.0; +uniform float frequency: hint_range(0, 15, 0.01) = 12.69; +uniform float rippleRate : hint_range(0.5, 150.0, 0.1) = 9.2; + + +// for wave +uniform float waveAmplitude = 0.1; +uniform float waveFrequency = 4.0; +uniform float blendingAmount = 0.6; + + +// other +uniform sampler2D noise; + + + +vec2 wave(vec2 uv, float time) { + return vec2( + uv.x + sin(uv.y * waveFrequency * 5.0 + time) * waveAmplitude, + uv.y + sin(uv.x * waveFrequency + time) * waveAmplitude + ); +} + +void fragment() { + vec2 wave_uv = wave(UV, TIME); + vec4 ns = texture(noise, wave_uv); + + vec2 motion = vec2(0.0, 1.0); + float pi = 3.14159265358979323846; + vec2 uv = UV * 2.0 - 1.0; + + float dist = length(uv); + ns *= 1.4142135; + dist += -0.1 * ns.x; + float ripple = sin(dist * -frequency * pi + rippleRate * TIME) * amplitude / (dist + 1.0); + + + vec4 color = vec4(1.0, 1.0, 1.0, 2.0 * ripple); + + float alphaScalar = (1.0 - min(dist, 1.0)) * ns.x * 2.5; + + + color.a *= 1.0 * alphaScalar * (ripple + ns.x * ns.y); + color.a = max(color.a - (ns.y * 0.45), 0.0); + + COLOR = color; +} \ No newline at end of file diff --git a/addons/post_processing/shaders/color_correction.gdshader b/addons/post_processing/shaders/color_correction.gdshader new file mode 100644 index 0000000..b289438 --- /dev/null +++ b/addons/post_processing/shaders/color_correction.gdshader @@ -0,0 +1,19 @@ +shader_type canvas_item; + +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear; +uniform vec4 tint : source_color = vec4(1, 1, 1, 1); +uniform float brightness : hint_range(-1.0, 1.0) = 0; +uniform float saturation : hint_range(-1.0, 1.0) = 0; + +void fragment(){ + vec4 color = texture(SCREEN_TEXTURE, SCREEN_UV); + vec4 final_col = color * tint; + final_col.rgb = final_col.rgb + brightness; + + float avg_col = (final_col.r + final_col.g + final_col.b) / 3.0; + vec3 sat_color = mix(vec3(avg_col), final_col.rgb, 1.0 + saturation); + + final_col.rgb = clamp(sat_color, 0.0, 1.0); + + COLOR = final_col; +} \ No newline at end of file diff --git a/addons/post_processing/shaders/dither.gdshader b/addons/post_processing/shaders/dither.gdshader new file mode 100644 index 0000000..f93bc33 --- /dev/null +++ b/addons/post_processing/shaders/dither.gdshader @@ -0,0 +1,76 @@ +/* +This shader is under MIT license. Feel free to use, improve and +change this shader according to your needs and consider sharing +the modified result to godotshaders.com. +*/ + +shader_type canvas_item; + +uniform sampler2D u_dither_tex; +uniform sampler2D u_color_tex; + +uniform int u_bit_depth; +uniform float u_contrast; +uniform float u_offset; +uniform int u_dither_size; + +void fragment() +{ + // sample the screen texture at the desired output resolution (according to u_dither_size) + // this will effectively pixelate the resulting output + vec2 screen_size = vec2(textureSize(TEXTURE, 0)) / float(u_dither_size); + vec2 screen_sample_uv = floor(UV * screen_size) / screen_size; + vec3 screen_col = texture(TEXTURE, screen_sample_uv).rgb; + + // calculate pixel luminosity (https://stackoverflow.com/questions/596216/formula-to-determine-brightness-of-rgb-color) + float lum = (screen_col.r * 0.299) + (screen_col.g * 0.587) + (screen_col.b * 0.114); + + // adjust with contrast and offset parameters + float contrast = u_contrast; + lum = (lum - 0.5 + u_offset) * contrast + 0.5; + lum = clamp(lum, 0.0, 1.0); + + // reduce luminosity bit depth to give a more banded visual if desired + float bits = float(u_bit_depth); + lum = floor(lum * bits) / bits; + + // to support multicolour palettes, we want to dither between the two colours on the palette + // which are adjacent to the current pixel luminosity. + // to do this, we need to determine which 'band' lum falls into, calculate the upper and lower + // bound of that band, then later we will use the dither texture to pick either the upper or + // lower colour. + + // get the palette texture size mapped so it is 1px high (so the x value however many colour bands there are) + ivec2 col_size = textureSize(u_color_tex, 0); + col_size /= col_size.y; + + float col_x = float(col_size.x) - 1.0; // colour boundaries is 1 less than the number of colour bands + float col_texel_size = 1.0 / col_x; // the size of one colour boundary + + lum = max(lum - 0.00001, 0.0); // makes sure our floor calculation below behaves when lum == 1.0 + float lum_lower = floor(lum * col_x) * col_texel_size; + float lum_upper = (floor(lum * col_x) + 1.0) * col_texel_size; + float lum_scaled = lum * col_x - floor(lum * col_x); // calculates where lum lies between the upper and lower bound + + // map the dither texture onto the screen. there are better ways of doing this that makes the dither pattern 'stick' + // with objects in the 3D world, instead of being mapped onto the screen. see lucas pope's details posts on how he + // achieved this in Obra Dinn: https://forums.tigsource.com/index.php?topic=40832.msg1363742#msg1363742 + ivec2 noise_size = textureSize(u_dither_tex, 0); + vec2 inv_noise_size = vec2(1.0 / float(noise_size.x), 1.0 / float(noise_size.y)); + vec2 noise_uv = UV * inv_noise_size * vec2(float(screen_size.x), float(screen_size.y)); + float threshold = texture(u_dither_tex, noise_uv).r; + + // adjust the dither slightly so min and max aren't quite at 0.0 and 1.0 + // otherwise we wouldn't get fullly dark and fully light dither patterns at lum 0.0 and 1.0 + threshold = threshold * 0.99 + 0.005; + + // the lower lum_scaled is, the fewer pixels will be below the dither threshold, and thus will use the lower bound colour, + // and vice-versa + float ramp_val = lum_scaled < threshold ? 0.0f : 1.0f; + // sample at the lower bound colour if ramp_val is 0.0, upper bound colour if 1.0 + float col_sample = mix(lum_lower, lum_upper, ramp_val); + vec3 final_col = texture(u_color_tex, vec2(col_sample, 0.5)).rgb; + + // return the final colour! + COLOR.rgb = final_col; +} \ No newline at end of file diff --git a/addons/post_processing/shaders/fish_eye.gdshader b/addons/post_processing/shaders/fish_eye.gdshader new file mode 100644 index 0000000..8ccfe15 --- /dev/null +++ b/addons/post_processing/shaders/fish_eye.gdshader @@ -0,0 +1,49 @@ +///////////////////////////////// +// 2D Radial Distortion Shader // +///////////////////////////////// + +// Screen space shader for Godot, based on: https://gist.github.com/aggregate1166877/a889083801d67917c26c12a98e7f57a7 + +shader_type canvas_item; + +uniform float aspect = 1.0; +uniform float distortion = 1.0; +uniform float radius = 1.0; +uniform float alpha = 1.0; +uniform float crop = 1.0; +uniform vec4 crop_color : source_color = vec4(0,0,0,1); +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap; + +vec2 distort(vec2 p) +{ + float d = length(p); + float z = sqrt(distortion + d * d * -distortion); + float r = atan(d, z) / 3.1415926535; + float phi = atan(p.y, p.x); + return vec2(r * cos(phi) * (1.0 / aspect) + 0.5, r * sin(phi) + 0.5); +} + +void fragment() +{ + vec2 xy = (SCREEN_UV * 2.0 - 1.0); // move origin of UV coordinates to center of screen + + xy = vec2(xy.x * aspect, xy.y); // adjust aspect ratio + + float d = length(xy); // distance from center + + vec4 tex; + + if (d < radius) + { + xy = distort(xy); + tex = texture(SCREEN_TEXTURE, xy); + COLOR = tex; + COLOR.a = alpha; + } + + // radial crop + if (d > crop) + { + COLOR = crop_color; + } +} \ No newline at end of file diff --git a/addons/post_processing/shaders/glitch.gdshader b/addons/post_processing/shaders/glitch.gdshader new file mode 100644 index 0000000..3a453fd --- /dev/null +++ b/addons/post_processing/shaders/glitch.gdshader @@ -0,0 +1,49 @@ +shader_type canvas_item; + +uniform float range : hint_range(0.0, 0.1, 0.005)= 0.05; +uniform float noiseQuality : hint_range(0.0, 300.0, 0.1)= 250.0; +uniform float noiseIntensity : hint_range(-0.6, 0.6, 0.0010)= 0.0088; +uniform float offsetIntensity : hint_range(-0.1, 0.1, 0.001) = 0.03; +uniform float colorOffsetIntensity : hint_range(0.0, 5.0, 0.001) = 1.3; +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture; +float rand(vec2 co) +{ + return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453); +} + +float verticalBar(float pos, float UVY, float offset) +{ + float edge0 = (pos - range); + float edge1 = (pos + range); + + float x = smoothstep(edge0, pos, UVY) * offset; + x -= smoothstep(pos, edge1, UVY) * offset; + return x; +} +const float saturation = 0.2; +void fragment() +{ + vec2 uv = SCREEN_UV; + for (float i = 0.0; i < 0.71; i += 0.1313) + { + float d = mod(TIME * i, 1.7); + float o = sin(1.0 - tan(TIME * 0.24 * i)); + o *= offsetIntensity; + uv.x += verticalBar(d, UV.y, o); + } + + float UVY = uv.y; + UVY *= noiseQuality; + UVY = float(int(UVY)) * (1.0 / noiseQuality); + float noise = rand(vec2(TIME * 0.00001, UVY)); + uv.x += noise * noiseIntensity; + + vec2 offsetR = vec2(0.009 * sin(TIME), 0.0) * colorOffsetIntensity; + vec2 offsetG = vec2(0.0073 * (cos(TIME * 0.97)), 0.0) * colorOffsetIntensity; + + float r = texture(SCREEN_TEXTURE, uv + offsetR).r; + float g = texture(SCREEN_TEXTURE, uv + offsetG).g; + float b = texture(SCREEN_TEXTURE, uv).b; + vec4 tex = vec4(r, g, b, 1.0); + COLOR = tex; +} \ No newline at end of file diff --git a/addons/post_processing/shaders/grain.gdshader b/addons/post_processing/shaders/grain.gdshader new file mode 100644 index 0000000..9b1f43b --- /dev/null +++ b/addons/post_processing/shaders/grain.gdshader @@ -0,0 +1,20 @@ +shader_type canvas_item; +// set max strength to your liking here=20.0, step_size=0.1 +uniform float strength:hint_range(0, 159.0, 0.1)=75; + +void fragment() { + + // Screen Color + vec4 screen = texture(TEXTURE, SCREEN_UV); + vec2 iResolution = 1.0 / SCREEN_PIXEL_SIZE; + vec2 uv = FRAGCOORD.xy / iResolution.xy; + + // Random noise + float x = (uv.x + 4.0 ) * (uv.y + 4.0 ) * (TIME * 10.0); + // Add grain to Screen + screen = screen+vec4(mod((mod(x, 13.0) ) * (mod(x, 123.0) ), 0.01)-0.005) * strength; + + screen = 1.0 - screen; + COLOR = screen; + +} \ No newline at end of file diff --git a/addons/post_processing/shaders/painted.gdshader b/addons/post_processing/shaders/painted.gdshader new file mode 100644 index 0000000..844cf46 --- /dev/null +++ b/addons/post_processing/shaders/painted.gdshader @@ -0,0 +1,20 @@ +shader_type canvas_item; + +uniform sampler2D flowMap; //Displacement map +uniform float strength; //Force of the effect +uniform float speed; //Speed of the effect +uniform int frames : hint_range(1, 10); //Frames of the effect +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear; + +//Returns a value between 0 and 1 depending of the frames -> exemple: frames = 4, frame 1 = 0.25 +float clock(float time){ + float fframes = float(frames); + return floor(mod(time * speed, fframes)) / fframes; +} + +void fragment(){ + float c = clock(TIME); //Get clock frame + vec4 offset = texture(flowMap, vec2(SCREEN_UV.x + c, SCREEN_UV.y + c)) * strength; //Get offset + //COLOR = texture(TEXTURE, vec2(UV.x,UV.y) + normal.xy); //Apply offset + COLOR = texture(SCREEN_TEXTURE, vec2(SCREEN_UV.x,SCREEN_UV.y) + offset.xy - vec2(0.5,0.5)*strength); //We need to remove the displacement +} \ No newline at end of file diff --git a/addons/post_processing/shaders/palette_limiter.gdshader b/addons/post_processing/shaders/palette_limiter.gdshader new file mode 100644 index 0000000..b9e5795 --- /dev/null +++ b/addons/post_processing/shaders/palette_limiter.gdshader @@ -0,0 +1,33 @@ +// Godot 4 Adapt To Palette Shader +shader_type canvas_item; + +uniform sampler2D palette: filter_nearest; +uniform sampler2D screen_texture: hint_screen_texture, filter_nearest; + +void fragment() { + float best_diff = 4.00; + ivec2 pal_size = textureSize(palette, 0); + + // Palette row scan + for (int y = 0; y < pal_size.y; y += 1) + { + // Palette column scan + for (int x = 0; x < pal_size.x; x += 1) + { + vec3 scr_pix = texture(screen_texture, SCREEN_UV).rgb; + vec3 pal_pix = texelFetch(palette, ivec2(x, y), 0).rgb; + + // Slightly faster than distance() + float this_diff = ( + abs(scr_pix.r - pal_pix.r) + + abs(scr_pix.g - pal_pix.g) + + abs(scr_pix.b - pal_pix.b)); + + if (this_diff < best_diff) + { + best_diff = this_diff; + COLOR.rgb = pal_pix.rgb; + } + } + } +} \ No newline at end of file diff --git a/addons/post_processing/shaders/pixelate.gdshader b/addons/post_processing/shaders/pixelate.gdshader new file mode 100644 index 0000000..2590b3a --- /dev/null +++ b/addons/post_processing/shaders/pixelate.gdshader @@ -0,0 +1,23 @@ +shader_type canvas_item; + +uniform int pixelSize = 4; +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear; + +void fragment() +{ + + ivec2 size = textureSize(SCREEN_TEXTURE, 0); + + int xRes = size.x; + int yRes = size.y; + + float xFactor = float(xRes) / float(pixelSize); + float yFactor = float(yRes) / float(pixelSize); + + float grid_uv_x = round(SCREEN_UV.x * xFactor) / xFactor; + float grid_uv_y = round(SCREEN_UV.y * yFactor) / yFactor; + + vec4 text = texture(SCREEN_TEXTURE, vec2(grid_uv_x, grid_uv_y)); + + COLOR = text; +} \ No newline at end of file diff --git a/addons/post_processing/shaders/post_process.svg b/addons/post_processing/shaders/post_process.svg new file mode 100644 index 0000000..7d0b52c --- /dev/null +++ b/addons/post_processing/shaders/post_process.svg @@ -0,0 +1,9 @@ + + Projekt bez nazwy (2) + + + + + + \ No newline at end of file diff --git a/addons/post_processing/shaders/post_process.svg.import b/addons/post_processing/shaders/post_process.svg.import new file mode 100644 index 0000000..f90fda1 --- /dev/null +++ b/addons/post_processing/shaders/post_process.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b6ml16b2jkbl2" +path="res://.godot/imported/post_process.svg-b065ed97f6998946e1ca98a22c2e2b81.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/post_processing/shaders/post_process.svg" +dest_files=["res://.godot/imported/post_process.svg-b065ed97f6998946e1ca98a22c2e2b81.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 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/addons/post_processing/shaders/screen_shake.gdshader b/addons/post_processing/shaders/screen_shake.gdshader new file mode 100644 index 0000000..e3241da --- /dev/null +++ b/addons/post_processing/shaders/screen_shake.gdshader @@ -0,0 +1,24 @@ +/* + Camera Shake Effect Shader by @Near + + MIT License +*/ + +shader_type canvas_item; +uniform float ShakeStrength = 0; +uniform vec2 FactorA = vec2(100.0,100.0); +uniform vec2 FactorB = vec2(1.0,1.0); +uniform vec2 magnitude = vec2(0.01,0.01); +uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap; + +void fragment() { + vec2 uv = SCREEN_UV; + uv -= 0.5; + uv *= 1.0 - 2.0 * magnitude.x; + uv += 0.5; + vec2 dt = vec2(0.0, 0.0); + dt.x = sin(TIME * FactorA.x+FactorB.x) * magnitude.x; + dt.y = cos(TIME *FactorA.y+ FactorB.y) * magnitude.y; + COLOR = texture(SCREEN_TEXTURE,uv + (dt*ShakeStrength)); +} + diff --git a/addons/post_processing/shaders/speed_lines.gdshader b/addons/post_processing/shaders/speed_lines.gdshader new file mode 100644 index 0000000..6367c9c --- /dev/null +++ b/addons/post_processing/shaders/speed_lines.gdshader @@ -0,0 +1,59 @@ +shader_type canvas_item; + + +uniform sampler2D noise: repeat_enable; +uniform vec4 line_color: source_color; +uniform float line_count: hint_range(0.0, 2.0, 0.05) = 2; +uniform float line_density: hint_range(0.0, 1.0) = 0.56; +uniform float line_faloff: hint_range(0.0, 1.0) = 0; +uniform float mask_size: hint_range(0.0, 1.0) = 0.333; +uniform float mask_edge: hint_range(0.0, 1.0) = 0.372; +uniform float animation_speed: hint_range(1.0, 20.0) = 20; + + + + +float inv_lerp(float from, float to, float value){ + return (value - from) / (to - from); +} + + + + +vec2 polar_coordinates(vec2 uv, vec2 center, float zoom, float repeat) +{ + vec2 dir = uv - center; + float radius = length(dir) * 2.0; + float angle = atan(dir.y, dir.x) * 1.0/(PI * 2.0); + return mod(vec2(radius * zoom, angle * repeat), 1.0); +} + + + + +vec2 rotate_uv(vec2 uv, vec2 pivot, float rotation) { + float cosa = cos(rotation); + float sina = sin(rotation); + uv -= pivot; + return vec2( + cosa * uv.x - sina * uv.y, + cosa * uv.y + sina * uv.x + ) + pivot; +} + + + + +void fragment(){ + vec2 polar_uv = polar_coordinates(rotate_uv(UV, vec2(0.5), floor(fract(TIME) * animation_speed) ) , vec2(0.5), 0.01, line_count); + vec3 lines = texture(noise, polar_uv).rgb; + + float mask_value = length(UV - vec2(0.5)); + float mask = inv_lerp(mask_size, mask_edge, mask_value); + float result = 1.0 - (mask * line_density); + + result = smoothstep(result, result + line_faloff, lines.r); + + COLOR.rgb = vec3(line_color.rgb); + COLOR.a = min(line_color.a, result); +} \ No newline at end of file diff --git a/addons/post_processing/shaders/vignette.gdshader b/addons/post_processing/shaders/vignette.gdshader new file mode 100644 index 0000000..44eb30d --- /dev/null +++ b/addons/post_processing/shaders/vignette.gdshader @@ -0,0 +1,23 @@ +shader_type canvas_item; + +uniform float vignette_intensity = 0.4; +uniform float vignette_opacity : hint_range(0.0, 1.0) = 0.5; +uniform vec4 vignette_rgb : source_color = vec4(0.0, 0.0, 0.0, 1.0); + +uniform sampler2D screen_vec : hint_screen_texture; + +float vignette(vec2 uv){ + uv *= 1.0 - uv.xy; + float vignette = uv.x * uv.y * 15.0; + return pow(vignette, vignette_intensity * vignette_opacity); +} + +void fragment(){ + vec4 color = texture(screen_vec, SCREEN_UV); + vec4 text = texture(TEXTURE, UV); + + text.rgba *= (vignette_rgb.rgba); + text.rgba *= (1.0 - vignette(UV)); + + COLOR = vec4((text.rgb)*color.rgb,text.a); +} \ No newline at end of file diff --git a/addons/post_processing/shaders/water.gdshader b/addons/post_processing/shaders/water.gdshader new file mode 100644 index 0000000..6c4a921 --- /dev/null +++ b/addons/post_processing/shaders/water.gdshader @@ -0,0 +1,48 @@ +shader_type canvas_item; + +uniform float first_stage : hint_range(0.0, 1.0) = 0.5; +uniform float first_smooth : hint_range(0.0, 1.0) = 0.0; // Lengthens the color transition +uniform float second_stage : hint_range(0.0, 1.0) = 0.0; // If left at 0, only level 1 is used. +uniform float second_smooth : hint_range(0.0, 1.0) = 0.0; +uniform float min_light : hint_range(0.0, 1.0) = 0.0; +uniform float mid_light : hint_range(0.0, 1.0) = 0.0; +uniform float max_light : hint_range(0.0, 1.0) = 1.0; +uniform float obj_light_add : hint_range(0.0, 1.0) = 0.0; + +float light_calc(float light_strength, float would_be_strength) { + float target_strength = light_strength + would_be_strength * obj_light_add; + if (target_strength == 0.0) {target_strength = 0.000001;} + if (would_be_strength == 0.0) {would_be_strength = 1.0;} + return(target_strength / would_be_strength); +} + +void light() { + float level_1 = first_stage; + float level_1_smooth = first_smooth; + float level_2 = second_stage; + float level_2_smooth = second_smooth; + + float mid_range_light = mid_light; + if (mid_light == 0.0) { mid_range_light = max_light * 0.5; } + vec3 light_normal = normalize(vec3(LIGHT_VEC, -LIGHT_HEIGHT)); + float would_be_strength = max(dot(-light_normal, NORMAL), 0.0); + if (would_be_strength > level_1 && level_2 == 0.0 ) { + float diff = smoothstep(level_1, (level_1 + level_1_smooth), would_be_strength) + min_light; + if (diff >= max_light) {diff = max_light;} + LIGHT *= light_calc(diff, would_be_strength); + } else if (would_be_strength > level_1 && would_be_strength < level_2 && level_2 != 0.0 ) { + float diff = smoothstep(level_1, (level_1 + level_1_smooth), would_be_strength) + min_light; + if (diff >= mid_range_light ) {diff = mid_range_light;} + LIGHT *= light_calc(diff, would_be_strength); + } else if (would_be_strength >= level_2 && level_2 != 0.0 ) { + float diff = smoothstep(level_2, (level_2 + level_2_smooth), would_be_strength) + mid_range_light; + if (diff < mid_range_light ) {diff = mid_range_light;} + if (diff >= max_light) {diff = max_light;} + LIGHT *= light_calc(diff, would_be_strength); + } else { + if (min_light != 0.0) { + LIGHT_VEC = -NORMAL.xy*length(LIGHT_VEC); + } + LIGHT *= min_light; + } +} \ No newline at end of file