某些着色器定义了参数值,着色器在创建其结果时会使用这些参数值。例如,更改图像亮度的着色器可能会指定一个亮度参数,该参数确定操作影响亮度的程度。根据着色器中的参数定义,着色器中定义的单个参数可能需要单个值或多个值。在 ActionScript 中,在着色器中定义的每个参数都由一个 ShaderParameter 对象表示。如
识别着色器输入和参数
中所述,ShaderParameter 对象是 Shader 对象的 data 属性中的 ShaderData 实例的属性。例如,假定着色器定义一个名为
brightness
的参数,并且该着色器由一个名为
myShader
的 Shader 对象表示。在这种情况下,可使用下面的标识符访问对应于
brightness
参数的 ShaderParameter:
myShader.data.brightness
若要为该参数设置一个(或多个)值,请创建包含这个值(或这些值)的 ActionScript 数组,并将该数组分配给 ShaderParameter 对象的
value
属性。
value
属性定义为 Array 实例,是因为单个着色器参数可能需要多个值。即使着色器参数只需要一个值,也必须将该值包含在 Array 对象中才能将它分配给
ShaderParameter.value
属性。下面的代码演示如何将单个值设置为
value
属性:
myShader.data.brightness.value = [75];
如果着色器的 Pixel Bender 源代码为参数定义默认值,则在创建 Shader 对象时,会创建包含默认值的数组,并将其分配给 ShaderParameter 对象的
value
属性。将数组分配给
value
属性之后(包括该数组是默认数组的情况),可以通过更改数组元素的值来更改参数值。您不需要创建新数组并将它分配给
value
属性。
下面的示例演示如何在 ActionScript 中设置着色器的参数值。在此示例中,着色器定义一个名为
color
的参数。在 Pixel Bender 源代码中,
color
参数声明为
float4
变量,这意味着该参数是包含四个浮点数的数组。在该示例中,
color
参数值会连续更改,该参数每次更改时,都会使用着色器在屏幕上绘制一个有色的矩形。产生的结果是具有动画效果的颜色更改。
这段 ActionScript 代码以下面三个方法为中心:
-
init()
:在
init()
方法中,代码加载包含着色器的 Pixel Bender 字节代码文件。加载文件后,调用
onLoadComplete()
方法。
-
onLoadComplete()
:在
onLoadComplete()
方法中,代码创建名为
shader
的 Shader 对象。同时还创建名为
texture
的 Sprite 实例。在
renderShader()
方法中,代码将着色器结果逐帧绘制在
texture
中。
-
onEnterFrame()
:
onEnterFrame()
方法按每帧一次的频率进行调用,用于创建动画效果。在此方法中,代码将着色器参数值设置为新颜色,然后调用
renderShader()
方法将着色器结果绘制为矩形。
-
renderShader()
:在
renderShader()
方法中,代码调用
Graphics.beginShaderFill()
方法来指定着色器填充。然后,绘制一个矩形,该矩形的填充由着色器输出(生成的颜色)定义。有关以此方法使用着色器的详细信息,请参阅
使用着色器作为绘制填充
。
下面是此示例的 ActionScript 代码。使用此类作为 Flash Builder 中纯 ActionScript 项目的主应用程序类,或者作为 Flash Professional 中 FLA 文件的文档类:
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();
}
}
}
下面是 ColorFilter 着色器内核的源代码,用于创建“ColorFilter.pbj”Pixel Bender 字节代码文件:
<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;
}
}
如果所使用的着色器的参数没有文档说明,则通过检查 ShaderParameter 对象的
type
属性,便可确定数组中必须包含的元素数量及其类型。
type
属性指示着色器本身定义的参数数据类型。有关每种参数类型需要的元素数量和类型的列表,请参阅“ActionScript 3.0 参考”中的
ShaderParameter.value
属性列表。
每个 ShaderParameter 对象还有一个
index
属性,该属性指示参数在着色器参数顺序中的位置。除了这些属性之外,ShaderParameter 对象还可以具有包含由着色器创作者提供的元数据值的其他属性。例如,创作者可以指定元数据值,如参数的最小值、最大值和默认值。创作者所指定的所有元数据值都会作为动态属性添加到 ShaderParameter 对象中。若要检查这些属性,请使用
for..in
循环来循环访问 ShaderParameter 对象的动态属性,以识别其元数据。下面的示例演示如何使用
for..in
循环来识别 ShaderParameter 对象的元数据。每个元数据值都会添加到一个名为
metadata
的 Vector 实例。请注意,此示例假定已创建了一个名为
myShader
的 Shader 实例,并且该实例具有一个名为
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