Blending functions
From polycount
Revision as of 14:49, 6 August 2014 by Haiddasalami (Talk | contribs)
Here are all the Photoshop Blending Modes, in easy to use functions for various languages.
Contents
HLSL
Category 1 (Darker)
float4 Darken (float4 cBase, float4 cBlend)
{
float4 cNew;
cNew.rgb = min(cBase.rgb, cBlend.rgb);
cNew.a = 1.0;
return cNew;
}
float4 Multiply (float4 cBase, float4 cBlend)
{
return (cBase * cBlend);
}
float4 ColorBurn (float4 cBase, float4 cBlend)
{
return (1 - (1 - cBase) / cBlend);
}
float4 LinearBurn (float4 cBase, float4 CBlend)
{
return (cBase + cBlend - 1);
}
Category 2 (Lighter)
float4 Lighten (float4 cBase, float4 cBlend)
{
float4 cNew;
cNew.rgb = max(cBase.rgb, cBlend.rgb);
cNew.a = 1.0;
return cNew;
}
float4 Screen (float4 cBase, float4 cBlend)
{
return (1 - (1 - cBase) * (1 - cBlend));
}
float4 ColorDodge (float4 cBase, float4 cBlend)
{
return (cBase / (1 - cBlend));
}
float4 LinearDodge (float4 cBase, float4 cBlend)
{
return (cBase + cBlend);
}
Category 3 (Complex)
float4 Overlay (float4 cBase, float4 cBlend)
{
/*
float4 cNew;
if (cBase.r > .5) { cNew.r = 1 - (1 - 2 * (cBase.r - .5)) * (1 - cBlend.r); }
else { cNew.r = (2 * cBase.r) * cBlend.r; }
if (cBase.g > .5) { cNew.g = 1 - (1 - 2 * (cBase.g - .5)) * (1 - cBlend.g); }
else { cNew.g = (2 * cBase.g) * cBlend.g; }
if (cBase.b > .5) { cNew.b = 1 - (1 - 2 * (cBase.b - .5)) * (1 - cBlend.b); }
else { cNew.b = (2 * cBase.b) * cBlend.b; }
cNew.a = 1.0;
return cNew;
*/
// Vectorized (easier for compiler)
float4 cNew;
// overlay has two output possbilities
// which is taken is decided if pixel value
// is below half or not
cNew = step(0.5,cBase);
// we pick either solution
// depending on pixel
// first is case of < 0.5
// second is case for >= 0.5
// interpolate between the two,
// using color as influence value
cNew= lerp((cBase*cBlend*2),(1.0-(2.0*(1.0-cBase)*(1.0-cBlend))),cNew);
cNew.a = 1.0;
return cNew;
}
float4 SoftLight (float4 cBase, float4 cBlend)
{
float4 cNew;
if (cBlend.r > .5) { cNew.r = cBase.r * (1 - (1 - cBase.r) * (1 - 2 * (cBlend.r)));}
else { cNew.r = 1 - (1 - cBase.r) * (1 - (cBase.r * (2 * cBlend.r))); }
if (cBlend.g > .5) { cNew.g = cBase.g * (1 - (1 - cBase.g) * (1 - 2 * (cBlend.g)));}
else { cNew.g = 1 - (1 - cBase.g) * (1 - (cBase.g * (2 * cBlend.g))); }
if (cBlend.g > .5) { cNew.b = cBase.b * (1 - (1 - cBase.b) * (1 - 2 * (cBlend.b)));}
else { cNew.b = 1 - (1 - cBase.b) * (1 - (cBase.b * (2 * cBlend.b))); }
cNew.a = 1.0;
return cNew;
}
float4 HardLight (float4 cBase, float4 cBlend)
{
float4 cNew;
if (cBlend.r > .5) { cNew.r = 1 - (1 - cBase.r) * (1 - 2 * (cBlend.r)); }
else { cNew.r = cBase.r * (2 * cBlend.r); }
if (cBlend.g > .5) { cNew.g = 1 - (1 - cBase.g) * (1 - 2 * (cBlend.g)); }
else { cNew.g = cBase.g * (2 * cBlend.g); }
if (cBlend.b > .5) { cNew.b = 1 - (1 - cBase.b) * (1 - 2 * (cBlend.b)); }
else { cNew.b = cBase.b * (2 * cBlend.b); }
cNew.a = 1.0;
return cNew;
}
float4 VividLight (float4 cBase, float4 cBlend)
{
float4 cNew;
if (cBlend.r > .5) {cNew.r = 1 - (1 - cBase.r) / (2 * (cBlend.r - .5)); }
else {cNew.r = cBase.r / (1 - 2 * cBlend.r); }
if (cBlend.g > .5) {cNew.g = 1 - (1 - cBase.g) / (2 * (cBlend.g - .5)); }
else {cNew.g = cBase.g / (1 - 2 * cBlend.g); }
if (cBlend.b > .5) {cNew.b = 1 - (1 - cBase.b) / (2 * (cBlend.b - .5)); }
else {cNew.b = cBase.b / (1 - 2 * cBlend.b); }
cNew.a = 1.0;
return cNew;
}
float4 LinearLight (float4 cBase, float4 cBlend)
{
float4 cNew;
if (cBlend.r > .5) {cNew.r = cBase.r + 2 * (cBlend.r - .5); }
else {cNew.r = cBase.r + 2 * cBlend.r - 1; }
if (cBlend.g > .5) {cNew.g = cBase.g + 2 * (cBlend.g - .5); }
else {cNew.g = cBase.g + 2 * cBlend.g - 1; }
if (cBlend.b > .5) {cNew.b = cBase.b + 2 * (cBlend.b - .5); }
else {cNew.b = cBase.b + 2 * cBlend.b - 1; }
cNew.a = 1.0;
return cNew;
}
float4 PinLight (float4 cBase, float4 cBlend)
{
float4 cNew;
if (cBlend.r > .5) { cNew.r = max(cBase.r, 2 * (cBlend.r - .5)); }
else {cNew.r = min(cBase.r, 2 * cBlend.r); }
if (cBlend.g > .5) { cNew.g = max(cBase.g, 2 * (cBlend.g - .5)); }
else {cNew.g = min(cBase.g, 2 * cBlend.g); }
if (cBlend.b > .5) { cNew.b = max(cBase.b, 2 * (cBlend.b - .5)); }
else {cNew.b = min(cBase.b, 2 * cBlend.b); }
cNew.a = 1.0;
return cNew;
}
Category 4 (Comparison)
float4 Difference (float4 cBase, float4 cBlend)
{
return (abs(cBase - cBlend));
}
float4 Exclusion (float4 cBase, float4 cBlend)
{
return (.5 - 2 * (cBase - .5) * (cBlend - .5));
}