Tuesday, 6 March 2012

Shader from string

I wanted to write a bit more about Flash shaders, but was constrained by being unable to show my workings: I can post screenshots and could even host a working demonstration but I could not upload a shader to Wonderfl (images can be uploaded but not other data). Nor could I easily load one from elsewhere because of Flash's security model: I would need to load it from a server where I could edit the Crossdomain.xml file.

But a search of Wonderfl and a further web search turned up the solution: the data can be embedded in the source as a Base64 string.

The Wonderfl example I based the shader code on is here, and is much more impressive than my simple hack. The Base64 encoder I used is here, although I'm sure there are other solutions. In detail:

First I took the shader, Desaturate.pbj, created in Pixel Bender Toolkit and exported for Flash, and uploaded it to the Base64 encoder. This generated a string of Base64 data. As this is just ASCII it can be embedded in Flash as a long String (if too long it could be broken into shorter strings for easier editing, and re-assembled when needed using String +).

The code to make a shader looks like this, where strShader is the string (see the test app for it). The Base64Decoder is from mx.utils

var shader:Shader, filter:FilterShader, dec:Base64Decoder;
dec = new Base64Decoder;

filter = new ShaderFilter(shader = new Shader(dec.drain()));

This generates a ShaderFilter which can be added as any other filter. The code to do this is as follows, together with the line that passes a parameter to it to set the degree of desaturation. Even though there's only one parameter it needs to be passed as an Array. The parameter fAmplitude is from the shader.

private function SetShader(fAmt:Number):void {
    shader.data.fAmplitude.value = [fAmt];
    filters = [filter];

The above is called every time the filter changes: as before the filter has to be re-added each time the parameter is changed.

The filter is a simple desaturation filter, with the desaturation going from 0 (no effect) to 1 (greyscale) based on the number passed to the function. It does this based on the bounces in the ballistics demo I forked to do this.

As far as I can see this is not restricited to Wonderfl: there's no reason why this couldn't be used to embed shaders in Flash apps built with Flash CS. The app uses the Flex Base64 decoder but a third party Base64 library is here.

The test app is embedded below. It's very primitive, and was only used so I'd have something with some colour and with events I could use to trigger the shader.

No comments:

Post a comment