diff --git a/godot/README.md b/godot/README.md new file mode 100644 index 0000000..6784d78 --- /dev/null +++ b/godot/README.md @@ -0,0 +1,90 @@ +# Mixbox for Godot +```gdscript +var Mixbox = preload("res://addons/mixbox/mixbox.gd") + +var color1 = Color(0.0, 0.129, 0.522) # blue +var color2 = Color(0.988, 0.827, 0.0) # yellow +var t = 0.5 # mixing ratio + +var color_mix = Mixbox.lerp(color1, color2, t) + +print(color_mix) +``` + +## Mixing Multiple Colors +```gdscript +var z1 = Mixbox.rgb_to_latent(color1) +var z2 = Mixbox.rgb_to_latent(color2) +var z3 = Mixbox.rgb_to_latent(color3) + +var z_mix = [] +z_mix.resize(Mixbox.LATENT_SIZE) + +for i in z_mix.size(): # mix together: + z_mix[i] = (0.3*z1[i] + # 30% of color1 + 0.6*z2[i] + # 60% of color2 + 0.1*z3[i]) # 10% of color3 + +var color_mix = Mixbox.latent_to_rgb(z_mix) +``` + +# Shader +```c++ +shader_type canvas_item; + +uniform sampler2D mixbox_lut; // attach "addons/mixbox/mixbox_lut.png" here + +uniform vec4 color1 : hint_color = vec4(0.0, 0.129, 0.522, 1.0); // blue +uniform vec4 color2 : hint_color = vec4(0.988, 0.827, 0.0, 1.0); // yellow + +// #include only works in Godot 4, if you are on Godot 3.X +// you will need to paste the Mixbox code here manually. +#include "addons/mixbox/mixbox.gdshaderinc" + +void fragment() { + COLOR = mixbox_lerp(color1, color2, UV.x); +} +``` +

+ +

+ +## Mixing Multiple Colors + +```glsl +mat3 z1 = mixbox_rgb_to_latent(color1.rgb); +mat3 z2 = mixbox_rgb_to_latent(color2.rgb); +mat3 z3 = mixbox_rgb_to_latent(color3.rgb); + +// mix together 30% of color1, 60% of color2, and 10% of color3 +mat3 z_mix = 0.3*z1 + 0.6*z2 + 0.1*z3; + +vec3 rgb_mix = mixbox_latent_to_rgb(z_mix); +``` + +# VisualShader +

+ +

