Implement oklab, oklch color space conversion functions, add example, restructure comments in the shaderlib, implements #37

This commit is contained in:
ChaoticByte 2025-01-17 16:50:34 +01:00
parent 35959290d3
commit 1a21589fc1
No known key found for this signature in database
8 changed files with 127 additions and 34 deletions

12
examples/oklab.gdshader Normal file
View file

@ -0,0 +1,12 @@
shader_type canvas_item;
#include "res://shaderlib/colorspaces.gdshaderinc"
//!load ./images/swamp.jpg
void fragment() {
vec4 oklab = rgb2oklab(COLOR);
vec4 oklch = oklab2oklch(oklab);
oklch.z -= 2.0;
COLOR = oklab2rgb(oklch2oklab(oklch));
}

View file

@ -1,7 +1,9 @@
// gaussian_blur adapted from https://godotshaders.com/shader/customizable-gausian-blur/ /*
// original code by https://godotshaders.com/author/djbob-gaming-yt/ gaussian_blur adapted from https://godotshaders.com/shader/customizable-gausian-blur/
// maximum radius is 64 original code by https://godotshaders.com/author/djbob-gaming-yt/
maximum radius is 64
*/
vec4 gaussian_blur(sampler2D texture, vec2 uv, int radius, float sigma) { vec4 gaussian_blur(sampler2D texture, vec2 uv, int radius, float sigma) {
vec2 resolution = 1.0 / vec2(textureSize(texture, 0)); vec2 resolution = 1.0 / vec2(textureSize(texture, 0));
// calculate kernel // calculate kernel

View file

@ -1,7 +1,16 @@
// rgb2hsv and hsv2rgb functions adapted /*
// from https://godotshaders.com/shader/hsv-adjustment/ Color space conversion functions always work with vec4.
// original code by https://godotshaders.com/author/al1-ce/ The fourth value is always alpha.
*/
#include "res://shaderlib/common.gdshaderinc"
/*
rgb2hsv and hsv2rgb functions adapted
from https://godotshaders.com/shader/hsv-adjustment/
original code by https://godotshaders.com/author/al1-ce/
*/
// Convert RGB to HSV (hue, saturation, brightness) // Convert RGB to HSV (hue, saturation, brightness)
vec4 rgb2hsv(vec4 c) { vec4 rgb2hsv(vec4 c) {
@ -20,3 +29,62 @@ vec4 hsv2rgb(vec4 c) {
vec3 rgb = c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); vec3 rgb = c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
return vec4(rgb.r, rgb.g, rgb.b, c.a); return vec4(rgb.r, rgb.g, rgb.b, c.a);
} }
/*
OkLab and OkLCh
For more details on oklab, see
- https://bottosson.github.io/posts/oklab/
- https://en.wikipedia.org/wiki/Oklab_color_space
*/
vec4 rgb2oklab(vec4 c) {
float l = 0.4122214708f * c.r + 0.5363325363f * c.g + 0.0514459929f * c.b;
float m = 0.2119034982f * c.r + 0.6806995451f * c.g + 0.1073969566f * c.b;
float s = 0.0883024619f * c.r + 0.2817188376f * c.g + 0.6299787005f * c.b;
float l_ = cbrt(l);
float m_ = cbrt(m);
float s_ = cbrt(s);
return vec4(
0.2104542553f*l_ + 0.7936177850f*m_ - 0.0040720468f*s_,
1.9779984951f*l_ - 2.4285922050f*m_ + 0.4505937099f*s_,
0.0259040371f*l_ + 0.7827717662f*m_ - 0.8086757660f*s_,
c.a
);
}
vec4 oklab2rgb(vec4 c) {
float l_ = c.x + 0.3963377774f * c.y + 0.2158037573f * c.z;
float m_ = c.x - 0.1055613458f * c.y - 0.0638541728f * c.z;
float s_ = c.x - 0.0894841775f * c.y - 1.2914855480f * c.z;
float l = l_*l_*l_;
float m = m_*m_*m_;
float s = s_*s_*s_;
return vec4(
+4.0767416621f * l - 3.3077115913f * m + 0.2309699292f * s,
-1.2684380046f * l + 2.6097574011f * m - 0.3413193965f * s,
-0.0041960863f * l - 0.7034186147f * m + 1.7076147010f * s,
c.a
);
}
vec4 oklab2oklch(vec4 c) {
return vec4(
c.x,
sqrt((c.y * c.y) + (c.z * c.z)),
atan(c.z, c.y),
c.a
);
}
vec4 oklch2oklab(vec4 c) {
return vec4(
c.x,
c.y * cos(c.z),
c.y * sin(c.z),
c.a
);
}

View file

@ -0,0 +1,5 @@
// inefficient cuberoot function
float cbrt(float x) {
return pow(x, 1.0/3.0);
}

View file

@ -1,32 +1,34 @@
/* glslSmartDenoise by Michele Morrone, adapted /*
original code: https://github.com/BrutPitt/glslSmartDeNoise glslSmartDenoise by Michele Morrone, adapted
license of the original code: original code: https://github.com/BrutPitt/glslSmartDeNoise
BSD 2-Clause License license of the original code:
Copyright (c) 2019-2020 Michele Morrone BSD 2-Clause License
All rights reserved.
Redistribution and use in source and binary forms, with or without Copyright (c) 2019-2020 Michele Morrone
modification, are permitted provided that the following conditions are met: All rights reserved.
1. Redistributions of source code must retain the above copyright notice, this Redistribution and use in source and binary forms, with or without
list of conditions and the following disclaimer. modification, are permitted provided that the following conditions are met:
2. Redistributions in binary form must reproduce the above copyright notice, 1. Redistributions of source code must retain the above copyright notice, this
this list of conditions and the following disclaimer in the documentation list of conditions and the following disclaimer.
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 2. Redistributions in binary form must reproduce the above copyright notice,
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE this list of conditions and the following disclaimer in the documentation
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE and/or other materials provided with the distribution.
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#define INV_SQRT_OF_2PI 0.39894228040143267793994605993439 // 1.0/SQRT_OF_2PI #define INV_SQRT_OF_2PI 0.39894228040143267793994605993439 // 1.0/SQRT_OF_2PI

View file

@ -1,6 +1,8 @@
// Load in a texture from a sampler2D with an offset and scale /*
// See examples/place_texture.gdshader Load in a texture from a sampler2D with an offset and scale
See examples/place_texture.gdshader
*/
vec4 place_texture(sampler2D sampler, vec2 uv, vec2 texture_pixel_size, vec2 offset, vec2 scale) { vec4 place_texture(sampler2D sampler, vec2 uv, vec2 texture_pixel_size, vec2 offset, vec2 scale) {
vec2 texture_size = vec2(textureSize(sampler, 0)); vec2 texture_size = vec2(textureSize(sampler, 0));
// position of current pixel; sample color c // position of current pixel; sample color c

View file

@ -1,6 +1,8 @@
// Alpha Blending a over b after Bruce A. Wallace /*
// source: https://en.wikipedia.org/wiki/Alpha_compositing Alpha Blending a over b after Bruce A. Wallace
source: https://en.wikipedia.org/wiki/Alpha_compositing
*/
vec4 alpha_blend(vec4 b, vec4 a) { vec4 alpha_blend(vec4 b, vec4 a) {
float alpha = a.a + (b.a * (1.0 - a.a)); float alpha = a.a + (b.a * (1.0 - a.a));
vec3 col = ((a.rgb*a.a) + ((b.rgb*b.a) * (1.0 - a.a)) / alpha); vec3 col = ((a.rgb*a.a) + ((b.rgb*b.a) * (1.0 - a.a)) / alpha);

View file

@ -137,7 +137,7 @@ var shaderlib_regex = {
"blur": RegEx.create_from_string(r'\s*\#include\s+\"res\:\/\/shaderlib\/blur\.gdshaderinc\"'), "blur": RegEx.create_from_string(r'\s*\#include\s+\"res\:\/\/shaderlib\/blur\.gdshaderinc\"'),
} }
const shaderlib_functions = { const shaderlib_functions = {
"colorspaces": ["rgb2hsv", "hsv2rgb"], "colorspaces": ["rgb2hsv", "hsv2rgb", "oklab2rgb", "rgb2oklab", "oklab2oklch", "oklch2oklab"],
"transform": ["place_texture"], "transform": ["place_texture"],
"transparency": ["alpha_blend"], "transparency": ["alpha_blend"],
"effects": ["pixelate"], "effects": ["pixelate"],