Pixel Bender Toolkit:Blendmodes filter
From Adobe Labs
// http://www.pegtop.net/delphi/articles/blendmodes/ // Note: this is just for convenience, each blendmode would normally be contained in a separate .hydro file.
<languageVersion : 1.0;> kernel blendmodes <
namespace : "default"; vendor : "tvzero"; version : 1; description : "Blendmodes";
> {
parameter int blendmode <
minValue:int(0);
maxValue:int(23);
defaultValue:int(0);
description:"Choose Blendmode (0=normal, 1=add, 2=average, ...)";
>;
input image4 layer1;
input image4 layer2;
output pixel4 result;
void evaluatePixel()
{
pixel4 a = sampleNearest(layer1, outCoord());
pixel4 b = sampleNearest(layer2, outCoord());
pixel4 temp = b;
// "astro" would require the results to be defined in single variables:
pixel4 result1 = a+b;
// additive
if (blendmode==1) temp = result1;
// average
if (blendmode==2) temp = (a+b)/2.0;
// burn
if (blendmode==3) temp = 1.0 - (1.0-a)/b;
// burn soft
if (blendmode==4) temp = 1.0 - (1.0-b)/a;
// burn inverse
if (blendmode==5) temp = 1.0 - (1.0-b)/a;
// darken
if (blendmode==6) temp = min(a, b);
// dodge
if (blendmode==7) temp = a/(1.0-b);
// difference
if (blendmode==8) temp.rgb = abs(a.rgb - b.rgb).rgb;
// difference exclusion
if (blendmode==9) temp.rgb = a.rgb + b.rgb - 2.0*a.rgb*b.rgb;
// dodge inverse
if (blendmode==10) temp = a/(1.0-b);
// difference negation
if (blendmode==11) temp.rgb = 1.0 - abs(a.rgb - b.rgb);
// stamp
if (blendmode==12) temp = a + 2.0*b - 1.0;
// subtractive
if (blendmode==13) temp = a+b-1.0;
// lighten
if (blendmode==14) temp = max(a, b);
// multiply
if (blendmode==15) temp = a*b;
// screen
if (blendmode==16) temp = 1.0 - (1.0-a) * (1.0-b);
// RGB Red
if (blendmode==17) temp.gb = a.gb;
// RGB Green
if (blendmode==18) temp.rb = a.rb;
// RGB Blue
if (blendmode==19) temp.rg = a.rg;
// Overlay (Should actually be componentwise, but seems to work pretty ok using luminance as well):
if (blendmode==20) {
if((a.r + a.g + a.b)/3.0 < 0.5 ){
temp.rgb = float3(2.0,2.0,2.0)*a.rgb*b.rgb;
}else{
temp.rgb = float3(1.0,1.0,1.0) - float3(2.0,2.0,2.0) * (float3(1.0,1.0,1.0) - a.rgb) * (float3(1.0,1.0,1.0) - b.rgb).rgb;
}
}
// Soft Light
if (blendmode==21){
if(b.r < 0.5){
temp.r = (2.0 * a.r * b.r) + (a.r * 2.0)*(1.0 - 2.0 * b.r);
}else{
temp.r = sqrt(a.r) * (2.0 * b.r - 1.0) + (2.0 * a.r) * (1.0 - b.r);
}
if(b.g < 0.5){
temp.g = (2.0 * a.g * b.g) + (a.g * 2.0)*(1.0 - 2.0 * b.g);
}else{
temp.g = sqrt(a.g) * (2.0 * b.g - 1.0) + (2.0 * a.g) * (1.0 - b.g);
}
if(b.b < 0.5){
temp.b = (2.0 * a.b * b.b) + (a.b * 2.0)*(1.0 - 2.0 * b.b);
}else{
temp.b = sqrt(a.b) * (2.0 * b.b - 1.0) + (2.0 * a.b) * (1.0 - b.b);
}
}
// Hard Light
if (blendmode==22){
if(b.r < 0.5){
temp.r = 2.0*(a.r*b.r);
}else{
temp.r = 1.0 - 2.0 * (1.0 - a.r) * (1.0 - b.r);
}
if(b.g < 0.5){
temp.g = 2.0*(a.g*b.g);
}else{
temp.g = 1.0 - 2.0 * (1.0 - a.g) * (1.0 - b.g);
}
if(b.b < 0.5){
temp.b = 2.0*(a.b*b.b);
}else{
temp.b = 1.0 - 2.0 * (1.0 - a.b) * (1.0 - b.b);
}
}
// Dodge Soft
if (blendmode==23) {
if(a.r+b.r < 1.0){
temp.r = 0.5*a.r/(1.0 -b.r);
}else{
temp.r = 1.0 - 0.5*(1.0 - b.r)/a.r;
}
if(a.g+b.g < 1.0 ){
temp.g = 0.5*a.g/(1.0 -b.g);
}else{
temp.g = 1.0 - 0.5*(1.0 - b.g)/a.g;
}
if(a.b+b.b < 1.0 ){
temp.b = 0.5*a.b/(1.0 -b.b);
}else{
temp.b = 1.0 - 0.5*(1.0 - b.b)/a.b;
}
}
result = temp; }
}
