(X) Hide this
    • Login
    • Join
      • Say No Bots Generate New Image
        By clicking 'Register' you accept the terms of use .

Pixel Effects in Silverlight

(2 votes)
Boyan Mihaylov
>
Boyan Mihaylov
Joined Jul 18, 2008
Articles:   11
Comments:   12
More Articles
8 comments   /   posted on Apr 05, 2009
Categories:   General

This article is compatible with the latest version of Silverlight.


Introduction

Element effects in Silverlight 2 were missing. This means that if you want to make your elements more attractive, you have to write your own effects. Silverlight.FX introduced a great number of effects and animations, which you can use. Nikhil Kothari has written a number of posts to show you the capabilities of this small but powerful framework.

In Silverlight 3 the Silverlight team had thought of implementing such effects. Thus, we had the pixel effects. Of course, you can use previous effect frameworks, but you'd better see the power of the built-in features.

Pixel Effects

Silverlight 3 beta 1 supports only two kinds of effects – the blur effect and the drop shadow effect. I will give you examples how to use these effects. However, the Silverlight team has implemented something that gives you much more power. You can implement your own effects and use them in your application. This process is not very simple, but I will try to explain you everything in details.

First, let’s get into the whole effect system of Silverlight. How is it constructed? Well actually it is done in a way that can be easily extended by adding more and more effects. Every object of type UIElement has a property, called Effect. It is of type Effect. All effects are all “in-place” effects in the sense that they output some modification of the pixel that is at the same location in the input texture as its destination in the output texture. It means that they just manipulate color but not position. How does this work? The way this works is that the Effect class defines a protected virtual method, called EffectMapping. The classes, which derive from the Effect class, have to override this method, which returns a GeneralTransform that takes a position and returns the post-effect corresponding position.

public abstract class Effect : DependencyObject 
  protected Effect(); 
  protected internal virtual GeneralTransform EffectMapping { get; } 
  public static Brush ImplicitInput { get; } 

Blur Effect

This effect is quite common. You may know this from your work with Photoshop or any other graphics software. It is built-in Silverlight, so you can use it very easily. Let’s create a simple application, which will demonstrate the usage of each of the effects. Our application will be called, Beeee (because I use an image with a bee to demonstrate the effect).

When you move the slider, the blur radius changes and the image becomes more and more blurred.

Cool, isn’t it? Let’s see how this is achieved. I will show you both the XAML way and the C# way. You may need to use either the first one or the second one in your projects.

<Image Source="images/bee.jpg" Stretch="Fill" Margin="10" x:Name="BeeImage"
  <Image.Effect> 
    <BlurEffect x:Name="BeeBlurEffect" Radius="1" /> 
  </Image.Effect> 
</Image> 
private void SetEffects() 
  BlurEffect effect = new BlurEffect(); 
  effect.Radius = 10; 
 
  BeeImage.Effect = effect; 

Before using the effects in the code-behind you should include the System.Windows.Media.Effects namespace in your class file.

In this example I am using another great technique introduced in Silverlight 3 beta 1 – element to element binding. It allows you to bind a property of an object to a property of another object. Pretty cool and useful. In this example I have bound the Value property of the slider control to the Radius property of the BlurEffect object.

You can check the online demo.

Drop Shadow Effect

This is another common effect. It allows you to add shadow under your objects. It can help you to make your Silverlight applications more attractive to users. So let’s have a look at the demo application I have created.

You can change the blur radius and the shadow depth to manipulate the shadow. Here it is:

Here is the list of properties you can use to manipulate the shadow of an object.

  • BlurRadius – manages the blur of the shadow
  • ShadowDepth – manages the depth of the shadow, that is the distance between the shadow and the image
  • Color – the color of the shadow
  • Direction - an angle specifying the direction of the shadow
  • Opacity – the opacity of the shadow

Here is the implementation both in the XAML way and the C# way as usual.

<Image Source="images/bee.jpg" Stretch="Fill" Margin="10" x:Name="BeeImage"
  <Image.Effect> 
    <DropShadowEffect x:Name="DropShadowEffect" BlurRadius="15" ShadowDepth="7" Color="DarkBlue" /> 
  </Image.Effect> 
</Image> 

 

private void SetEffects() 
  DropShadowEffect effect = new DropShadowEffect(); 
  effect.BlurRadius = 10; 
  effect.ShadowDepth = 5; 
 
  BeeImage.Effect = effect; 

You can check the online demo.

Implementing Custom Effects

I think this is the most interesting part of the article. Despite Silverlight has only two built-in effects, you can add your own effect. This process is not so simple but for the sake of the good application look, we can go through it.

In Silverlight, Shader Effects (a.k.a. Pixel Shaders) allow you to modify the rendered pixels of any UI Element before they are composited to the current view. They can be used to add effects to screen elements including shadows, blur, grayscale, redeye removal – pretty much anything you can accomplish by tweaking pixels using an algorithm. Normally, pixel shaders are done using the GPU (video card), but currently in Silverlight 3, Pixel Shaders are rendered using a software-based algorithm. This means that Pixel Shaders in Silverlight aren’t nearly as fast as they might be using the GPU.

In order to create a custom effect, you need to follow these steps. First, you need to install the latest version of DirectX SDK. You need the effects compiler (fxc.exe) from this SDK in order to be able to compile custom effects. Now you have to write your own effect using Microsoft's High-Level Shading Language (HLSL). This language is not very simple but it provides a way to manipulate images. Let’s write our first HLSL program and save it as WateryEffect.fx.

