A Surface application I’ve been working on has just gone live to the public in Manhattan, NY. You can check it out at Bloomingdale’s in the Clinique area.
All the real products you see in the photo can be used interactively. For example you can place a tube of moisturizer on the table and have it sent to your Facebook wall or e-mail.
Everything “feels” great to use – the gestures, discoverability, and design I all like personally. Although the last statement may sound self-serving it’s really to the credit of the designers and Clinique product team. By the end the process they really “got it” and have enabled a special experience.
I’ve found that creating water effects that respond interactively and smoothly is not really something easy to do in WPF or Silverlight.However because a project required it I trudged forward managed to get it working pretty nicely – buttery smooth and low CPU utilization.
The results can be seen in the video, but the reasons it wasn’t easy may be interesting to WPF/Silverlight developers so I’ll mention why below. Can you guess what the technical obstacles are?
(user interaction 17 seconds in)
(user interaction 17 seconds in)
Graphics architecture
The first hurdle is that WPF and Silverlight primarily use a “display list” or “retained mode” graphics architecture.This is usually not a bad thing, and allowed developers to break away from the WM_PAINT model which is used in WinForms and Win32 before that.Those older systems encourage an “immediate mode” architecture while WPF and Silverlight encourage a retained mode, but will tolerate immediate mode in certain cases.
WPF and Silverlight
You might have nightmares about WinForms and Win32 and wish all manner of death upon them.Death to immediate mode as well – long live WPF/Silverlight and retained mode graphics!
Just one small problem – immediate mode graphics are well suited to certain things like games and simulations, and no one wants give those up.In fact Direct3d itself is an immediate mode architecture which underlies most graphics in Windows 7 including WPF itself.I’m speaking in general here and there are always exceptions.For example I’ve written simple games and simulations in WPF, but many times it is not an ideal approach.
Animation vs. Simulation
To get more specific on why WPF/Silverlight are not great at simulating water, it’s basically about loops.Many simulations for water and other phenomena run a programming loop over and over again throughout the simulation.The reason is that future states of the simulation depend on the output of previous states of the simulation.The problem is that animations are different than simulations.
In WPF you can easily animate a ball along a flat line. WPF determines the position of the ball using a function with time as the input:
Time elapsed 1 second - Move ball to 25% along the line
Time elapsed 2 second - Move ball to 50% along the line
Time elapsed 3 second - Move ball to 75% along the line
You could also choose any random time and the ball would be placed properly because the new position does not depend on the previous position.It’s always just a function taking any time as an input, and spitting out a position as output.
Most animation systems work in a similar way, which is why regardless of what applications artists and animators choose it usually has a big timeline along the bottom.
So if that's how animation works, how is simulation different?
In simulation of water our function to calculate the new position takes not only time as an input but also the previous position of the water. This feedback loop is the key difference.
Since WPF does not encourage loops that let you feedback the output into the next input, we are kind of stuck.
What about CompositionTarget?
One ray of hope is the CompositionTarget. This is a WPF component specifically designed to enable controlling your own rendering loop.I consider CompositionTarget going a bit off the reservation because it’s not really a mainstream technique used by most apps, however it’s fairly clean and that’s ok if it can get us past the loop barrier. While this lets us have precise control over the rendering loop, it still does not allow any way for output of the shaders to feed back into the loop.
We could just not use shaders and write the code procedurally, but then the question becomes how much performance do shaders afford our simulation?
How fast are shaders in WPF?
VERY fast. In fact to get nice performance and realistic water, custom shaders are essentially required. It's an order(s) of magnitude difference. Using shaders should be no problem because WPF supports shader model 3.0.In fact in a previous blog post I showed a single drop water effect using WPF shaders and the code is simple XAML with no problems.But again, that was an animation not a simulation.The drops could not affect each other and you could not drag your finger through the water and create a wave as in the video above.
To get some real coolness we need a simulation, which means using the output from the shader as the input for the next time the shader is run.The problem is when you capture the output of shaders as data in WPF (rather than just display the output), you lose hardware acceleration and performance goes to heck in a handbasket. One item on my wishlist for WPF 5.0 would definitely be enabling a form of shader trees where the output can be modified and looped back as input.
To keep pixel shaders running in hardware in this fashion within a WPF app requires Direct3d, which in turn requires D3DImage.D3DImage is the class that can allow separate Direct3d C++ code to output into an image brush within a WPF app.It also allows (requires really) the Direct3d code to have it’s own rendering loop, which allows us to feed shader output back to the input for the simulation.
With Silverlight its worse because of the lack of GPU acceleration and because the Direct3d integration is not an option.I’ve seen a few liquid/particle simulations in Silverlight but they are quite slow, and tend to peg CPU utilization.
So the bottom line is to create interactive effects like this in WPF really requires CompositionTarget, custom shaders, and a separate Direct3d helper DLL.The first two techniques alone will do the same thing at about a quarter of the speed.
Every year I hope to never code in C++ again, but it looks like that time is not here quite yet.
This video shows a water drop effect implemented using WPF animations and a custom shader. It's written using .NET 4.0 in which support for shader model 3.0 was added. You could probably do the same thing in .NET 3.5, but it's a pain having shader instructions limited to 128 or whatever the limit was. It could pretty easily run in Silverlight 3 or later with the usual WPF->Silverlight mods.
There are two parts to achieving this effect, the shader and the animation. The shader is the canonical ripple effect and is common enough I won't post it here.
However I've posted animation below - it may be helpful because you have to tweak things a bit to get a more organic look.
The objects are bouncing off one another using a simple physics model I added based on the Farseer engine.
Note one of the objects is a working analog clock which continues to run while the water drop falls on it. One final trivia: The coin is a $3 gold piece that was in circulation sometime around the late 19th century. It's worth a bit more than $3 now ;).
This is the shader animation, just throw it in a resource dictionary and fire off a trigger on mouse or other event:
This post provides a DirectX 10 sample app that simply displays a square with a photo on it. (a quad with a texture map).
It uses C# and the SlimDX which is an excellent and lightweight way to use Direct X from .NET.
Although there is already a SlimDX sample to display a colored triangle, this sample demonstrates a few additional points:
How to apply a texture (no it's not obvious at all!)
How to use a quad instead of a triangle (again not obvious)
Data is initialized using collections. This allows the geometry count to be defined in 0 places instead of 4 (it's implied by the collection count) which is less error prone when making data changes.
Collections also make the code more readable because all data types such as Points can be declared as isolated groups rather than all types mixed together in one big array.
I encourage anyone new to DirectX to learn version 10 because it's the foundation for both Vista and Windows 7, and significantly different than version 9 which you might be able to avoid altogether and save a lot of time.
Also a strong recommendation to use SlimDX and to not use C++ for DirectX if you have a choice. Even if you know C++ well it's just a huge drop in efficiency compared to a more modern language and environment like C#. In most cases the performance difference is very small.
.80 - Initial release .82 - Added event log IP scanner to auto extract IPs from event log .84 - More robust checking for duplicates and properly formed data Keep latest copy of downloaded feed data in txt file for easy inspection Allow for comments by skipping IPFeed data lines starting with # Misc small fixes
I've written a small app that allows IIS sites to block Chinese and Korean web sites with just a couple clicks. It's called IISIP and is found here.
Unfortunately up to 80% of spam and server attacks come servers outside the US. Even though ASP.Net blocks a most attempts, it still clutters up your event logs with tons of junk that makes it harder to see real site errors.
I know of no other free way to do this so easily which is why I wrote the app. If you try to do this yourself you run into the following problems:
A lot of sample code is out there to program IIS, but hardly any of it is built into a ready to run tool. Using these bits of sample code is a pain and requires integration time and often fixing someone else's glitches. IISIP is ready to run, 32-bit and 64-bit Windows.
Even if you have a tool to bulk block IPs, it takes time to build your own block list. What's needed is integration of known block list INTO the app so everything you need is in one place. Thankfully sites like okean.com are maintaining such lists, and I've integrated them into the app.
A final requirement to make this process easy is the ability to support dynamic and local "IP feeds". For example rather than hardcoding the lists into the app, the latest versions are automatically downloaded. You can also add other feeds by dropping an .xml file into the IPFeeds folder. So if you have your own lists built ISSIP can use them.
I'd appreciate any feedback - The app works well for me but it is new so if you want to be super safe you can backup your metabase first.
Updates: 7/7/2008 Version 0.88
Enhanced IPFeed parsing to handle ranges of IPs, many were being missed
Added Link to IP Geographic Locator
Added more detail to status while work is being done