Rick Barraza

Silverlight UX Development

20090813 Thursday August 13, 2009

Fluid Dynamics in Silverlight



It's been crazy busy here at Cynergy so I haven't written much in a while. But after a few months of Microsoft Surface work and a side detour into Flash territory, I finally had some free time to jump back into Silverlight 3 and I’m loving the new WriteableBitmap object.

My plan is to create a series of tutorials concerning more advanced rendering techniques in Silverlight 3. However, I wanted to start today with sharing a Silverlight port of a project I’ve been building on the Surface, a real time fluid dynamics effect based off of Jos Stam's paper and the amazing work of Mehmet Akten in OpenFrameworks. I'm a big fan of his and you can find reference links to his original implementation at the end of the article.

Dynamic Visuals Versus Byte Arrays and Why It Matters

Usually, code for interactive experiences generally involves dynamically attaching a User Control or a Visual to the screen in an animation loop of some kind ( for example, see my previous tutorial Sketching in C#).

However, with Silverlight 3 and Windows 7 providing a multi-touch experience, the amount of dynamic elements on the stage based on multiple inputs can quickly get out of hand. This problem is made even more obvious with the massive multi-user opportunity that Microsoft Surface provides with over 50 simultaneous user inputs! Now coding a single cursor particle emitter is rather straight forward (See Project Rosetta Tutorial). Both Flash and Silverlight allow thousands of elements animating across the screen right out of the box. However, try having 50 fingers on a Surface all shooting out hundreds of particles per second each, and you’ll quickly bring the best machines to a crawl. Even with the limited number of multiple contact points that current touch screens allow, this will also become a very quick issue for Silverlight interactive animations as well. It might be a good time to look into what all this WriteableBitmap stuff is about.

The fluid simulation you see above takes an entirely different approach. Instead of creating, attaching, animating and deleting independent User Controls dozens of times a second, all the visual logic is calculated in memory in a byte array and the only the final calculation is rendered into a WriteableBitmap, which we then display on screen. Long story short, it is significantly faster for computers to do some array math and shoot out a single picture than for us to force the program to literally juggle thousands and thousands of Visuals at a time, with all the unnecessary overhead this would require.

“So Anyways, Let’s Get Down to the Nitty Gritty”

I’m not going to cover the basics of WriteableBitmaps since I think there are already amazing resources on Silverlight 3 and WriteableBitmaps online. For example, check out Rene Schulte and his fantastic series of posts at www.kodierer.blogspot.com. I would also strongly recommend you check out Pete Brown’s experiments with Byte Streams and other awesomeness here. Both of these guys always share amazing stuff and push me to do more.

However, there is a rendering technique that I’m using in the Fluid Dynamics demo above that I would like to share and haven't seen it talked about too much in Silverlight 3. If you click on the stage and enter Vector Lines mode, you’ll see what I’m talking about. The elusive fade to black. While I can’t share the full Fluid Dynamics code externally yet, I will walk you through a much more direct example that highlights this particular render technique.

On dynamic elements, this one is a no brainer. You simply drop the opacity of your dynamic UIElements until they’re transparent and then delete or respawn them to conserve memory. However, applying a fade to black on a dynamically generated image in Silverlight is not nearly as straight forward.

Too up the ante some, I’ll also show you how to do the much cooler “blur and fade” technique, since you end up getting both with just a little more work. Hey, I have to give you at least something cool, right? So here’s how it goes.

The MainPage.XAML is pretty straightforward:



Notice that the IMAGE object named imgStamp is pointing to a 30x30 pixel image of a star I created in Photoshop. I’m going to use this as my stamp (or brush). However, I can hide this particular IMAGE instance that is in XAML by collapsing its visibility and it won't effect anything. Also, its pretty important to note that the image that will be bound to my WriteableBitmap in code, imgOut, has a BlurEffect on it. The WriteableBitmap we generate will basically be constantly taking a photo of itself, so the blur will continue to grow if we don't fade it back down.

The actual code isn't too long, but there are some tricky things going on here. I’ll discuss them in the comments inline:



And here is what this simple snippet of code get's you:





Again, this is just a fast and easier demo of one of the new render techniques that are now available with WriteableBitmap and Silverlight 3. But there are a lot of things we can do to make this much, much better. How about not using an image brush at all but drawing lines directly into the byte array? What about expanding this to support multi-touch? What if want to control the blur or fade to transparent? And what exactly is a vector field, anyway? These are some of the issues we'll be presenting next.

Rick Barraza
twitter.com/rickbarraza
August 14, 2009


Appendix: Tackle it Yourself

I'm not going to lie to you, wrapping your head around the fluid dynamics solution isn't going to be the easiest thing you've done. You may be able to port a straightforward solution to C# quickly enough, but I learned so much by jumping into it and really working out the guts of the process, I strongly suggest anyone interested in this type of thing spend a weekend and do it for themselves. Here is what I used and where I suggest you get started if you're up for it:

"Real Time Fluid Dynamics for Games" by Jos Stam
The paper that seems to have started it all that Jos Stam presented in 2003 at the Game Developers Conference. You can find the PDF here.

However, I wouldn't have even heard of this if I hadn't been blown away by this great video that Mehmet Akten posted of his Fluid Dynamics implementation and render techniques in Open Frameworks.

Open Frameworks, by the way, is a whole post in itself! However, if you've been playing in C# and WPF but want to really see what the Microsoft stack can do with C++ and OpenGL, you can drink from the fire hose here: www.openframeworks.cc.

Finally, coming from a Flash background, I found Eugene's ActionScript 3 Port of Memo's Open Frameworks code a great help. You can find his AS3 rewrite here.

Hope those links help. They definitely got me where I wanted to be and have been a fountain of great ideas the past couple weeks. As I mentioned above, I'll be spending the next couple posts discussing what I learned on the actual rendering side of things, so stay tuned. Have fun!

Posted by rickbarraza | Aug 13 2009, 07:03:12 PM PST
XML