Mixbox: Pigment-Based Color Mixing
Mixbox is a new blending method for natural color mixing. It produces saturated gradients with hue shifts and natural secondary colors during blending. Yellow and blue make green. The interface is simple - RGB in, RGB out. Internally, Mixbox treats colors as real-life pigments using the Kubelka & Munk theory to predict realistic color behavior. That way, colors act like actual paints and bring more vibrance and intuition into digital painting.
Video: https://youtu.be/ATzVPVNp1qA
Mixbox is shipping in Rebelle 5 Pro as the Rebelle Pigments feature and in the Flip Fluids addon for Blender.
Usage
C / C++:
#include "mixbox.h"
and buildmixbox.cpp
together with your projectC#: use Mixbox package from NuGet
https://www.nuget.org/packages/Mixbox/2.0.0
Java: add
implementation 'com.scrtwpns:mixbox:2.0.0'
to your GradleJavaScript:
<script src="https://scrtwpns.com/mixbox.js">
Node:
npm install mixbox
Python:
pip install pymixbox
Rust: add
mixbox = "2.0.0"
to your Cargo.tomlUnity: add package from git url
git://github.com/scrtwpns/mixbox.git#upm
Godot: copy
godot\addons
to the root of your projectShaders: load
mixbox_lut.png
as texture and paste the Mixbox.glsl
/.hlsl
code into your shader
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 |
C / C++
#include <stdio.h>
#include "mixbox.h"
int main() {
unsigned char r1 = 0, g1 = 33, b1 = 133; // blue
unsigned char r2 = 252, g2 = 211, b2 = 0; // yellow
float t = 0.5;
unsigned char r, g, b;
mixbox_lerp(r1, g1, b1, // first color
r2, g2, b2, // second color
t, // mixing ratio
&r, &g, &b); // result
printf("%d %d %d\n", r, g, b);
}
GLSL Shader
#ifdef GL_ES
precision highp float;
#endif
uniform sampler2D mixbox_lut; // bind the "mixbox_lut.png" texture here
#include "mixbox.glsl" // paste the contents of mixbox.glsl here
void main(void) {
vec3 rgb1 = vec3(0, 0.129, 0.522); // blue
vec3 rgb2 = vec3(0.988, 0.827, 0); // yellow
float t = 0.5; // mixing ratio
vec3 rgb = mixbox_lerp(rgb1, rgb2, t);
gl_FragColor = vec4(rgb, 1.0);
}
Rust
fn main() {
let rgb1 = [0, 33, 133]; // blue
let rgb2 = [252, 211, 0]; // yellow
let t = 0.5; // mixing ratio
let [r, g, b] = mixbox::lerp(&rgb1, &rgb2, t);
println!("{} {} {}", r, g, b);
}
Python
import mixbox
rgb1 = (0, 33, 133) # blue
rgb2 = (252, 211, 0) # yellow
t = 0.5 # mixing ratio
rgb_mix = mixbox.lerp(rgb1, rgb2, t)
print(rgb_mix)
JavaScript
<html>
<body>
<script src="https://scrtwpns.com/mixbox.js"></script>
<script>
var rgb1 = "rgb(0, 33, 133)"; // blue
var rgb2 = "rgb(252, 211, 0)"; // yellow
var t = 0.5; // mixing ratio
var mixed = mixbox.lerp(rgb1, rgb2, t);
document.body.style.background = mixed;
</script>
</body>
</html>
Node
import mixbox from 'mixbox';
let rgb1 = "rgb(0, 33, 133)"; // blue
let rgb2 = "rgb(252, 211, 0)"; // yellow
let t = 0.5; // mixing ratio
let mixed = mixbox.lerp(rgb1, rgb2, t);
console.log(mixed);
Java
import java.awt.Color;
import com.scrtwpns.Mixbox;
class HelloMixbox {
public static void main(String[] args) {
Color color1 = new Color(0, 33, 133); // blue
Color color2 = new Color(252, 211, 0); // yellow
float t = 0.5f; // mixing ratio
Color colorMix = new Color(Mixbox.lerp(color1.getRGB(), color2.getRGB(), t));
System.out.print(colorMix);
}
}
Android
package com.example.hellomixbox;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.graphics.Color;
import com.scrtwpns.Mixbox;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
int color1 = Color.rgb(0, 33, 133); // blue
int color2 = Color.rgb(252, 211, 0); // yellow
float t = 0.5f; // mixing ratio
int colorMix = Mixbox.lerp(color1, color2, t);
View view = new View(this);
view.setBackgroundColor(colorMix);
setContentView(view);
}
}
C#
using System.Drawing;
using Scrtwpns.Mixbox;
public class HelloMixbox
{
public static void Main(string[] args)
{
Color color1 = Color.FromArgb(0, 33, 133); // blue
Color color2 = Color.FromArgb(252, 211, 0); // yellow
float t = 0.5f; // mixing ratio
Color colorMix = Color.FromArgb(Mixbox.Lerp(color1.ToArgb(), color2.ToArgb(), t));
System.Console.WriteLine(colorMix);
}
}
Unity
using UnityEngine;
using Scrtwpns.Mixbox;
public class NewBehaviourScript : MonoBehaviour
{
void Start()
{
Color color1 = new Color(0.0f, 0.129f, 0.522f); // blue
Color color2 = new Color(0.988f, 0.827f, 0.0f); // yellow
float t = 0.5f; // mixing ratio
Color colorMix = Mixbox.Lerp(color1, color2, t);
Debug.Log(colorMix);
}
}
Unity Shader
Shader "MixboxHelloShader"
{
Properties
{
_MixboxLUT ("Mixbox LUT", 2D) = "white" {} // assign "Packages/Mixbox/Textures/MixboxLUT.png"
_Color1 ("Color 1", Color) = (0, 0.129, 0.522, 1) // blue
_Color2 ("Color 2", Color) = (0.988, 0.827, 0, 1) // yellow
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MixboxLUT;
#include "Packages/com.scrtwpns.mixbox/ShaderLibrary/Mixbox.cginc"
fixed4 _Color1;
fixed4 _Color2;
struct appdata { float4 vertex : POSITION; float2 uv : TEXCOORD0; };
struct v2f { float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; };
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
fixed4 mixedColor = MixboxLerp(_Color1, _Color2, i.uv.x);
return mixedColor;
}
ENDCG
}
}
}
Unity Shader Graph
Godot
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)
Godot Shader
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 "addons/mixbox/mixbox.gdshaderinc"
void fragment() {
COLOR = mixbox_lerp(color1, color2, UV.x);
}
Godot VisualShader
WebGL
<script src="https://scrtwpns.com/mixbox.js"></script>
var shader = `
precision highp float;
uniform sampler2D mixbox_lut; // bind mixbox.lutTexture(gl) here
#include "mixbox.glsl"
void main(void) {
vec3 rgb1 = vec3(0, 0.129, 0.522); // blue
vec3 rgb2 = vec3(0.988, 0.827, 0); // yellow
float t = 0.5; // mixing ratio
vec3 rgb = mixbox_lerp(rgb1, rgb2, t);
gl_FragColor = vec4(rgb, 1.0);
}
`;
shader = shader.replace('#include "mixbox.glsl"', mixbox.glsl());
gl.useProgram(shaderProgram);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, mixbox.lutTexture(gl));
gl.uniform1i(gl.getUniformLocation(shaderProgram, "mixbox_lut"), 0);
Examples
Gradients |
Mountains |
Palette Snakes |
---|---|---|
Splash Art |
Paint Mixer |
Pigment Fluids |
---|---|---|
Painter
This painting app runs two color mixing implementations in parallel: one based on Mixbox and the other that performs ordinary RGB mixing. The app allows switching between them on the fly, showing the differences between pigment-based mixing and the normal RGB mixing. To launch the painter in your browser, please click here.
Table of Contents
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