Scripts, Tools & Methods Developed at Hook
So it was one of those mornings, just after the first sweet sip of the morning RedBull, and the boss man pops in to ask a question: “So what do you think about refraction through glass in flash?”. Being the new guy and trying to hide the obvious “deer in the headlights” feeling, I had no choice but to respond “Umm.. that might be possible”. Thus began the quest for real-time “refraction”.
(please note the quotes on refraction, its all lies, I promise.)
Hitting up Google revealed that people were doing a sort of lens effect in flash 8 using the DisplacementMapFilter. With the the fear subsided a bit, the key was in the all mighty displacement bitmap filter.
The concept of displacement has been around as long as pixels, and it works a bit like this:
Flash’s DisplacementMapFilter allows you do to this and control the offsets with the channel data of another image. In other words, all of the really hard stuff is done for you courtesy of Adobe.
This particular illusion has three parts:
The most important part is the displacement map itself. We used the red and green channels to control the horizontal and vertical offsets. Dark red to bright red, would move the pixel left to right, and dark green to light green would move the pixel up and down. Anything with a median color (128) would not be offset. With a bit of noodling, we managed to build a shader that could render out these displacement maps directly from the 3D data.
The alpha image was used to crop out the proper pixels from the “scratch” bitmap data that was a result of applying all of the filters.
The final image is the beauty render of the class with alpha. This is simply overlaid on top of the cropped and filtered pixels
Another helpful bit of misdirection was the mouse cursor. You will notice that the mouse goes behind the glass and is distorted as well. This helped to sell the illusion a bit more. The mouse is simply a sprite that has its pixels drawn onto the “Distortion Layer” every frame.
The original concept called for fairly large (think 720p) stage dimensions, and multiple glass objects. Therefore performance quickly became an issue when trying to run the filters on the whole stage. The biggest performance boost (not surprisingly) came from simply reducing the number of pixels to deal with.
So we calculated a rectangle around each glass/distortion object that would have enough pixels to fill out the displacement but still be few enough to be fast. We copied only those pixels out to a temporary bitmap data object. This allowed us to apply a set of filters to a much smaller number of pixels. Next, we copied the beauty shot pixels on to that temporary bitmap data We then copied the resultant pixels back to the target display object respecting the alpha channel of the AlphaImage from above, this allowed a fairly seamless reintegration with the background layers.
So the final process is as follows:
Wallah, instant awesome.
The moral of the story? CopyPixels is hella fast.
There is one more feature that is supported but not shown in this demo, think animated ice cubes inside of the glass…