Some shaders
define parameter values that the shader uses in creating its result. For
example, a shader that alters the brightness of an image might specify
a brightness parameter that determines how much the operation affects
the brightness. A single parameter defined in a shader can expect
a single value or multiple values, according to the parameter definition
in the shader. Each parameter that is defined in a shader is represented
in ActionScript by a ShaderParameter object. The ShaderParameter
object is a property of the ShaderData instance in the Shader object’s
data property, as described in
Identifying shader inputs and parameters
. For example, suppose a shader
defines a parameter named
brightness
, and that
shader is represented by a Shader object named
myShader
.
In that case you access the ShaderParameter corresponding to the
brightness
parameter
using the following identifier:
myShader.data.brightness
To
set a value (or values) for the parameter, create an ActionScript
array containing the value or values and assign that array to the
ShaderParameter object’s
value
property. The
value
property
is defined as an Array instance because it’s possible that a single
shader parameter requires multiple values. Even if the shader parameter
only expects a single value, you must wrap the value in an Array
object to assign it to the
ShaderParameter.value
property.
The following listing demonstrates setting a single value as the
value
property:
myShader.data.brightness.value = [75];
If
the Pixel Bender source code for the shader defines a default value
for the parameter, an array containing the default value or values
is created and assigned to the ShaderParameter object’s
value
property
when the Shader object is created. Once an array has been assigned
to the
value
property (including if it’s the default
array) the parameter value can be changed by changing the value
of the array element. You do not need to create a new array and
assign it to the
value
property.
The following example demonstrates setting a shader’s parameter
value in ActionScript. In this example the shader defines a parameter
named
color
. The
color
parameter
is declared as a
float4
variable in the Pixel Bender
source code, which means it is an array of four floating point numbers.
In the example, the
color
parameter value is changed
continuously, and each time it changes the shader is used to draw
a colored rectangle on the screen. The result is an animated color
change.
Note:
The code for this example was written by Ryan Taylor. Thank
you Ryan for sharing this example. You can see Ryan’s portfolio
and read his writing at
www.boostworthy.com/
.
The ActionScript code centers around three methods:
-
init()
: In the
init()
method
the code loads the Pixel Bender bytecode file containing the shader.
When the file loads, the
onLoadComplete()
method
is called.
-
onLoadComplete()
: In the
onLoadComplete()
method
the code creates the Shader object named
shader
.
It also creates a Sprite instance named
texture
.
In the
renderShader()
method, the code draws the shader
result into
texture
once per frame.
-
onEnterFrame()
: The
onEnterFrame()
method
is called once per frame, creating the animation effect. In this
method, the code sets the shader parameter value to the new color,
then calls the
renderShader()
method to draw the
shader result as a rectangle.
-
renderShader()
: In the
renderShader()
method,
the code calls the
Graphics.beginShaderFill()
method
to specify a shader fill. It then draws a rectangle whose fill is
defined by the shader output (the generated color) For more information
on using a shader in this way, see
Using a shader as a drawing fill
.
The following is the ActionScript code for this example. Use
this class as the main application class for an ActionScript-only
project in Flash Builder, or as the document class for the FLA file
in Flash Professional:
package
{
import flash.display.Shader;
import flash.display.Sprite;
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLLoaderDataFormat;
import flash.net.URLRequest;
public class ColorFilterExample extends Sprite
{
private const DELTA_OFFSET:Number = Math.PI * 0.5;
private var loader:URLLoader;
private var shader:Shader;
private var texture:Sprite;
private var delta:Number = 0;
public function ColorFilterExample()
{
init();
}
private function init():void
{
loader = new URLLoader();
loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, onLoadComplete);
loader.load(new URLRequest("ColorFilter.pbj"));
}
private function onLoadComplete(event:Event):void
{
shader = new Shader(loader.data);
texture = new Sprite();
addChild(texture);
addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onEnterFrame(event:Event):void
{
shader.data.color.value[0] = 0.5 + Math.cos(delta - DELTA_OFFSET) * 0.5;
shader.data.color.value[1] = 0.5 + Math.cos(delta) * 0.5;
shader.data.color.value[2] = 0.5 + Math.cos(delta + DELTA_OFFSET) * 0.5;
// The alpha channel value (index 3) is set to 1 by the kernel's default
// value. This value doesn't need to change.
delta += 0.1;
renderShader();
}
private function renderShader():void
{
texture:graphics.clear();
texture.graphics.beginShaderFill(shader);
texture.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
texture.graphics.endFill();
}
}
}
The following is the source code for the ColorFilter shader kernel,
used to create the “ColorFilter.pbj” Pixel Bender bytecode file:
<languageVersion : 1.0;>
kernel ColorFilter
<
namespace : "boostworthy::Example";
vendor : "Ryan Taylor";
version : 1;
description : "Creates an image where every pixel has the specified color value.";
>
{
output pixel4 result;
parameter float4 color
<
minValue:float4(0, 0, 0, 0);
maxValue:float4(1, 1, 1, 1);
defaultValue:float4(0, 0, 0, 1);
>;
void evaluatePixel()
{
result = color;
}
}
If
you’re using a shader whose parameters aren’t documented, you can
figure out how many elements of what type must be included in the
array by checking the ShaderParameter object’s
type
property.
The
type
property indicates the data type of the
parameter as defined in the shader itself. For a list of the number
and type of elements expected by each parameter type, see the
ShaderParameter.value
property
listing in the ActionScript 3.0 Reference.
Each ShaderParameter
object also has an
index
property that indicates
where the parameter fits in the order of the shader’s parameters.
In addition to these properties, a ShaderParameter object can have
additional properties containing metadata values provided by the
shader’s author. For example, the author can specify metadata values
such as minimum, maximum, and default values for a parameter. Any
metadata values that the author specifies are added to the ShaderParameter
object as dynamic properties. To examine those properties, use a
for..in
loop
to loop over the ShaderParameter object’s dynamic properties to
identify its metadata. The following example shows how to use a
for..in
loop
to identify a ShaderParameter object’s metadata. Each metadata value
is added to a Vector instance named
metadata
. Note
that this example assumes a Shader instance named
myShader
is
already created, and that it is known to have a parameter named
brightness
:
var brightness:ShaderParameter = myShader.data.brightness;
var metadata:Vector.<String> = new Vector.<String>();
for (var prop:String in brightness)
{
if (brightness[prop] is String)
{
metadata[metadata.length] = brightness[prop];
}
}
// do something with the metadata