In my last post I showed a quick summary of a graphic-intensive dashboard that I helped out with. I also mentioned that there are a lot of posts out there dogging SL and WPF rendering performance. But if we get creative with some of the built-in controls SL has to offer we can get some pretty good drawing perf. I wanted to elaborate on some of the techniques I used to eek-out every bit of perf I could. The main concepts I want to discuss are:
- Procedural Animations
- Writeable Bitmaps
- Image Blitting
Out of the box, Silverlight and WPF have Storyboards and Timelines to animate objects on the screen. Storyboards, however, quickly break down once you need to draw more than ~50 items on a screen at once. Storyboards are great for quick animation (slide-in, slide-out, etc.), but for intense data visualizations we’ll have to get a little closer to the metal.
Procedural animations are most commonly found in video games and are used to create complex visual effects. Things like simulating particle systems, physics-based animations, and sprite animations. But that doesn’t mean we can’t spicy up our everyday-software with some of the same concepts.
They way most procedural animations are implemented are with a simple a Setup and Update, Draw loop.
In Silverlight we can setup our animations by hooking in to the CompositionTarget.Rendering event and then call ‘Update’ and ‘Draw’ each time it ticks. If you’ve ever done any game programming for SL or WPF this should look very familiar as it resembles a typical game ticker.
Here is a sample project you can download to wrap your head around how procedural animations in Silverlight.
This is the basic shell for doing pretty much any type of procedural animation and is the base of what we’ll build on to get to the good stuff. Note that just by following this pattern you can easily animate 1,000 objects on the screen…which is a nice improvement from 50.
Writeable Bitmaps for Animation
But why stop at animating a meager 1,000 objects? Lets crank it to 11. There are three key things to know about writeable bitmaps when using them for animation.
- You can snapshot items in the visual tree and render them to a static image
- You can write directly to the byte array (modify image at the pixel level)
- You can render visuals that are NOT in the visual tree to an image
But since this post is about Animation I’m going to gloss over the nitty-gritty of WBs…there are a ton of great resources that already exist on the topic.
The WriteableBitmapEx library is the main thing I want to focus on. Once you wrap your head around the power of the WriteableBitmap you’ll find that this library is totally amazing, and can seriously take your visual effects to another level. This library does some REALLY interesting things that are NOT easy to do with SL and WPF out-of-the-box. :
- Bit Blit – (bit block image transfer)
- Super fast shape generation - the WriteableBitmapEx line drawing approach is more than 20-30 faster than Silverlight’s
- XNA style color tinting – You can apply a color tint to a visual
- Blending Modes – The sample below uses an “overlay” effect
Here is a basic implementation of a writeable bitmap being used as the drawing surface for a procedural animation:
All we’re doing here is setting an Image’s source equal to the WriteableBitmap. Then in the draw loop we clear out the drawing surface, populate our WB with ellipses, and then force a redraw(Invalidate). Pretty simple.
Image Blitting with Writeable Bitmaps
This is where things get interesting. We can use the super fast “blit” extension method to blit an existing image resource into the writeable bitmap. Sound confusing?
Its not…Silverlight is faster at drawing images than it is generating shapes, so we can take the bytes of an existing image and insert them into our writeable bitmap’s byte array. And the handy ‘blit’ extension method takes care of all the dirty work for us.
Putting all this all together you can start pushing the boundaries of what Silverlight can do. Below is a recreation of a popular particle effect using all the techniques I mentioned above. In the example I’m animating 3000 images at ~60fps. Go ahead and download the code and crank it up to 10,000-15,000..its still pretty smooth.
I hope this provides some insight into pushing the limits of silverlight’s rendering pipeline. I look forward to seeing other folks make some interesting visualizations.
Erik Klimczak | firstname.lastname@example.org |twitter.com/eklimcz17 comments , permalink