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