Lysis blog

31st March 2012

Filter sprites

Introduction

In the last article I mentioned how reading and writing of the data from and to bitmap form could be a significant bottleneck, and a potential drawback to the filter computation method. It's clearly desirable to minimise the number of accesses needed; here I describe a method I've discovered which can contribute to this goal.

One of the main usage cases for filter-based code is the manipulation of some two-dimensional array data - either for some overall environmental process or object manipulation (which I will consider in more depth in a later article).
Naively, when it comes to rendering this data these are the possibilities which avoid tapping the full state :

All of these are satisfactory under particular circumstances. Good uses of these could be for wind effects, falling sand or to give a detailed closeup of a much larger simulation.

However, would it not be nice to render each datapoint as a bitmap graphic?
Here is an example, using a simple 6-state CA. :

Simple 6-state Cellular Automata with filter sprites
Click on-screen to draw or remove walls, and use the mouse menu to change iteration speed or randomise the display

Method overview

This process relies on the highly adaptable displacementMapFilter function.
This is normally used to apply a distortion effect to a bitmap, for example ripples in water. It uses two channels from a second supplied bitmap to offset the pixel read for each position. Here we use it to select which image to display for the tile.

In overview, the pathway is essentially as follows:

Advert

Filter spritesheets

The displacementMapFilter uses a channel to describe the offset of the read pixel in each direction; a value in the range 0..255 represents an offset of -128..127.
For reasons described in the next section, we can only use half of this range, giving a maximum size for the spritesheet of 128x128 pixels.
The displacementMapFilter only processes the union of the bitmaps supplied, so this needs to be repeated to cover at minimum the size of the display area.

Correction factor bitmap

As the pixel selection is a displacement from the initial position, the range of the source image (the spritesheet) targetted depends on the image coordinate. The offset into the spritesheet has to be the same for each tile position. We can arrange this by adding on an offset dependent on the position.
Fortunately, flash provides the ability to combine pixel values together directly, using alternative blendmodes. Using the 'add' mode, we can add on 128 for the lefmost/topmost tile, then step down by one tile's width/height at a time.
With this strategy we can have a two-dimensional table of up to 128x128 pixels. Again this needs to be repeated to cover the display area when scaled up.

Processing the data

So far we've considered only initialisation - these bitmaps can be generated and stored as constant data. What follows needs to be done per frame.
First we take a copy of the correction-factor bitmap.
Generally, the working data will need to be copied and processed into spritesheet offsets. In some cases the values may simply be scaled up with a colorTransform or colorMatrixFilter operation, but using paletteMap is the most flexible, and can sometimes be had for free - if there are two unused channels in the internal representation of each cell.
Onto this tile data the correction factor bitmap is drawn with a blendmode of 'add', then the result is scaled up so each pixel 'cell' becomes a bitmap 'tile'. The displacementMapFilter then uses the resulting bitmap as its distortion map, and the spritesheet as source bitmap, converting each flat-filled rectangle into an image drawn from the spritesheet.

Overview

This covers the basic method for rendering filter sprites. Obviously there are several very clear restriction on these graphics - the 128 by 128 size addressing limit and grid alignment are the most egregious examples. However, more advanced and specialised techniques can overcome either of these, or any other particularly objectionable limit.

Please note that filter sprites are still only going to be a win under a fairly limited set of conditions. In particular, there needs to be a good reason for redrawing everything - if a large proportion of the images don't change then the rendering effort for them is wasted. On the other hand, though, at least the processing power required is a constant, so there won't be intermittent lag however much activity occurs. Also, the smaller the tiles the better - the cost of reading data out and rendering each individually with copyPixels increases greatly, while the filter sprites method has constant cost. And not only that - there is space for more tiles within the size limit.

Conclusion

Some of the difficulties imposed by filters can be overcome, with some ingenuity.

Graphical overview of the filtersprites method:

The spritesheet offsets are added to the correction-factor, and rescaled to use as a displacement map on a spritesheet to create the final image

Functions covered

Comments

Add a comment (Please read the notes before submitting your first comment)
no registration required
re-use handle & password to retain identity

Advert

Back to Lysis Games main page

Back to Lysis Blog