Aug 12, 2008

Blending Modes in WPF using ShaderEffect's

Posted by rravuri

With the RTM of .NET 3.5 SP1 , we can now create hardware accelerated layer blending effects in WPF like those available in Image Editing tools & Photoshop & GIMP

some of the common blending modes are

Darken, Darker Colors preferred.
darken

sampler2D input : register(s0);
sampler2D tex1 : register(s1);

float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 clr1;
clr1= tex2D(tex1, uv.xy);

float4 Color;
Color= tex2D( input , uv.xy);

if (Color.r>clr1.r) Color.r=clr1.r;
if (Color.g>clr1.g) Color.g=clr1.g;
if (Color.b>clr1.b) Color.b=clr1.b;

return Color;
}

Lighten, Lighter Colors preferred.
Lighten

sampler2D input : register(s0);
sampler2D tex1 : register(s1);


float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 clr1;
clr1= tex2D(tex1, uv.xy);

float4 Color;
Color= tex2D( input , uv.xy);

if (Color.r<clr1.r) Color.r=clr1.r;
if (Color.g<clr1.g) Color.g=clr1.g;
if (Color.b<clr1.b) Color.b=clr1.b;

return Color;
}

Difference, Simple Arithmetic difference on color components.
Difference

sampler2D input : register(s0);
sampler2D tex1 : register(s1);

float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 clr1;
clr1= tex2D(tex1, uv.xy);

float4 Color;
Color= tex2D( input , uv.xy);

Color.r=clr1.r - Color.r;
Color.g=clr1.g - Color.g;
Color.b=clr1.b - Color.b;

return Color;
}

Multiply, Simple Arithmetic Multiplication on color components.
Multiply

sampler2D input : register(s0);
sampler2D tex1 : register(s1);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 clr1;
clr1= tex2D(tex1, uv.xy);

float4 Color;
Color= tex2D( input , uv.xy);

Color.r=clr1.r * Color.r;
Color.g=clr1.g * Color.g;
Color.b=clr1.b * Color.b;

return Color;
}

NegationDifference, opposite or negative of difference
NegationDifference

sampler2D input : register(s0);
sampler2D tex1 : register(s1);

float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 clr1;
clr1= tex2D(tex1, uv.xy);

float4 Color;
Color= tex2D( input , uv.xy);

Color.r=1-(1-clr1.r - Color.r);
Color.g=1-(1-clr1.g - Color.g);
Color.b=1-(1-clr1.b - Color.b);

return Color;
}

Overlay Hardlight, Combination of Multiply for darer colors and NegationDifference for Lighter colors.
overlayHard

sampler2D input : register(s0);
sampler2D tex1 : register(s1);

float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 clr1;
clr1= tex2D(tex1, uv.xy);

float4 Color;
Color= tex2D( input , uv.xy);
if (Color.r<0.5)
Color.r=clr1.r * Color.r;
else
Color.r=1-((1-Color.r)*(1-clr1.r));

if (Color.g<0.5)
Color.g=clr1.g * Color.g;
else
Color.g=1-((1-Color.g)*(1-clr1.g));

if (Color.b<0.5)
Color.b=clr1.b * Color.b;
else
Color.b=1-((1-Color.b)*(1-clr1.b));

return Color;
}

Overlay SoftLight, Variation on Overlay for Lighter colors.
overlaysoft

sampler2D input : register(s0);
sampler2D tex1 : register(s1);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float c=0;
float4 clr1;
clr1= tex2D(tex1, uv.xy);

float4 Color;
Color= tex2D( input , uv.xy);
c=clr1.r * Color.r;
Color.r=c+Color.r*(1-((1-Color.r)*(1-clr1.r)-c));

c=clr1.g * Color.g;
Color.g=c+Color.g*(1-((1-Color.g)*(1-clr1.g)-c));

c=clr1.b * Color.b;
Color.b=c+Color.b*(1-((1-Color.b)*(1-clr1.b)-c));

return Color;
}

Exclusion
Exclusion

sampler2D input : register(s0);
sampler2D tex1 : register(s1);

float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 clr1;
clr1= tex2D(tex1, uv.xy);

float4 Color;
Color= tex2D( input , uv.xy);

Color.r+=clr1.r-clr1.r * Color.r;
Color.g+=clr1.g-clr1.g * Color.g;
Color.b+=clr1.b-clr1.b * Color.b;

return Color;
}



Download ShaderPad and play with these effects..


kick it on DotNetKicks.com

2 comments:

Jon Paul Davies said...

Looks very good indeed. Are these available to Silverlight 2 as well? I can't find it documented anywhere.

rravuri said...

Jon,
Unfortunately Silverlight 2 still doesnt support ShaderEffect', I read on the web that Flash & Java Fx (applets) will support it, so we may see it in the next version.