diff --git a/examples/images/CREDITS.md b/examples/images/CREDITS.md index ed427c8..d662b8c 100644 --- a/examples/images/CREDITS.md +++ b/examples/images/CREDITS.md @@ -3,3 +3,4 @@ - swamp.jpg by [clfr21 on Pixabay](https://pixabay.com/de/users/clfr21-6530007/) - grass.png by [GDJ on Pixabay](https://pixabay.com/users/gdj-1086657/) +- mountain.jpg by [Phghvvcftyyufj on Pixabay](https://pixabay.com/users/phghvvcftyyufj-12646982) diff --git a/examples/images/mountain.jpg b/examples/images/mountain.jpg new file mode 100644 index 0000000..591c06d Binary files /dev/null and b/examples/images/mountain.jpg differ diff --git a/examples/images/mountain.jpg.import b/examples/images/mountain.jpg.import new file mode 100644 index 0000000..e914676 --- /dev/null +++ b/examples/images/mountain.jpg.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://ben72llmopgaj" +path="res://.godot/imported/mountain.jpg-c1b7de1e6557b826bc6f9324027e11af.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://examples/images/mountain.jpg" +dest_files=["res://.godot/imported/mountain.jpg-c1b7de1e6557b826bc6f9324027e11af.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/examples/kuwahara.gdshader b/examples/kuwahara.gdshader new file mode 100644 index 0000000..345f826 --- /dev/null +++ b/examples/kuwahara.gdshader @@ -0,0 +1,16 @@ +shader_type canvas_item; + +//!load ./images/mountain.jpg + +#include "res://shaderlib/kuwahara.gdshaderinc" +#include "res://shaderlib/hsv.gdshaderinc" + +void fragment() { + // Kuwahara + COLOR.rgb = kuwahara(TEXTURE, UV, 20, 80.0, 18.0, 0.6, .15, 8); + // A litte bit of color adjustments + vec4 hsv = rgb2hsv(COLOR); + hsv.x += .03; + hsv.y *= 1.4; + COLOR = hsv2rgb(hsv); +} diff --git a/project.godot b/project.godot index d51c3fe..b5573aa 100644 --- a/project.godot +++ b/project.godot @@ -11,7 +11,7 @@ config_version=5 [application] config/name="Fragmented" -config/version="v8.1" +config/version="v8.2" run/main_scene="res://scenes/main.tscn" config/features=PackedStringArray("4.3", "Mobile") run/low_processor_mode=true diff --git a/shaderlib/kuwahara.gdshaderinc b/shaderlib/kuwahara.gdshaderinc new file mode 100644 index 0000000..ea6e22b --- /dev/null +++ b/shaderlib/kuwahara.gdshaderinc @@ -0,0 +1,116 @@ +/* + Kuwahara Filter, adapted + original code: https://godotshaders.com/shader/generalized-kuwahara/ + original authors: + - https://godotshaders.com/author/firerabbit/ + - https://github.com/GarrettGunnell (Acerola) + license of the original code: + + MIT License + + Copyright (c) 2022 Garrett Gunnell + Copyright (c) 2024 Firerabbit + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons + to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies + or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + IN THE SOFTWARE. +*/ + +vec3 kuwahara( + sampler2D texture, + vec2 uv, + int kernel_size, // should be > 2 - high values will affect performance + float hardness, // should be in the range of 1.0 - 100.0 + float sharpness, // should be in the range of 1.0 - 18.0 + float zero_crossing, // should be in the range of 0.5 - 2.0 + float zeta, // should be in the range of 0.01 - 3.0 + int n // number of iterations, should be 8, must be <= 8 +) { + vec2 texelSize = vec2(1.0 / vec2(textureSize(texture, 0))); + vec4 m[8]; + vec3 s[8]; + + int kernel_radius = kernel_size / 2; + + float sin_zero_crossing = sin(zero_crossing); + float eta = (zeta + cos(zero_crossing)) / (sin_zero_crossing * sin_zero_crossing); + + for (int k = 0; k < n; ++k) { + m[k] = vec4(0.0f); + s[k] = vec3(0.0f); + } + + for (int y = -kernel_radius; y <= kernel_radius; ++y) { + for (int x = -kernel_radius; x <= kernel_radius; ++x) { + vec2 v = vec2(float(x), float(y)) / float(kernel_radius); + vec3 c = texture(texture, uv + vec2(float(x), float(y)) * texelSize.xy).rgb; + c = clamp(c, 0.0f, 1.0f); + float sum = 0.0f; + float w[8]; + float z, vxx, vyy; + + /* Calculate Polynomial Weights */ + vxx = zeta - eta * v.x * v.x; + vyy = zeta - eta * v.y * v.y; + z = max(0, v.y + vxx); + w[0] = z * z; + sum += w[0]; + z = max(0, -v.x + vyy); + w[2] = z * z; + sum += w[2]; + z = max(0, -v.y + vxx); + w[4] = z * z; + sum += w[4]; + z = max(0, v.x + vyy); + w[6] = z * z; + sum += w[6]; + v = sqrt(2.0f) / 2.0f * vec2(v.x - v.y, v.x + v.y); + vxx = zeta - eta * v.x * v.x; + vyy = zeta - eta * v.y * v.y; + z = max(0, v.y + vxx); + w[1] = z * z; + sum += w[1]; + z = max(0, -v.x + vyy); + w[3] = z * z; + sum += w[3]; + z = max(0, -v.y + vxx); + w[5] = z * z; + sum += w[5]; + z = max(0, v.x + vyy); + w[7] = z * z; + sum += w[7]; + + float g = exp(-3.125f * dot(v,v)) / sum; + + for (int k = 0; k < 8; ++k) { + float wk = w[k] * g; + m[k] += vec4(c * wk, wk); + s[k] += c * c * wk; + } + } + } + + vec4 output = vec4(0.0f); + for (int k = 0; k < n; ++k) { + m[k].rgb /= m[k].w; + s[k] = abs(s[k] / m[k].w - m[k].rgb * m[k].rgb); + float sigma2 = s[k].r + s[k].g + s[k].b; + float w = 1.0f / (1.0f + pow(hardness * 1000.0f * sigma2, 0.5f * sharpness)); + output += vec4(m[k].rgb * w, w); + } + + return clamp(output / output.w, 0.0f, 1.0f).rgb; +} diff --git a/src/Editor.gd b/src/Editor.gd index 61f0435..2d29232 100644 --- a/src/Editor.gd +++ b/src/Editor.gd @@ -134,6 +134,7 @@ const shaderlib_functions = { "common": ["alpha_blend", "cbrt"], "denoise": ["smart_denoise"], "hsv": ["rgb2hsv", "hsv2rgb",], + "kuwahara": ["kuwahara",], "oklab": ["oklab2rgb", "rgb2oklab", "oklab2oklch", "oklch2oklab"], "pixelate": ["pixelate"], "place_texture": ["place_texture"],