虽然Pixel Bender主要是用来处理图形任务,但他还有一个强大的用法-处理普通数据(generic number crunching)。Pixel Bender核心和ActionScript在不同的进程中运行,你可以利用这个特点来避免界面的假死(无响应)。提高复杂运算的速度。例如,我们在处理一个很大规模的数据集合,需要对每个数据进行复杂的数学计算(3D,声音引擎等等)。你可以使用Pixel Bender kernal来处理这些数据,最后再将处理好的数据交给AS代码,效果好的甚至会超过优化的很好的AS代码。
下面是个非常简单的例子,Pixel Bender kernel接受一个数组,然后返回一个包含源数组的平方根的新数组。
CODE:
-
<languageVersion : 1.0;>
-
-
kernel NumberCruncher
-
<
-
namespace : "AIF";
-
vendor : "Ryan Taylor";
-
version : 1;
-
description : "Basic example of a generic number cruncher.";
-
>
-
{
-
input image1 src;
-
output pixel3 result;
-
-
void evaluatePixel()
-
{
-
pixel1 value = pixel1(sqrt(sample(src, outCoord())));
-
result = pixel3(value, 0.0, 0.0);
-
}
-
}
首先,注意结果是通过一个三元的pixel值返回回来的。当输出值低于三元的时候,目前版本的Pixel Bender工具,会抛出一个错误,并且拒绝生成字节码。Pixel Bender细则中描述是支持pixel1,pixel2,pixel3,pixel4输出的,所以这可能是一个Pixel Bender工具的bug。为了解决这个问题,我将后两个元素设置为0。
同样,输入的类型必须为image1。
在AS段,需要如下处理:
1.创建一个ByteArray对象,使用writeFloat方法来天津每个数据,确保endian设置为little endian。细则中虽说Vector.<Number>类型可以作为shader的输入数据,但是在使用这种方法的时候同样也出现了bug。
2.创建一个Shader实例来接受Pixel Bender的字节码。宽度根据你的数据数组的长度来获取。在ByteArray中,你需要将数组长度除以4。高度你只需要设置为1。input必须为一个集合。
3.创建一个ByteArray来储存shader计算的结果。同样确保endian为little endian。
4.创建一个ShaderJob实例类接受shader,设置好输入,高度,宽度几个参数,添加一个"complete"的监听,等Shader计算结束后,来处理输出的ByteArray。然后你可以使用start方法来执行shader。
这是as的代码示例:
-
package
-
{
-
import flash.display.Shader;
-
import flash.display.ShaderJob;
-
import flash.display.Sprite;
-
import flash.events.Event;
-
import flash.utils.ByteArray;
-
import flash.utils.Endian;
-
-
public class Main extends Sprite
-
{
-
protected var _shader:Shader;
-
-
protected var _shaderJob:ShaderJob;
-
-
protected var _input:ByteArray;
-
-
protected var _output:ByteArray;
-
-
[Embed(source="/../assets/filters/NumberCruncher.pbj", mimeType="application/octet-stream")]
-
protected var NumberCruncher:Class;
-
-
public function Main()
-
{
-
init();
-
}
-
-
protected function init():void
-
{
-
_input = new ByteArray();
-
_input.endian = Endian.LITTLE_ENDIAN;
-
_input.writeFloat(4);
-
_input.writeFloat(16);
-
_input.writeFloat(100);
-
_input.writeFloat(400);
-
_input.position = 0;
-
-
var width:int = _input.length >> 2;
-
var height:int = 1;
-
-
_shader = new Shader(new NumberCruncher());
-
_shader.data.src.width = width;
-
_shader.data.src.height = height;
-
_shader.data.src.input = _input;
-
-
_output = new ByteArray();
-
_output.endian = Endian.LITTLE_ENDIAN;
-
-
_shaderJob = new ShaderJob(_shader, _output, width, height);
-
_shaderJob.addEventListener(Event.COMPLETE, onShaderJobComplete, false, 0, true);
-
_shaderJob.start();
-
}
-
-
protected function onShaderJobComplete(event:Event):void
-
{
-
_output.position = 0;
-
-
var length:int = _output.length;
-
-
for(var i:int = 0; i < length; i += 4)
-
{
-
var output:Number = _output.readFloat();
-
-
if(i % 3 == 0)
-
trace("value -> " + output);
-
}
-
}
-
}
-
}
为了解决我早先提到的三通道输出的问题,我使用了取模的运算,在“onShaderJobComplete”方法中,最终结果是所有输入数字的平方根。
所以那是很好的。可以想象,等这些bug都消除以后,这江是个非常有用的东西。