diff --git a/src/doc/stdlib.md b/src/doc/stdlib.md
index bcc803ebb..d818b7062 100644
--- a/src/doc/stdlib.md
+++ b/src/doc/stdlib.md
@@ -166,6 +166,12 @@ the computations are performed component-by-component (separately for `x`,
$ x*(1-\alpha) + y*(\alpha) $
+*`type`* **`unmix`** (*`type`* `x`, *`type`* `y`, *`type`* `alpha`)
*`type`* **`unmix`** (*`type`* `x`, *`type`* `y, float alpha`)
+ : The `unmix` function returns a inverse of `mix`, similar to inverse linear interpolation:
+ $ (x - (\alpha)) / (y - x) $
+ The x and y value can't be the same, as we can't divide by zero.
+
+
*`type`* **`select`** (*`type`* `x`, *`type`* `y`, *`type`* `cond`)
*`type`* **`select`** (*`type`* `x`, *`type`* `y, float cond`)
*`type`* **`select`** (*`type`* `x`, *`type`* `y, int cond`)
: The `select` function returns `x` if `cond` is zero, or `y`
if `cond` is nonzero. This is roughly equivalent to `(cond ? y : x)`,
diff --git a/src/shaders/color2.h b/src/shaders/color2.h
index ca7bef3c4..1c6fa325a 100644
--- a/src/shaders/color2.h
+++ b/src/shaders/color2.h
@@ -183,6 +183,12 @@ color2 mix(color2 a, color2 b, float x )
mix(a.a, b.a, x));
}
+color2 unmix(color2 a, color2 b, float x )
+{
+ return color2(unmix(a.r, b.r, x),
+ unmix(a.a, b.a, x));
+}
+
color2 smoothstep(color2 edge0, color2 edge1, color2 c)
{
return color2(smoothstep(edge0.r, edge1.r, c.r),
diff --git a/src/shaders/color4.h b/src/shaders/color4.h
index 84610f0f1..4b216872c 100644
--- a/src/shaders/color4.h
+++ b/src/shaders/color4.h
@@ -183,6 +183,12 @@ color4 mix(color4 a, color4 b, float x )
mix(a.a, b.a, x));
}
+color4 unmix(color4 a, color4 b, float x )
+{
+ return color4(unmix(a.rgb, b.rgb, x),
+ unmix(a.a, b.a, x));
+}
+
color4 smoothstep(color4 edge0, color4 edge1, color4 c)
{
return color4(smoothstep(edge0.rgb, edge1.rgb, c.rgb),
diff --git a/src/shaders/stdosl.h b/src/shaders/stdosl.h
index ee86ae7be..be4e35a51 100644
--- a/src/shaders/stdosl.h
+++ b/src/shaders/stdosl.h
@@ -164,6 +164,32 @@ float mix (float x, float y, float a) BUILTIN;
closure color mix (closure color x, closure color y, float a) { return x*(1-a) + y*a; }
closure color mix (closure color x, closure color y, color a) { return x*(1-a) + y*a; }
+#if 0 // Assuming x != y
+normal unmix (normal x, normal y, normal a) { return (a - x) / (y - x); }
+normal unmix (normal x, normal y, float a) { return (a - x) / (y - x); }
+vector unmix (vector x, vector y, vector a) { return (a - x) / (y - x); }
+vector unmix (vector x, vector y, float a) { return (a - x) / (y - x); }
+point unmix (point x, point y, point a) { return (a - x) / (y - x); }
+point unmix (point x, point y, float a) { return (a - x) / (y - x); }
+color unmix (color x, color y, color a) { return (a - x) / (y - x); }
+color unmix (color x, color y, float a) { return (a - x) / (y - x); }
+float unmix (float x, float y, float a) { return (a - x) / (y - x); }
+#else
+normal unmix (normal x, normal y, normal a) BUILTIN;
+normal unmix (normal x, normal y, float a) BUILTIN;
+vector unmix (vector x, vector y, vector a) BUILTIN;
+vector unmix (vector x, vector y, float a) BUILTIN;
+point unmix (point x, point y, point a) BUILTIN;
+point unmix (point x, point y, float a) BUILTIN;
+color unmix (color x, color y, color a) BUILTIN;
+color unmix (color x, color y, float a) BUILTIN;
+float unmix (float x, float y, float a) BUILTIN;
+#endif
+// closure color unmix (closure color x, closure color y, float a) { return (a - x) / (y - x); }
+// closure color unmix (closure color x, closure color y, color a) { return (a - x) / (y - x); }
+
+// TODO: ADD REMAP FROM MIX AND UNMIX
+
normal select (normal x, normal y, normal cond) BUILTIN;
vector select (vector x, vector y, vector cond) BUILTIN;
point select (point x, point y, point cond) BUILTIN;
diff --git a/src/shaders/vector2.h b/src/shaders/vector2.h
index f57307a66..39085e233 100644
--- a/src/shaders/vector2.h
+++ b/src/shaders/vector2.h
@@ -182,6 +182,11 @@ vector2 mix(vector2 a, vector2 b, float x )
return vector2 (mix(a.x, b.x, x), mix(a.y, b.y, x));
}
+vector2 unmix(vector2 a, vector2 b, float x )
+{
+ return vector2 (unmix(a.x, b.x, x), unmix(a.y, b.y, x));
+}
+
float dot(vector2 a, vector2 b)
{
return (a.x * b.x + a.y * b.y);
diff --git a/src/shaders/vector4.h b/src/shaders/vector4.h
index c30167bf9..573a769ba 100644
--- a/src/shaders/vector4.h
+++ b/src/shaders/vector4.h
@@ -209,6 +209,14 @@ vector4 mix(vector4 value1, vector4 value2, float x )
mix( value1.w, value2.w, x));
}
+vector4 unmix(vector4 value1, vector4 value2, float x )
+{
+ return vector4 (unmix( value1.x, value2.x, x),
+ unmix( value1.y, value2.y, x),
+ unmix( value1.z, value2.z, x),
+ unmix( value1.w, value2.w, x));
+}
+
vector vec4ToVec3(vector4 v)
{
return vector(v.x, v.y, v.z) / v.w;