sampler2D input : register(S0); 
 
float4 main(float2 uv : TEXCOORD) : COLOR 
  uv.y = uv.y + (sin(uv.y*100)*0.03); 
  return tex2D( input , uv.xy); 

Now, we have to compile this source using the effects compiler. So open the command prompt and enter the following command, which compiles FX files to PS.

fxc /T ps_2_0 /Fo WateryEffect.ps WateryEffect.fx

There is a tool, called Shazzam, which can help you to compile FX files. Here is the list of its features:

  • Contains a HLSL editor.
  • Open existing HLSL file. Save changes to file system if desired.
  • Auto generates derived ShaderEffect class samples (VB and C#) for any valid HLSL snippet.
  • Auto generates input controls to manipulate the shader registers.
  • Contains sample images for instant viewing of shader effect.
  • Supports importing custom user image.
  • Rich color editing of C, C# and VB source.

If you don’t want to download and install any programs, you can check the Chris Hay’s Web Pixel Shader Compiler. It is a Silverlight application which does the compilation for you. You write your HLSL code and get the PS file after the compilation.

Tamir Khason has written a great post about pixel shader effects. You can check it and see how you can manipulate images using HLSL.

The next step is to include the PS file in your Silverlight project. You have to add it to your project in Visual Studio and change its Build Action to Resource. Now you have to create a class which will represent your effect. You have to derive from ShaderEffect class and to provide a default constructor which will initialize the effect.

public class WateryEffect : ShaderEffect 
  public WateryEffect() 
  { 
    PixelShader ps = new PixelShader(); 
    ps.UriSource = new Uri("CustomEffects;component/effects/WateryEffect.ps", UriKind.Relative); 
 
    this.PixelShader = ps; 
  } 

CustomEffects is the name of your assembly. In my project, the file WateryEffect.ps is in a folder, called effects. When you have used Resource as a build action, you have to specify the path to the file in the following way: component/{FILE_PATH_IN_VISUAL_STUDIO}.

Well, we now have our custom effect in Silverlight. Now we can use the same way as the previous effects.

<Image Source="images/bee.jpg" Stretch="Fill" Margin="10" x:Name="BeeImage"
  <Image.Effect> 
    <effects:WateryEffect /> 
  </Image.Effect> 
</Image> 

Do not forget to include your effects namespace in the XAML.

xmlns:effects="clr-namespace:CustomEffects.effects" 

 

private void SetEffects() 
  BeeImage.Effect = new WateryEffect(); 

And here is our custom effect in action:

You can check the online demo.

Conclusion

The fact that Silverlight supports HLSL opens up a whole new world of possibilities for Silverlight developers. In beta 1 all these effects are not well optimized. Normally, pixel shaders are done using the GPU (video card), but currently in Silverlight, Pixel Shaders are rendered using a software-based algorithm. This means that Pixel Shaders in Silverlight aren’t nearly as fast as they might be using the GPU. I am sure this will be changed in the official release. Don't forget that you can apply effect not only to images, but also to every object of type UIElement. This is very powerful because you can achieve a great presentation, which your users will definitely like.

Source Code

You can download the source code of the examples and test it yourself.

References


Subscribe

Comments

  • -_-

    RE: Pixel Effects in Silverlight 3


    posted by Nair on Apr 06, 2009 12:21
    Pretty cool stuff.
  • -_-

    RE: Pixel Effects in Silverlight 3


    posted by Tom on Apr 06, 2009 14:11
    Great article!  I'm curious about one point.  Regarding pixel shaders being rendered in software, you wrote "I am sure this will be changed in the official release."  What is your basis for this statement?
  • boyanmihailov

    RE: Pixel Effects in Silverlight 3


    posted by boyanmihailov on Apr 07, 2009 09:05
    I can't tell surely what will be done in the final release. By saying 'I am sure' I mean 'I hope', because using GPU will increase the performance.
  • -_-

    RE: Pixel Effects in Silverlight 3


    posted by Conker on Jul 21, 2009 20:27

    Getting error in http://sl.dortikum.net/pixeleffects/custom/ , I'm using Silverlight 3.

     

    Webpage error details

    User Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; InfoPath.2; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET CLR 1.1.4322)
    Timestamp: Tue, 21 Jul 2009 17:25:47 UTC

    Message: Unhandled Error in Silverlight Application
    Code: 2106   
    Category: InitializeError      
    Message: Failed to load the application. It was built with an obsolete version of Silverlight    

    Line: 52
    Char: 13
    Code: 0
    URI: http://sl.dortikum.net/pixeleffects/custom/

     

  • boyanmihailov

    RE: Pixel Effects in Silverlight 3


    posted by boyanmihailov on Jul 21, 2009 20:57
    I have updated these examples to work with Silverlight 3. Thanks for reporting that!
  • -_-

    RE: Pixel Effects in Silverlight 3


    posted by abhigt on Aug 10, 2009 14:11
    cant we have shadow effect in all the four sides is it possible?
  • -_-

    RE: Pixel Effects in Silverlight 3


    posted by Neo on Mar 19, 2010 17:04

    Great article. Thank you.

     

  • -_-

    RE: Pixel Effects in Silverlight 3


    posted by Eric Christian on May 08, 2010 18:30
    Thank you for being the only person who actually put C# code on implementation of the Pixel Shader. I've seen so many people put only XAML (which is worthless if you attach objects dynamically.)

Add Comment

Login to comment:
  *      *