diff --git a/README.md b/README.md index e4051ba..2b8c9f0 100644 --- a/README.md +++ b/README.md @@ -1,67 +1,370 @@ -# Mixbox: Practical Pigment Mixing for Digital Painting - -

- -

- -Mixbox is a pigment mixing black-box. You pass RGB colors in and get the mixed RGB out. -Internally, Mixbox treats the colors as if they were made of actual real-world pigments. -It uses the Kubelka & Munk theory to predict the color of the resulting mixture. -This way, Mixbox achieves that blue and yellow mix to green, the same way real pigments do. - -* Paper: https://scrtwpns.com/mixbox.pdf
-* Video: https://youtu.be/ATzVPVNp1qA
-* Talk: https://youtu.be/_qa5iWdfNKg
-* Demo: https://scrtwpns.com/mixbox/painter
- -Mixbox is shipping in Rebelle 5 Pro as the [Rebelle Pigments](https://www.escapemotions.com/products/rebelle/about) feature. - -## Usage -The simplest way to use Mixbox is with the *lerp* interface: -```c++ -#include -#include "mixbox.h" - -int main() -{ - unsigned char r1=252, g1=211, b1=0; // bright yellow - unsigned char r2=0, g2=0, b2=96; // deep blue - float t = 0.5; - unsigned char r,g,b; - - mixbox_lerp_srgb8(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); -} -``` -Alternatively, one can use the *latent* interface. This allows mixing multiple RGB colors at once using arbitrary weights: - -```c++ -float latent1[MIXBOX_NUMLATENTS]; -float latent2[MIXBOX_NUMLATENTS]; -float latentMix[MIXBOX_NUMLATENTS]; - -mixbox_srgb8_to_latent(r1,g1,b1,latent1); -mixbox_srgb8_to_latent(r2,g2,b2,latent2); - -for(int i=0;i - -

-This is a toy painting app with soft round brush and a smudge tool. It 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 demo in your browser, please click here. - -## License -Copyright (c) 2022, Secret Weapons. All rights reserved.
-This code is for non-commercial use only. It is provided for research and evaluation purposes.
-If you wish to obtain commercial license, please contact: mixbox@scrtwpns.com - +# 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. + +* Paper: https://scrtwpns.com/mixbox.pdf
+* Video: https://youtu.be/ATzVPVNp1qA
+* Talk: https://youtu.be/_qa5iWdfNKg
+* Demo: https://scrtwpns.com/mixbox/painter
+ +Mixbox is shipping in Rebelle 5 Pro as the [Rebelle Pigments](https://www.escapemotions.com/products/rebelle/about) feature and in the [Flip Fluids](https://flipfluids.com/) addon for Blender. + +## Usage +- [C / C++](cpp): `#include "mixbox.h"` and build `mixbox.cpp` together with your project +- [C#](csharp): use Mixbox package from NuGet `https://www.nuget.org/packages/Mixbox/2.0.0` +- [Java](java): add `implementation 'com.scrtwpns:mixbox:2.0.0'` to your Gradle +- [JavaScript](javascript): ` + + + +``` +## Node +```javascript +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 +```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 +```java +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# +```csharp +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 +```csharp +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 +```ShaderLab +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 +```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) +``` + +## Godot Shader +```glsl +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 +```html + +``` +```javascript +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()); +``` +```javascript +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 | +|:---:|:---:|:---:| +| | | | +| [source code](javascript/examples/gradients.js) | [source code](javascript/examples/mountains.js) | [source code](javascript/examples/palette.js) | + +| Splash Art | Paint Mixer | Pigment Fluids | +|:---:|:---:|:---:| +| | | | +| [source code](javascript/examples/splash.html) | [source code](javascript/examples/mixer.js) | [source code](https://scrtwpns.com/mixbox/fluids/script.js) | + +## 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. + +## 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