Blending functions

From polycount
Revision as of 15:49, 6 August 2014 by Haiddasalami (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Here are all the Photoshop Blending Modes, in easy to use functions for various languages.

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));
}
Personal tools
Namespaces

Variants
Actions
Navigation
Tools