+ +## Pigment Colors +| Pigment | | RGB | Float RGB | Linear RGB | +| --- | --- |:----:|:----:|:----:| +| Cadmium Yellow | | 254, 236, 0 | 0.996, 0.925, 0.0 | 0.991, 0.839, 0.0 | +| Hansa Yellow | | 252, 211, 0 | 0.988, 0.827, 0.0 | 0.973, 0.651, 0.0 | +| Cadmium Orange | | 255, 105, 0 | 1.0, 0.412, 0.0 | 1.0, 0.141, 0.0 | +| Cadmium Red | | 255, 39, 2 | 1.0, 0.153, 0.008 | 1.0, 0.02, 0.001 | +| Quinacridone Magenta | | 128, 2, 46 | 0.502, 0.008, 0.18 | 0.216, 0.001, 0.027 | +| Cobalt Violet | | 78, 0, 66 | 0.306, 0.0, 0.259 | 0.076, 0.0, 0.054 | +| Ultramarine Blue | | 25, 0, 89 | 0.098, 0.0, 0.349 | 0.01, 0.0, 0.1 | +| Cobalt Blue | | 0, 33, 133 | 0.0, 0.129, 0.522 | 0.0, 0.015, 0.235 | +| Phthalo Blue | | 13, 27, 68 | 0.051, 0.106, 0.267 | 0.004, 0.011, 0.058 | +| Phthalo Green | | 0, 60, 50 | 0.0, 0.235, 0.196 | 0.0, 0.045, 0.032 | +| Permanent Green | | 7, 109, 22 | 0.027, 0.427, 0.086 | 0.002, 0.153, 0.008 | +| Sap Green | | 107, 148, 4 | 0.42, 0.58, 0.016 | 0.147, 0.296, 0.001 | +| Burnt Sienna | | 123, 72, 0 | 0.482, 0.282, 0.0 | 0.198, 0.065, 0.0 | + +## License +Copyright (c) 2022, Secret Weapons. All rights reserved.
+Mixbox is provided under the CC BY-NC 4.0 license for non-commercial use only.
+If you want to obtain commercial license, please contact: mixbox@scrtwpns.com diff --git a/godot/addons/mixbox/mixbox.gd b/godot/addons/mixbox/mixbox.gd new file mode 100644 index 0000000..e1ead2b --- /dev/null +++ b/godot/addons/mixbox/mixbox.gd @@ -0,0 +1,198 @@ +# ========================================================== +# MIXBOX 2.0 (c) 2022 Secret Weapons. All rights reserved. +# License: Creative Commons Attribution-NonCommercial 4.0 +# Authors: Sarka Sochorova and Ondrej Jamriska +# ========================================================== +# +# BASIC USAGE +# +# var color_mix = Mixbox.lerp(color1, color2, t) +# +# MULTI-COLOR MIXING +# +# var z1 = Mixbox.rgb_to_latent(color1) +# var z2 = Mixbox.rgb_to_latent(color2) +# var z3 = Mixbox.rgb_to_latent(color3) +# +# var z_mix = [] +# z_mix.resize(Mixbox.LATENT_SIZE) +# +# for i in z_mix.size(): # mix together: +# z_mix[i] = (0.3*z1[i] + # 30% of color1 +# 0.6*z2[i] + # 60% of color2 +# 0.1*z3[i]) # 10% of color3 +# +# var color_mix = Mixbox.latent_to_rgb(z_mix) +# +# PIGMENT COLORS +# +# Cadmium Yellow 0.996, 0.925, 0.000 +# Hansa Yellow 0.988, 0.827, 0.000 +# Cadmium Orange 1.000, 0.412, 0.000 +# Cadmium Red 1.000, 0.153, 0.008 +# Quinacridone Magenta 0.502, 0.008, 0.180 +# Cobalt Violet 0.306, 0.000, 0.259 +# Ultramarine Blue 0.098, 0.000, 0.349 +# Cobalt Blue 0.000, 0.129, 0.522 +# Phthalo Blue 0.051, 0.106, 0.267 +# Phthalo Green 0.000, 0.235, 0.196 +# Permanent Green 0.027, 0.427, 0.086 +# Sap Green 0.420, 0.580, 0.016 +# Burnt Sienna 0.482, 0.282, 0.000 +# +# LICENSING +# +# If you want to obtain commercial license, please +# contact us at: mixbox@scrtwpns.com +# + +const lut = preload("mixbox.res").__data__ + +const LATENT_SIZE = 7 + +static func clamp01(value : float) -> float: + return clamp(value, 0.0, 1.0) + +static func eval_polynomial(c0 : float, c1 : float, c2 : float, c3 : float) -> Color: + var r = 0.0 + var g = 0.0 + var b = 0.0 + + var c00 = c0 * c0 + var c11 = c1 * c1 + var c22 = c2 * c2 + var c33 = c3 * c3 + var c01 = c0 * c1 + var c02 = c0 * c2 + var c12 = c1 * c2 + + var w = 0.0 + w = c0*c00; r += +0.07717053*w; g += +0.02826978*w; b += +0.24832992*w; + w = c1*c11; r += +0.95912302*w; g += +0.80256528*w; b += +0.03561839*w; + w = c2*c22; r += +0.74683774*w; g += +0.04868586*w; b += +0.00000000*w; + w = c3*c33; r += +0.99518138*w; g += +0.99978149*w; b += +0.99704802*w; + w = c00*c1; r += +0.04819146*w; g += +0.83363781*w; b += +0.32515377*w; + w = c01*c1; r += -0.68146950*w; g += +1.46107803*w; b += +1.06980936*w; + w = c00*c2; r += +0.27058419*w; g += -0.15324870*w; b += +1.98735057*w; + w = c02*c2; r += +0.80478189*w; g += +0.67093710*w; b += +0.18424500*w; + w = c00*c3; r += -0.35031003*w; g += +1.37855826*w; b += +3.68865000*w; + w = c0*c33; r += +1.05128046*w; g += +1.97815239*w; b += +2.82989073*w; + w = c11*c2; r += +3.21607125*w; g += +0.81270228*w; b += +1.03384539*w; + w = c1*c22; r += +2.78893374*w; g += +0.41565549*w; b += -0.04487295*w; + w = c11*c3; r += +3.02162577*w; g += +2.55374103*w; b += +0.32766114*w; + w = c1*c33; r += +2.95124691*w; g += +2.81201112*w; b += +1.17578442*w; + w = c22*c3; r += +2.82677043*w; g += +0.79933038*w; b += +1.81715262*w; + w = c2*c33; r += +2.99691099*w; g += +1.22593053*w; b += +1.80653661*w; + w = c01*c2; r += +1.87394106*w; g += +2.05027182*w; b += -0.29835996*w; + w = c01*c3; r += +2.56609566*w; g += +7.03428198*w; b += +0.62575374*w; + w = c02*c3; r += +4.08329484*w; g += -1.40408358*w; b += +2.14995522*w; + w = c12*c3; r += +6.00078678*w; g += +2.55552042*w; b += +1.90739502*w; + + return Color(r, g, b) + +static func rgb_to_latent(color : Color) -> Array: + var r = clamp01(color.r) + var g = clamp01(color.g) + var b = clamp01(color.b) + + var x = r * 63.0 + var y = g * 63.0 + var z = b * 63.0 + + var ix = int(x) + var iy = int(y) + var iz = int(z) + + var tx = x - ix + var ty = y - iy + var tz = z - iz + + var xyz = ix + iy*64 + iz*64*64 + + var c0 = 0.0 + var c1 = 0.0 + var c2 = 0.0 + + var w = 0.0 + w = (1.0-tx)*(1.0-ty)*(1.0-tz); c0 += w*lut[xyz+ 192]; c1 += w*lut[xyz+262336]; c2 += w*lut[xyz+524480]; + w = ( tx)*(1.0-ty)*(1.0-tz); c0 += w*lut[xyz+ 193]; c1 += w*lut[xyz+262337]; c2 += w*lut[xyz+524481]; + w = (1.0-tx)*( ty)*(1.0-tz); c0 += w*lut[xyz+ 256]; c1 += w*lut[xyz+262400]; c2 += w*lut[xyz+524544]; + w = ( tx)*( ty)*(1.0-tz); c0 += w*lut[xyz+ 257]; c1 += w*lut[xyz+262401]; c2 += w*lut[xyz+524545]; + w = (1.0-tx)*(1.0-ty)*( tz); c0 += w*lut[xyz+4288]; c1 += w*lut[xyz+266432]; c2 += w*lut[xyz+528576]; + w = ( tx)*(1.0-ty)*( tz); c0 += w*lut[xyz+4289]; c1 += w*lut[xyz+266433]; c2 += w*lut[xyz+528577]; + w = (1.0-tx)*( ty)*( tz); c0 += w*lut[xyz+4352]; c1 += w*lut[xyz+266496]; c2 += w*lut[xyz+528640]; + w = ( tx)*( ty)*( tz); c0 += w*lut[xyz+4353]; c1 += w*lut[xyz+266497]; c2 += w*lut[xyz+528641]; + + c0 /= 255.0 + c1 /= 255.0 + c2 /= 255.0 + + var c3 = 1.0 - (c0 + c1 + c2) + + var c00 = c0 * c0 + var c11 = c1 * c1 + var c22 = c2 * c2 + var c33 = c3 * c3 + var c01 = c0 * c1 + var c02 = c0 * c2 + var c12 = c1 * c2 + + var rmix = 0.0 + var gmix = 0.0 + var bmix = 0.0 + + w = c0*c00; rmix += +0.07717053*w; gmix += +0.02826978*w; bmix += +0.24832992*w; + w = c1*c11; rmix += +0.95912302*w; gmix += +0.80256528*w; bmix += +0.03561839*w; + w = c2*c22; rmix += +0.74683774*w; gmix += +0.04868586*w; bmix += +0.00000000*w; + w = c3*c33; rmix += +0.99518138*w; gmix += +0.99978149*w; bmix += +0.99704802*w; + w = c00*c1; rmix += +0.04819146*w; gmix += +0.83363781*w; bmix += +0.32515377*w; + w = c01*c1; rmix += -0.68146950*w; gmix += +1.46107803*w; bmix += +1.06980936*w; + w = c00*c2; rmix += +0.27058419*w; gmix += -0.15324870*w; bmix += +1.98735057*w; + w = c02*c2; rmix += +0.80478189*w; gmix += +0.67093710*w; bmix += +0.18424500*w; + w = c00*c3; rmix += -0.35031003*w; gmix += +1.37855826*w; bmix += +3.68865000*w; + w = c0*c33; rmix += +1.05128046*w; gmix += +1.97815239*w; bmix += +2.82989073*w; + w = c11*c2; rmix += +3.21607125*w; gmix += +0.81270228*w; bmix += +1.03384539*w; + w = c1*c22; rmix += +2.78893374*w; gmix += +0.41565549*w; bmix += -0.04487295*w; + w = c11*c3; rmix += +3.02162577*w; gmix += +2.55374103*w; bmix += +0.32766114*w; + w = c1*c33; rmix += +2.95124691*w; gmix += +2.81201112*w; bmix += +1.17578442*w; + w = c22*c3; rmix += +2.82677043*w; gmix += +0.79933038*w; bmix += +1.81715262*w; + w = c2*c33; rmix += +2.99691099*w; gmix += +1.22593053*w; bmix += +1.80653661*w; + w = c01*c2; rmix += +1.87394106*w; gmix += +2.05027182*w; bmix += -0.29835996*w; + w = c01*c3; rmix += +2.56609566*w; gmix += +7.03428198*w; bmix += +0.62575374*w; + w = c02*c3; rmix += +4.08329484*w; gmix += -1.40408358*w; bmix += +2.14995522*w; + w = c12*c3; rmix += +6.00078678*w; gmix += +2.55552042*w; bmix += +1.90739502*w; + + return [ + c0, + c1, + c2, + c3, + r - rmix, + g - gmix, + b - bmix, + ] + +static func latent_to_rgb(latent) -> Color: + var rgb = eval_polynomial(latent[0], latent[1], latent[2], latent[3]) + return Color( + clamp01(rgb.r + latent[4]), + clamp01(rgb.g + latent[5]), + clamp01(rgb.b + latent[6]) + ); + +static func lerp(color1 : Color, color2 : Color, t : float) -> Color: + var latent1 = rgb_to_latent(color1) + var latent2 = rgb_to_latent(color2) + + var latent_mix = [] + + latent_mix.resize(LATENT_SIZE) + + for i in latent_mix.size(): + latent_mix[i] = (1.0-t)*latent1[i] + t*latent2[i] + + var color_mix = latent_to_rgb(latent_mix) + + color_mix.a = (1.0-t)*color1.a + t*color2.a + + return color_mix diff --git a/godot/addons/mixbox/mixbox.gdshader b/godot/addons/mixbox/mixbox.gdshader new file mode 100644 index 0000000..d28ed5e --- /dev/null +++ b/godot/addons/mixbox/mixbox.gdshader @@ -0,0 +1,121 @@ +// ========================================================== +// MIXBOX 2.0 (c) 2022 Secret Weapons. All rights reserved. +// License: Creative Commons Attribution-NonCommercial 4.0 +// Authors: Sarka Sochorova and Ondrej Jamriska +// ========================================================== +// +// BASIC USAGE +// +// vec3 rgb = mixbox_lerp(rgb1, rgb2, t); +// +// MULTI-COLOR MIXING +// +// mat3 z1 = mixbox_rgb_to_latent(rgb1); +// mat3 z2 = mixbox_rgb_to_latent(rgb2); +// mat3 z3 = mixbox_rgb_to_latent(rgb3); +// +// // mix 30% of rgb1, 60% of rgb2, and 10% of rgb3 +// mat3 z_mix = 0.3*z1 + 0.6*z2 + 0.1*z3; +// +// vec3 rgb_mix = mixbox_latent_to_rgb(z_mix); +// +// PIGMENT COLORS +// +// Cadmium Yellow 0.996, 0.925, 0.000 +// Hansa Yellow 0.988, 0.827, 0.000 +// Cadmium Orange 1.000, 0.412, 0.000 +// Cadmium Red 1.000, 0.153, 0.008 +// Quinacridone Magenta 0.502, 0.008, 0.180 +// Cobalt Violet 0.306, 0.000, 0.259 +// Ultramarine Blue 0.098, 0.000, 0.349 +// Cobalt Blue 0.000, 0.129, 0.522 +// Phthalo Blue 0.051, 0.106, 0.267 +// Phthalo Green 0.000, 0.235, 0.196 +// Permanent Green 0.027, 0.427, 0.086 +// Sap Green 0.420, 0.580, 0.016 +// Burnt Sienna 0.482, 0.282, 0.000 +// +// LICENSING +// +// If you want to obtain commercial license, please +// contact us at: mixbox@scrtwpns.com +// + +shader_type canvas_item; + +uniform sampler2D mixbox_lut; // attach "addons/mixbox/mixbox_lut.png" here + +uniform vec4 color1 : hint_color = vec4(0.0, 0.129, 0.522, 1.0); // blue +uniform vec4 color2 : hint_color = vec4(0.988, 0.827, 0.0, 1.0); // yellow + +vec3 _mixbox_eval_polynomial(vec3 _mixbox_c) { + float _mixbox_c0 = _mixbox_c[0]; + float _mixbox_c1 = _mixbox_c[1]; + float _mixbox_c2 = _mixbox_c[2]; + float _mixbox_c3 = 1.0 - (_mixbox_c0 + _mixbox_c1 + _mixbox_c2); + + float _mixbox_c00 = _mixbox_c0 * _mixbox_c0; + float _mixbox_c11 = _mixbox_c1 * _mixbox_c1; + float _mixbox_c22 = _mixbox_c2 * _mixbox_c2; + float _mixbox_c01 = _mixbox_c0 * _mixbox_c1; + float _mixbox_c02 = _mixbox_c0 * _mixbox_c2; + float _mixbox_c12 = _mixbox_c1 * _mixbox_c2; + float _mixbox_c33 = _mixbox_c3 * _mixbox_c3; + + return ( + (_mixbox_c0 * _mixbox_c00) * vec3(+0.07717053, +0.02826978, +0.24832992) + + (_mixbox_c1 * _mixbox_c11) * vec3(+0.95912302, +0.80256528, +0.03561839) + + (_mixbox_c2 * _mixbox_c22) * vec3(+0.74683774, +0.04868586, +0.00000000) + + (_mixbox_c3 * _mixbox_c33) * vec3(+0.99518138, +0.99978149, +0.99704802) + + (_mixbox_c00 * _mixbox_c1) * vec3(+0.04819146, +0.83363781, +0.32515377) + + (_mixbox_c01 * _mixbox_c1) * vec3(-0.68146950, +1.46107803, +1.06980936) + + (_mixbox_c00 * _mixbox_c2) * vec3(+0.27058419, -0.15324870, +1.98735057) + + (_mixbox_c02 * _mixbox_c2) * vec3(+0.80478189, +0.67093710, +0.18424500) + + (_mixbox_c00 * _mixbox_c3) * vec3(-0.35031003, +1.37855826, +3.68865000) + + (_mixbox_c0 * _mixbox_c33) * vec3(+1.05128046, +1.97815239, +2.82989073) + + (_mixbox_c11 * _mixbox_c2) * vec3(+3.21607125, +0.81270228, +1.03384539) + + (_mixbox_c1 * _mixbox_c22) * vec3(+2.78893374, +0.41565549, -0.04487295) + + (_mixbox_c11 * _mixbox_c3) * vec3(+3.02162577, +2.55374103, +0.32766114) + + (_mixbox_c1 * _mixbox_c33) * vec3(+2.95124691, +2.81201112, +1.17578442) + + (_mixbox_c22 * _mixbox_c3) * vec3(+2.82677043, +0.79933038, +1.81715262) + + (_mixbox_c2 * _mixbox_c33) * vec3(+2.99691099, +1.22593053, +1.80653661) + + (_mixbox_c01 * _mixbox_c2) * vec3(+1.87394106, +2.05027182, -0.29835996) + + (_mixbox_c01 * _mixbox_c3) * vec3(+2.56609566, +7.03428198, +0.62575374) + + (_mixbox_c02 * _mixbox_c3) * vec3(+4.08329484, -1.40408358, +2.14995522) + + (_mixbox_c12 * _mixbox_c3) * vec3(+6.00078678, +2.55552042, +1.90739502)); +} + +mat3 mixbox_rgb_to_latent(vec3 _mixbox_rgb) { + _mixbox_rgb = clamp(_mixbox_rgb, 0.0, 1.0); + + float _mixbox_x = _mixbox_rgb.r * 63.0; + float _mixbox_y = _mixbox_rgb.g * 63.0; + float _mixbox_z = _mixbox_rgb.b * 63.0; + + float _mixbox_iz = floor(_mixbox_z); + + float _mixbox_x0 = mod(_mixbox_iz, 8.0) * 64.0; + float _mixbox_y0 = floor(_mixbox_iz / 8.0) * 64.0; + + float _mixbox_x1 = mod(_mixbox_iz + 1.0, 8.0) * 64.0; + float _mixbox_y1 = floor((_mixbox_iz + 1.0) / 8.0) * 64.0; + + vec2 _mixbox_uv0 = vec2(_mixbox_x0 + _mixbox_x + 0.5, _mixbox_y0 + _mixbox_y + 0.5) / 512.0; + vec2 _mixbox_uv1 = vec2(_mixbox_x1 + _mixbox_x + 0.5, _mixbox_y1 + _mixbox_y + 0.5) / 512.0; + + vec3 _mixbox_c = mix(textureLod(mixbox_lut, _mixbox_uv0, 0.0).rgb, textureLod(mixbox_lut, _mixbox_uv1, 0.0).rgb, _mixbox_z - _mixbox_iz); + + return mat3(_mixbox_c, _mixbox_rgb - _mixbox_eval_polynomial(_mixbox_c), vec3(0.0)); +} + +vec3 mixbox_latent_to_rgb(mat3 _mixbox_latent) { + return clamp(_mixbox_eval_polynomial(_mixbox_latent[0]) + _mixbox_latent[1], 0.0, 1.0); +} + +vec4 mixbox_lerp(vec4 _mixbox_color1, vec4 _mixbox_color2, float _mixbox_t) { + return vec4(mixbox_latent_to_rgb((1.0-_mixbox_t)*mixbox_rgb_to_latent(_mixbox_color1.rgb) + _mixbox_t*mixbox_rgb_to_latent(_mixbox_color2.rgb)), mix(_mixbox_color1.a, _mixbox_color2.a, _mixbox_t)); +} + +void fragment() { + COLOR = mixbox_lerp(color1, color2, UV.x); +} diff --git a/godot/addons/mixbox/mixbox.gdshaderinc b/godot/addons/mixbox/mixbox.gdshaderinc new file mode 100644 index 0000000..dc7c607 --- /dev/null +++ b/godot/addons/mixbox/mixbox.gdshaderinc @@ -0,0 +1,110 @@ +// ========================================================== +// MIXBOX 2.0 (c) 2022 Secret Weapons. All rights reserved. +// License: Creative Commons Attribution-NonCommercial 4.0 +// Authors: Sarka Sochorova and Ondrej Jamriska +// ========================================================== +// +// BASIC USAGE +// +// vec3 rgb = mixbox_lerp(rgb1, rgb2, t); +// +// MULTI-COLOR MIXING +// +// mat3 z1 = mixbox_rgb_to_latent(rgb1); +// mat3 z2 = mixbox_rgb_to_latent(rgb2); +// mat3 z3 = mixbox_rgb_to_latent(rgb3); +// +// // mix 30% of rgb1, 60% of rgb2, and 10% of rgb3 +// mat3 z_mix = 0.3*z1 + 0.6*z2 + 0.1*z3; +// +// vec3 rgb_mix = mixbox_latent_to_rgb(z_mix); +// +// PIGMENT COLORS +// +// Cadmium Yellow 0.996, 0.925, 0.000 +// Hansa Yellow 0.988, 0.827, 0.000 +// Cadmium Orange 1.000, 0.412, 0.000 +// Cadmium Red 1.000, 0.153, 0.008 +// Quinacridone Magenta 0.502, 0.008, 0.180 +// Cobalt Violet 0.306, 0.000, 0.259 +// Ultramarine Blue 0.098, 0.000, 0.349 +// Cobalt Blue 0.000, 0.129, 0.522 +// Phthalo Blue 0.051, 0.106, 0.267 +// Phthalo Green 0.000, 0.235, 0.196 +// Permanent Green 0.027, 0.427, 0.086 +// Sap Green 0.420, 0.580, 0.016 +// Burnt Sienna 0.482, 0.282, 0.000 +// +// LICENSING +// +// If you want to obtain commercial license, please +// contact us at: mixbox@scrtwpns.com +// + +vec3 _mixbox_eval_polynomial(vec3 _mixbox_c) { + float _mixbox_c0 = _mixbox_c[0]; + float _mixbox_c1 = _mixbox_c[1]; + float _mixbox_c2 = _mixbox_c[2]; + float _mixbox_c3 = 1.0 - (_mixbox_c0 + _mixbox_c1 + _mixbox_c2); + + float _mixbox_c00 = _mixbox_c0 * _mixbox_c0; + float _mixbox_c11 = _mixbox_c1 * _mixbox_c1; + float _mixbox_c22 = _mixbox_c2 * _mixbox_c2; + float _mixbox_c01 = _mixbox_c0 * _mixbox_c1; + float _mixbox_c02 = _mixbox_c0 * _mixbox_c2; + float _mixbox_c12 = _mixbox_c1 * _mixbox_c2; + float _mixbox_c33 = _mixbox_c3 * _mixbox_c3; + + return ( + (_mixbox_c0 * _mixbox_c00) * vec3(+0.07717053, +0.02826978, +0.24832992) + + (_mixbox_c1 * _mixbox_c11) * vec3(+0.95912302, +0.80256528, +0.03561839) + + (_mixbox_c2 * _mixbox_c22) * vec3(+0.74683774, +0.04868586, +0.00000000) + + (_mixbox_c3 * _mixbox_c33) * vec3(+0.99518138, +0.99978149, +0.99704802) + + (_mixbox_c00 * _mixbox_c1) * vec3(+0.04819146, +0.83363781, +0.32515377) + + (_mixbox_c01 * _mixbox_c1) * vec3(-0.68146950, +1.46107803, +1.06980936) + + (_mixbox_c00 * _mixbox_c2) * vec3(+0.27058419, -0.15324870, +1.98735057) + + (_mixbox_c02 * _mixbox_c2) * vec3(+0.80478189, +0.67093710, +0.18424500) + + (_mixbox_c00 * _mixbox_c3) * vec3(-0.35031003, +1.37855826, +3.68865000) + + (_mixbox_c0 * _mixbox_c33) * vec3(+1.05128046, +1.97815239, +2.82989073) + + (_mixbox_c11 * _mixbox_c2) * vec3(+3.21607125, +0.81270228, +1.03384539) + + (_mixbox_c1 * _mixbox_c22) * vec3(+2.78893374, +0.41565549, -0.04487295) + + (_mixbox_c11 * _mixbox_c3) * vec3(+3.02162577, +2.55374103, +0.32766114) + + (_mixbox_c1 * _mixbox_c33) * vec3(+2.95124691, +2.81201112, +1.17578442) + + (_mixbox_c22 * _mixbox_c3) * vec3(+2.82677043, +0.79933038, +1.81715262) + + (_mixbox_c2 * _mixbox_c33) * vec3(+2.99691099, +1.22593053, +1.80653661) + + (_mixbox_c01 * _mixbox_c2) * vec3(+1.87394106, +2.05027182, -0.29835996) + + (_mixbox_c01 * _mixbox_c3) * vec3(+2.56609566, +7.03428198, +0.62575374) + + (_mixbox_c02 * _mixbox_c3) * vec3(+4.08329484, -1.40408358, +2.14995522) + + (_mixbox_c12 * _mixbox_c3) * vec3(+6.00078678, +2.55552042, +1.90739502)); +} + +mat3 mixbox_rgb_to_latent(vec3 _mixbox_rgb) { + _mixbox_rgb = clamp(_mixbox_rgb, 0.0, 1.0); + + float _mixbox_x = _mixbox_rgb.r * 63.0; + float _mixbox_y = _mixbox_rgb.g * 63.0; + float _mixbox_z = _mixbox_rgb.b * 63.0; + + float _mixbox_iz = floor(_mixbox_z); + + float _mixbox_x0 = mod(_mixbox_iz, 8.0) * 64.0; + float _mixbox_y0 = floor(_mixbox_iz / 8.0) * 64.0; + + float _mixbox_x1 = mod(_mixbox_iz + 1.0, 8.0) * 64.0; + float _mixbox_y1 = floor((_mixbox_iz + 1.0) / 8.0) * 64.0; + + vec2 _mixbox_uv0 = vec2(_mixbox_x0 + _mixbox_x + 0.5, _mixbox_y0 + _mixbox_y + 0.5) / 512.0; + vec2 _mixbox_uv1 = vec2(_mixbox_x1 + _mixbox_x + 0.5, _mixbox_y1 + _mixbox_y + 0.5) / 512.0; + + vec3 _mixbox_c = mix(textureLod(mixbox_lut, _mixbox_uv0, 0.0).rgb, textureLod(mixbox_lut, _mixbox_uv1, 0.0).rgb, _mixbox_z - _mixbox_iz); + + return mat3(_mixbox_c, _mixbox_rgb - _mixbox_eval_polynomial(_mixbox_c), vec3(0.0)); +} + +vec3 mixbox_latent_to_rgb(mat3 _mixbox_latent) { + return clamp(_mixbox_eval_polynomial(_mixbox_latent[0]) + _mixbox_latent[1], 0.0, 1.0); +} + +vec4 mixbox_lerp(vec4 _mixbox_color1, vec4 _mixbox_color2, float _mixbox_t) { + return vec4(mixbox_latent_to_rgb((1.0-_mixbox_t)*mixbox_rgb_to_latent(_mixbox_color1.rgb) + _mixbox_t*mixbox_rgb_to_latent(_mixbox_color2.rgb)), mix(_mixbox_color1.a, _mixbox_color2.a, _mixbox_t)); +} diff --git a/godot/addons/mixbox/mixbox.res b/godot/addons/mixbox/mixbox.res new file mode 100644 index 0000000..64ea5d5 Binary files /dev/null and b/godot/addons/mixbox/mixbox.res differ diff --git a/godot/addons/mixbox/mixbox_lerp_node.gd b/godot/addons/mixbox/mixbox_lerp_node.gd new file mode 100644 index 0000000..3156b1a --- /dev/null +++ b/godot/addons/mixbox/mixbox_lerp_node.gd @@ -0,0 +1,163 @@ +# ========================================================== +# MIXBOX 2.0 (c) 2022 Secret Weapons. All rights reserved. +# License: Creative Commons Attribution-NonCommercial 4.0 +# Authors: Sarka Sochorova and Ondrej Jamriska +# ========================================================== +# +# USAGE +# +# VisualShader: Add Node... > Mixbox > MixboxLerp +# +# Inspector: +# Drag file "res://addons/mixbox/mixbox_lut.png" +# to "Material > Shader Param > Mixbox Lut" slot. +# +# PIGMENT COLORS +# +# Cadmium Yellow 0.996, 0.925, 0.000 +# Hansa Yellow 0.988, 0.827, 0.000 +# Cadmium Orange 1.000, 0.412, 0.000 +# Cadmium Red 1.000, 0.153, 0.008 +# Quinacridone Magenta 0.502, 0.008, 0.180 +# Cobalt Violet 0.306, 0.000, 0.259 +# Ultramarine Blue 0.098, 0.000, 0.349 +# Cobalt Blue 0.000, 0.129, 0.522 +# Phthalo Blue 0.051, 0.106, 0.267 +# Phthalo Green 0.000, 0.235, 0.196 +# Permanent Green 0.027, 0.427, 0.086 +# Sap Green 0.420, 0.580, 0.016 +# Burnt Sienna 0.482, 0.282, 0.000 +# +# LICENSING +# +# If you want to obtain commercial license, please +# contact us at: mixbox@scrtwpns.com +# + +tool +extends VisualShaderNodeCustom +class_name VisualShaderNodeMixboxLerp + +func _init(): + set_input_port_default_value(0, Vector3(0.0, 0.129, 0.522)) + set_input_port_default_value(1, Vector3(0.988, 0.827, 0.0)) + set_input_port_default_value(2, 0.5) + +func _get_name(): + return "MixboxLerp" + +func _get_category(): + return "Mixbox" + +func _get_description(): + return "Mixbox" + +func _get_return_icon_type(): + return VisualShaderNode.PORT_TYPE_VECTOR + +func _get_input_port_count(): + return 3 + +func _get_input_port_name(port): + match port: + 0: + return "a" + 1: + return "b" + 2: + return "t" + +func _get_input_port_type(port): + match port: + 0: + return VisualShaderNode.PORT_TYPE_VECTOR + 1: + return VisualShaderNode.PORT_TYPE_VECTOR + 2: + return VisualShaderNode.PORT_TYPE_SCALAR + +func _get_output_port_count(): + return 1 + + +func _get_output_port_name(port): + return "result" + +func _get_output_port_type(port): + return VisualShaderNode.PORT_TYPE_VECTOR + +func _get_global_code(mode): + return """ +uniform sampler2D mixbox_lut; + +vec3 _mixbox_eval_polynomial(vec3 _mixbox_c) { + float _mixbox_c0 = _mixbox_c[0]; + float _mixbox_c1 = _mixbox_c[1]; + float _mixbox_c2 = _mixbox_c[2]; + float _mixbox_c3 = 1.0 - (_mixbox_c0 + _mixbox_c1 + _mixbox_c2); + + float _mixbox_c00 = _mixbox_c0 * _mixbox_c0; + float _mixbox_c11 = _mixbox_c1 * _mixbox_c1; + float _mixbox_c22 = _mixbox_c2 * _mixbox_c2; + float _mixbox_c01 = _mixbox_c0 * _mixbox_c1; + float _mixbox_c02 = _mixbox_c0 * _mixbox_c2; + float _mixbox_c12 = _mixbox_c1 * _mixbox_c2; + float _mixbox_c33 = _mixbox_c3 * _mixbox_c3; + + return ( + (_mixbox_c0 * _mixbox_c00) * vec3(+0.07717053, +0.02826978, +0.24832992) + + (_mixbox_c1 * _mixbox_c11) * vec3(+0.95912302, +0.80256528, +0.03561839) + + (_mixbox_c2 * _mixbox_c22) * vec3(+0.74683774, +0.04868586, +0.00000000) + + (_mixbox_c3 * _mixbox_c33) * vec3(+0.99518138, +0.99978149, +0.99704802) + + (_mixbox_c00 * _mixbox_c1) * vec3(+0.04819146, +0.83363781, +0.32515377) + + (_mixbox_c01 * _mixbox_c1) * vec3(-0.68146950, +1.46107803, +1.06980936) + + (_mixbox_c00 * _mixbox_c2) * vec3(+0.27058419, -0.15324870, +1.98735057) + + (_mixbox_c02 * _mixbox_c2) * vec3(+0.80478189, +0.67093710, +0.18424500) + + (_mixbox_c00 * _mixbox_c3) * vec3(-0.35031003, +1.37855826, +3.68865000) + + (_mixbox_c0 * _mixbox_c33) * vec3(+1.05128046, +1.97815239, +2.82989073) + + (_mixbox_c11 * _mixbox_c2) * vec3(+3.21607125, +0.81270228, +1.03384539) + + (_mixbox_c1 * _mixbox_c22) * vec3(+2.78893374, +0.41565549, -0.04487295) + + (_mixbox_c11 * _mixbox_c3) * vec3(+3.02162577, +2.55374103, +0.32766114) + + (_mixbox_c1 * _mixbox_c33) * vec3(+2.95124691, +2.81201112, +1.17578442) + + (_mixbox_c22 * _mixbox_c3) * vec3(+2.82677043, +0.79933038, +1.81715262) + + (_mixbox_c2 * _mixbox_c33) * vec3(+2.99691099, +1.22593053, +1.80653661) + + (_mixbox_c01 * _mixbox_c2) * vec3(+1.87394106, +2.05027182, -0.29835996) + + (_mixbox_c01 * _mixbox_c3) * vec3(+2.56609566, +7.03428198, +0.62575374) + + (_mixbox_c02 * _mixbox_c3) * vec3(+4.08329484, -1.40408358, +2.14995522) + + (_mixbox_c12 * _mixbox_c3) * vec3(+6.00078678, +2.55552042, +1.90739502)); +} + +mat3 _mixbox_rgb_to_latent(vec3 _mixbox_rgb) { + _mixbox_rgb = clamp(_mixbox_rgb, 0.0, 1.0); + + float _mixbox_x = _mixbox_rgb.r * 63.0; + float _mixbox_y = _mixbox_rgb.g * 63.0; + float _mixbox_z = _mixbox_rgb.b * 63.0; + + float _mixbox_iz = floor(_mixbox_z); + + float _mixbox_x0 = mod(_mixbox_iz, 8.0) * 64.0; + float _mixbox_y0 = floor(_mixbox_iz / 8.0) * 64.0; + + float _mixbox_x1 = mod(_mixbox_iz + 1.0, 8.0) * 64.0; + float _mixbox_y1 = floor((_mixbox_iz + 1.0) / 8.0) * 64.0; + + vec2 _mixbox_uv0 = vec2(_mixbox_x0 + _mixbox_x + 0.5, _mixbox_y0 + _mixbox_y + 0.5) / 512.0; + vec2 _mixbox_uv1 = vec2(_mixbox_x1 + _mixbox_x + 0.5, _mixbox_y1 + _mixbox_y + 0.5) / 512.0; + + vec3 _mixbox_c = mix(textureLod(mixbox_lut, _mixbox_uv0, 0.0).rgb, textureLod(mixbox_lut, _mixbox_uv1, 0.0).rgb, _mixbox_z - _mixbox_iz); + + return mat3(_mixbox_c, _mixbox_rgb - _mixbox_eval_polynomial(_mixbox_c), vec3(0.0)); +} + +vec3 _mixbox_latent_to_rgb(mat3 _mixbox_latent) { + return clamp(_mixbox_eval_polynomial(_mixbox_latent[0]) + _mixbox_latent[1], 0.0, 1.0); +} + +vec3 _mixbox_lerp(vec3 _mixbox_color1, vec3 _mixbox_color2, float _mixbox_t) { + return _mixbox_latent_to_rgb((1.0-_mixbox_t)*_mixbox_rgb_to_latent(_mixbox_color1.rgb) + _mixbox_t*_mixbox_rgb_to_latent(_mixbox_color2.rgb)); +} + """ + +func _get_code(input_vars, output_vars, mode, type): + return output_vars[0] + " = _mixbox_lerp(%s, %s, %s);" % [input_vars[0], input_vars[1], input_vars[2]] diff --git a/godot/addons/mixbox/mixbox_lut.png b/godot/addons/mixbox/mixbox_lut.png new file mode 100644 index 0000000..db1286f Binary files /dev/null and b/godot/addons/mixbox/mixbox_lut.png differ diff --git a/godot/addons/mixbox/mixbox_lut.png.import b/godot/addons/mixbox/mixbox_lut.png.import new file mode 100644 index 0000000..6b98872 --- /dev/null +++ b/godot/addons/mixbox/mixbox_lut.png.import @@ -0,0 +1,35 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/mixbox_lut.png-d8cb77d0d5322618f1648925da003780.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://addons/mixbox/mixbox_lut.png" +dest_files=[ "res://.import/mixbox_lut.png-d8cb77d0d5322618f1648925da003780.stex" ] + +[params] + +compress/mode=3 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=true +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=false +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +process/normal_map_invert_y=false +stream=false +size_limit=0 +detect_3d=false +svg/scale=1.0