Calculating Shader Effects in WriteableBitmap (Fast Float Computations And More)

Jan 11, 2010

Here's a small code snippet that allows you to calculate any pixel shader and get the output into a WriteableBitmap!

Stream stream = Application.GetResourceStream(new Uri("SilverlightApplication1;component/Images/test.jpg", UriKind.Relative)).Stream;
WriteableBitmap result = new WriteableBitmap(1, 1); // avoid creating intermediate BitmapImage

Image image = new Image();
image.Effect = new BlurEffect(); // any pixel shader effect
image.Source = result; // set the image to the original
result.Render(image, null);
result.Invalidate(); // render the pixel shader
image.Source = null; // release the bitmap reference
image.Effect = null;
GC.Collect(); // remove all obsolete bitmaps from memory [optional]
// result contains the image with shader effect applied! assign it to any Image.Source!
myImage.Source = result;

For the sample, I used InvertColorEffect() that I had on my PC, but you could try with your own (or just use the BlurEffect() to see how it works).

Note that the image doesn't even have to be part of the UI tree, and you don't have to wait for a render pass!

Why is this good?

In an apples-to-apples comparison (float computations) pixel shaders are much faster than managed code. See for performance comparison. This means that you can now run even faster computations from managed code in Silverlight!

Also in case Silverlight eventually executes shaders on the GPU (I don't know what is the plan about that), your applications will really be able to benefit from the fast computations!

There is also one other reason why is it so good: but I'll mention it in a later post (working on secret project now...) :)



Tips/Tricks: Short Sounds, Fireworks and BitmapCache Speed

Jan 4, 2010

This blog post is a follow-up of the previous one dedicated to the Shock improvements.

I'll just list all tips or other interesting findings/updates in no particular order:

Playing Short Sounds in Silverlight (Improved)

You probably know by now that Silverlight (2,3) has an annoying issue with short sounds - sometimes the sound is not played correctly. The simple workaround is here

If you happen to play too many sounds/sec, the above workaround can cause your memory usage to grow more than you want to for short time. The easiest way to avoid the surge in mem usage is to cache the streams that contain the .mp3 sounds, like this:

private static Dictionary<string, Stream> _streams = new Dictionary<string, Stream>();

public static void PlayShortSound(string embeddedSoundName, double volume)
    Stream stream;
    if (!_streams.TryGetValue(embeddedSoundName, out stream))
        stream = Application.GetResourceStream(new Uri(String.Format("/Shock;component/Sounds/{0}", embeddedSoundName), UriKind.Relative)).Stream;
        _streams[embeddedSoundName] = stream;
    MediaElement media = new MediaElement();
    media.MediaFailed += media_MediaFailed;
    media.MediaEnded += media_MediaEnded;
    media.Volume = volume;
    media.AutoPlay = true;
    media.Position = TimeSpan.FromMilliseconds(0);

Then, just call the function like this example: PlayShortSound("explosion.mp3"). You can use this trick, because multiple sounds using the same stream don't cause issues with each other, which is nice.

"Shatter" Effect

In my previous blog post I mentioned the "shatter" brick effect, which is based on this one:

I changed the effect and made it self-recycling: removes itself from the parent after a given time period. It will also display "fireworks" in an area, not  a dot. All of these are really small modifications, but help make the effect "run and forget", and easy to use for "shattering" stuff like bricks.

Here's an usage sample:

public static TimeSpan ShatterEffectTimeSpan = TimeSpan.FromSeconds(0.3);              

Fireworks fireworks = new Fireworks(TimeSpan.FromSeconds(0.3), (int)width, (int)height, brickAppearance == BrickAppearance.Ice);
Canvas.SetLeft(fireworks, centerX);
Canvas.SetTop(fireworks, centerY);

And here's the source code. Note: get the complete sample from the link above and then change the 2 files below. The code won't compile, but you just have to call your own Random() function, and maybe fix few other basic things.

Fireworks.xaml.cs (4.98 kb)  MagicDot.cs (2.89 kb)

I want to call out something very interesting in the above effect (not made by me originally) - each MagicDot is created within its own container. I believe it will cause less layout work than putting all dots within the same container (this is a gut-feeling unverified speculation)

If you want to see the shatter effect in action, break the ice bricks on level 2 of Shock:

When (Not) To Use BitmapCache, Even For Images That Don't Move

I found out that if I use CacheMode="BitmapCache" for each brick (100+ per level), the performance suffers. This is very interesting, and is something to keep in mind when using bitmap cache.

Seems like the larger the image, the better.

More On Speed

Some blogs (don't remember where) mention that images with Opacity=0 still render and take valuable CPU/GPU time - I tested it and it seems that in Silverlight 4 Beta this is not the case.

I observed no noticeable speed change when a UserControl (the highscore) had Opacity=0 vs Visibility=Invisible. Note, however that Opacity=0 means you get hit testing, so there is some speed difference - don't just blindly overuse Opacity=0 instead of Visibility=Invisible.

  | Terms | Log in


About the author

Happy & enjoying life. Software enthusiast.
The opinions I express here and on are mine and not my employeer's (Microsoft).
This is the official blog of You can find Silverlight samples, coding stuff, and hopefully other interesting things here.