Let’s give some love to Silverlight and in particular Silverlight 5’s 3DApi, which happens to be XNA.
I want to draw something cool on this XNA DrawingSurface BUT then also replicate it in DirectX. I’ve honestly never done a DirectX/C++ project so this will be very risky and a completely new experience for me….
This post will concentrate on the Silverlight 5 part, and the next post will be the DirectX part.
The IDEA
I want to experiment mixing UIElement’s that sit in the visual tree and sprites that sit in the XNA “DrawingSurface” . Below is a very simplified pic of how the UI will be layered…
- XAML UIElements sitting in the top layer (Retained Mode UIElements)
- As the user moves the mouse around the screen I will draw a nice ‘UserControl’ that gives us the x,y position of the mouse in a visual way.
- This UserControl will also have a “Dot” to represent the exact mouse location
- “DrawingSurface” Sprites (Immediate Mode Sprites)
- A bunch of purple sprites will follow the mouse around the screen
- When the user clicks someone on the screen a bunch of green sprites will burst at that location
- The circles fade over time
- The circles move with random velocities, in random directions from the mouse-point
The Top Layer
What we want is a special shape that follows the cursor around as you move the mouse. And this shape needs to hold the x,y position of the mouse. Also this is all rendered in the XAML’s visual tree.
Blend ships with some awesome shapes, one of those is exactly what we need
I cannot begin to tell you how useful the shapes are in Blend, and I really hope that a lot of these blend libraries are available in WinRT-XAML apps in beta.
Silverlight and Blend are mature, WinRT isn’t and that is my main concern with WinRT. I really hope we don’t need to wait 3 more years for WinRT to reach the maturity of Silverlight 5 and Blend 4
Basically I am going to use this “Rectangular Callout”, add it to the visual tree then move it around as the cursor moves. I’m also going to add a small dot to signify the center of the mouse-point.
To animate these 2 controls (Ellipse, Callout) I am going to use a storyboard, which has some great easing rules built into it which will allow me to give it a nice eased motion.
The code that actually wires up the MouseMove and triggers the storyboard is self-contained in a class I called “CalloutCursor.cs” . I won’t go into the details of how that works, just know that it executes the storyboard, plugging in values where the mouse currently is. It also has the calculations to make sure the pointy bit of the callout is in the correct orientation.
So this is what the TOP layer looks like when all the above pieces are running … Pretty simple, and that’s the beauty of Silverlight & Blend, it’s so easy to do stuff like this (once you know your way around that is) ..
The Bottom Layer
This is where it get’s interesting … We are going to use the XNA bits in Silverlight 5 to draw a burst of circles where the current mouse position is.
First step is to place the XNA surface in the XAML where we will render our sprites.
Notice that we wired up the “Draw” event of the DrawingSurface. This triggers 60 times a second and it’s during these events that we draw the sprites on the surface.
For those that haven’t written much XNA code before there is this concept of a “scene”, we wrap the XNA animation inside of this scene. I have created a scene class that wraps all the logic of rendering the sprites when the mouse moves..
The actual SceneBurst class is here : Scene.Burst.cs
In the scene there is this concept of a sprite, and in my case I created a sprite called “BurstingCircles”, and as the name suggests it wraps up all the logic to draw the sprites on the surface.
I create 2 instances of these “BurstingCircles” sprites, one follows the mouse around and the other appears where the mouse is clicked
And these sprites are actually drawn in the “DRAW” method..
Now the actual “BurstingCircles” sprites code is here if your interested :
Sprite.BurstingCircles.cs
The BurstingCircles sprite is made up of 100 circles that randomly spray in 360 degree directions from a central point. These 100 circles appear one after the other, not all in one go.
Each circle is made up of 2 triangle primitives which is made up of 6 vertexes (each triangle is made up of 3 vertex).
Notice that I use a VertexPositionTexture to represent each vertex, the operative word here is “texture”. We are going to use a texture to draw on each triangle.
The texture that we are going to use is dynamically created. This is pretty cool … Silverlights WriteableBitmap lets us take a snap of a visual element and create a bitmap out of it, it is this bitmap that we are going to use as the texture
The texture I dynamically create is based on an ellipse and i create it with a dynamically defined colour. You can do some damn interesting things when we mix the power of Silverlight’’s mature framework and the XNA immediate mode graphics pipeline.
The draw routine is pretty straight forward, generate the 100 circles over time and re-calculate the velocity information during each cycle. This is pretty standard when dealing with pipeline graphics rendering … It’s really low level, to the metal … love it
I should briefly mention that we use simple (not complex) pixel & vertex shader’s. There’s nothing special about them, their purpose is to get pixels onto the surface and draw non-complex vertexes of the triangles.. No morphing of complex pixel effects for us yet !!!
So this is what the bottom layer looks like, it’s pretty simple once you get the hang of how the XNA pipeline works and how to draw in this pipeline..
The Install Experience
The 3DAPI (XNA) bits require GPU and Elevated Trust. So getting the user to give you these permissions is tricky.
I’ve gone with some simple graphics and I won’t go into how I did this as it’s pretty common knowledge how to wire up these setup/install screens, if you really want to see code just download the sample
This is what the user sees to ask for their permission to run the GPU demo and to install the app as an “out of browser” app. I chose to make this OOB because it’s easier to give this elevated trust than keep it in browser and getting the user to go into the dialogs and give manual permission to the Graphics card.
These are the Silverlight standard dialogs explaining that we want “elevated trust” for our app …
This is what the APP looks like in browser once it is installed ..
This is what the APP looks like when it is running Out Of Browser, having been manually installed by the user.
The Result
Here is what it looks like when everything is pulled together
Or try out the demo, you need Silverlight 5 to run it
The Silverlight 5 XNA Api’s are damn awesome, the CPU hit on this is less than 5% and memory footprint is small. My mind is exploding with ideas around 3D animations to compliment Visual Tree UI elements.
I really hope that every developer out there that has invested time to learn Silverlight/WPF and/or XAML, takes the time to learn XNA and/or graphics pipeline immediate mode programming. It seriously opens up your mind in a whole new direction
The next step is to reproduce this in DirectX-WinRT .. off to do just that … stay tuned!!!