There's something fascinating in looking at the way water in a pool refracts and creates patches of light.
I needed to recreate this effect (called caustic effect) in Flash. The idea was pretty simple, just use a caustic map. At first I thought about generating it on the fly but I seriously doubt this can be done in Flash in real-time (maybe in AS3 but I'm not too sure, and I needed it in AS2 anyway). After a little searching, I found a free little program called - what do you know - Caustics Generator.
Update 28 June 2006: The link I've provided is down, so here's another one.
With it I made a 16-frames animation of the caustics; to keep the file size small, the frames were rendered at half-resolution and upsampled with Actionscript.
A small screenshot of the result can be seen below:
The code is straightforward:
Follow up:
ActionScript:
import flash.filters.DisplacementMapFilter; | |
import flash.display.BitmapData; | |
import flash.geom.Point; | |
import flash.geom.Matrix; | |
| |
var frameCount:Number; | |
var caustic:BitmapData; | |
var causticResized:BitmapData; | |
| |
// create container for the background movie/image and attach it from the library | |
var backgroundContainer:MovieClip = this.createEmptyMovieClip("backgroundContainer", 1); | |
backgroundContainer.attachMovie("bkg", "bkg", 1); | |
| |
// create container for the additive layer | |
var additiveContainer:MovieClip = this.createEmptyMovieClip("backgroundContainer", 2); | |
| |
// synchronize the aeffect with the movie frame rate | |
function onEnterFrame() | |
{ | |
if (frameCount==null) frameCount = 1; | |
// always dispose bitmaps when no longer needed, otherwise memory usage will jump through the roof! | |
if (causticResized !=null) causticResized.dispose(); | |
| |
//load the needed caustic effect bitmap frame | |
caustic = BitmapData.loadBitmap(String(frameCount)); | |
// resize it - we use store it in half-resolution to conserve file size | |
causticResized = new BitmapData(760,420); | |
var transformMatrix:Matrix = new Matrix(); | |
transformMatrix.scale(2, 2); | |
causticResized.draw(caustic, transformMatrix, null, null, null, true); | |
caustic.dispose(); | |
| |
// apply caustic displacement to the background clip | |
var displacementMap:DisplacementMapFilter = new DisplacementMapFilter(causticResized, new Point(0, 0), 1, 1, 50, 50, "ignore", 1); | |
backgroundContainer.filters = [displacementMap]; | |
| |
// copy the caustic bitmap in the additive layer | |
additiveContainer.attachBitmap(causticResized, 1); | |
additiveContainer.blendMode = "add"; | |
| |
frameCount++; | |
if (frameCount>16) frameCount = 1; | |
} |
You can also download the full caustics example.