`

学习一下 Pixel Bender

阅读更多

Adobe Pixel Bender 是一种编程语言,用于创建或操作图像内容。您可以使用 Pixel Bender 创建一个内核(在本文档中亦称之为着色器)。着色器定义了一个可对图像的每个像素单独执行的单一函数。对该函数的每次调用都将得到图像中该像素坐标处的输 出颜色。可通过指定输入图像和参数值来自定义该操作。在着色器的单次执行中,输入值和参数值是不变的。唯一发生变化的是像素(其颜色是函数调用的结果)的 坐标。

对多个输出像素坐标调用着色器函数时,将尽可能采用并行方式。这样会改进着色器性能,提供高性能的处理能力。

在 Flash Player 和 Adobe AIR 中,使用着色器可轻松创建三种类型的效果:

  • 绘制填充

  • 混合模式

  • 滤镜

着色器也可以按独立模式执行。使用独立模式时,将直接访问着色器的结果,而非预先指定着色器的用途。结果可以按图像数据或者二进制或数值数据的形式 访问。该数据完全不必是图像数据。这样一来,您可以为着色器输入一组数据。着色器将处理该数据,然后您可以访问着色器返回的结果数据。

 

以下是您可能会在 ActionScript 中使用滤镜完成的任务:

  • 将着色器加载到正在运行的 SWF 应用程序中,或者在编译时嵌入着色器并在运行时访问它。

  • 访问着色器元数据

  • 为着色器标识并指定输入值(通常为图像)

  • 为着色器标识并指定参数值

  • 着色器有以下几种使用方法:

    • 用于绘制填充

    • 用于混合模式

    • 用作滤镜

    • 按独立模式使用

  • 内核:对于 Pixel Bender 而言,内核指的就是着色器。通过 Pixel Bender,您的代码定义了一个内核,它定义了可对图像的每个像素单独执行的单一函数。

  • Pixel Bender 字节代码:编译 Pixel Bender 内核时,会将其转换为 Pixel Bender 字节代码。Flash Player 或 Adobe AIR 在运行时访问并执行字节代码。

  • Pixel Bender 语言:用于创建 Pixel Bender 内核的编程语言。

  • Pixel Bender 工具包:用于依据 Pixel Bender 源代码创建 Pixel Bender 字节代码文件的应用程序。您可以使用该工具包编写、测试和编译 Pixel Bender 源代码。

  • 着色器:在本文档中,着色器是指采用 Pixel Bender 语言编写的一组功能。着色器的代码会创建视觉效果或执行计算。在任一情况下,着色器都返回一组数据(通常为图像的像素)。着色器对每个数据点执行相同的操作,唯一的区别在于输出像素的坐标不同。

    着色器不是用 ActionScript 编写的。它用 Pixel Bender 语言编写,并编译为 Pixel Bender 字节代码。着色器可在编译时嵌入 SWF 文件,也可在运行时作为外部文件加载。无论采用上述哪一种方式,都要在 ActionScript 中访问着色器,方法是先创建一个 Shader 对象,然后将其链接到着色器字节代码。

  • 着色器输入:一种复杂的输入,通常为位图图像数据,该数据提供给着色器供其计算之用。对于着色器中定义的每个输入变量,着色器的整个执行过程都使用单一变量值(即,一个图像或一组二进制数据)。

  • 着色器参数:提供给着色器供其计算之用的单一值(或限定的值集合)。着色器的每次执行中都会定义各个参数值,该值在着色器的整个执行过程中保持不变。

 

首先去下个Pixel BenerToolkit 。界面如下:

 


 

图2为,代码编辑区:

看一下,Kernel Language 的语法结构:

 

  <languageVersion : 1.0;>
  
  kernel DoNothing   头信息


  <
      namespace: "Adobe::Example";
      vendor: "Adobe examples";
      version: 1;
      description: "A shader that does nothing, but does it well."; 版本信息


  >
  {
      input image4 src; 输入图片源


  
      output pixel4 dst; 输出


      
      parameter float3 color 定义一个float4,输入参数


      <
          description: "......................";
      >;
      
      parameter float alpha
      <
          description: "......................";
      >;
  
      void evaluatePixel() kernel 

的像素计算


      {
          dst = sampleNearest(src, outCoord());
          dst.rgb = color;
          dst.a = alpha;
      }
  }
  

 

在 ActionScript 中使用 Pixel Bender 着色器的第一步是在 ActionScript 代码中访问着色器。因为着色器是用 Adobe Pixel Bender 工具包创建并以 Pixel Bender 语言编写的,所以不能在 ActionScript 中直接访问。您需要创建 Shader 类的一个实例,用于向 ActionScript 表示 Pixel Bender 着色器。通过 Shader 对象可以查明着色器的有关信息,如着色器是否需要参数或输入图像值。将 Shader 对象传递给其它对象即可实际使用着色器。例如,若要将着色器用作滤镜,可将 Shader 对象分配给 ShaderFilter 对象的 shader 属性。若要将着色器用作绘制填充,可将 Shader 对象作为参数传递给 Graphics.beginShaderFill() 方法。

ActionScript 代码可以通过两种方式访问由 Adobe Pixel Bender 工具包创建的着色器(.pbj 文件):

在运行时加载:可以使用 URLLoader 对象将着色器文件作为外部资源进行加载。这种方法类似于加载外部资源(如文本文件)。下面的示例演示如何在运行时加载着色器字节码文件并将其链接到一个 Shader 实例:

 

var loader:URLLoader = new URLLoader(); 
loader.dataFormat = URLLoaderDataFormat.BINARY; 
loader.addEventListener(Event.COMPLETE, onLoadComplete); 
loader.load(new URLRequest("myShader.pbj")); 
 
var shader:Shader; 
 
function onLoadComplete(event:Event):void { 
    // Create a new shader and set the loaded data as its bytecode 
    shader = new Shader(); 
    shader.byteCode = loader.data; 
     
    // You can also pass the bytecode to the Shader() constructor like this: 
    // shader = new Shader(loader.data); 
     
     // do something with the shader 
}
 

   嵌入在 SWF 文件中:使用 [Embed] 元数据标签可以在编译时将着色器文件嵌入在 SWF 文件中。只有在使用 Flex SDK 编译 SWF 文件时,[Embed] 元数据标签才可用。[Embed] 标签的 source 参数指向着色器文件,其 mimeType 参数为"application/octet-stream"

,如此例中所示:

 

[Embed(source="myShader.pbj", mimeType="application/octet-stream")] 
var MyShaderClass:Class; 
 
// ... 
 
// create a shader and set the embedded shader as its bytecode 
var shaderShader = new Shader(); 
shader.byteCode = new MyShaderClass(); 
 
// You can also pass the bytecode to the Shader() constructor like this: 
// var shader:Shader = new Shader(new MyShaderClass()); 
 
// do something with the shader
 

在任何一种情况下,都可以将原始着色器字节码(URLLoader.data 属性或 [Embed] 数据类的实例)链接到 Shader 实例。如以上示例所示,可以通过两种方式将字节码分配给 Shader 实例。可以将着色器字节代码作为参数传递到 Shader() 构造函数。或者,可以将其设置为 Shader 实例的 byteCode 属性。

在创建 Pixel Bender 着色器并将其链接到 Shader 对象后,即可使用着色器以多种方式创建效果。您可以将着色器用作滤镜、混合模式、位图填充,也可以用于位图或其它数据的独立处理。您还可以使用 Shader 对象的 data

属性访问着色器的元数据、指定输入图像以及设置参数值。

 

使用着色器作为绘制填充

在使用着色器创建绘制填充时,您将使用绘图 API 方法来创建矢量形状。正如使用绘图 API 可将任何位图图像用作位图填充一样,着色器的输出将用于填充该形状。若要创建着色器填充,可在代码中开始绘制形状的位置处,调用 Graphics 对象的 beginShaderFill() 方法。将 Shader 对象作为第一个参数传递给 beginShaderFill()

方法,如以下清单所示:

 

var canvas:Sprite = new Sprite(); 
canvas.graphics.beginShaderFill(myShader); 
canvas.graphics.drawRect(10, 10, 150, 150); 
canvas.graphics.endFill(); 
// add canvas
 


 

<languageVersion : 1.0;> 
kernel ThreePointGradient 
< 
    namespace : "Petri Leskinen::Example"; 
    vendor : "Petri Leskinen"; 
    version : 1; 
    description : "Creates a gradient fill using three specified points and colors."; 
> 
{ 
    parameter float2 point1 // coordinates of the first point 
    < 
        minValue:float2(0, 0); 
        maxValue:float2(4000, 4000); 
        defaultValue:float2(0, 0); 
    >; 
     
    parameter float4 color1 // color at the first point, opaque red by default 
    < 
        defaultValue:float4(1.0, 0.0, 0.0, 1.0); 
    >; 
     
    parameter float2 point2 // coordinates of the second point 
    < 
        minValue:float2(0, 0); 
        maxValue:float2(4000, 4000); 
        defaultValue:float2(0, 500); 
    >; 
     
    parameter float4 color2 // color at the second point, opaque green by default 
    < 
        defaultValue:float4(0.0, 1.0, 0.0, 1.0); 
    >; 
     
    parameter float2 point3 // coordinates of the third point 
    < 
        minValue:float2(0, 0); 
        maxValue:float2(4000, 4000); 
        defaultValue:float2(0, 500); 
    >; 
     
    parameter float4 color3 // color at the third point, opaque blue by default 
    < 
        defaultValue:float4(0.0, 0.0, 1.0, 1.0); 
    >; 
     
    output pixel4 dst; 
     
    void evaluatePixel() 
    { 
        float2 d2 = point2 - point1; 
        float2 d3 = point3 - point1; 
         
        // transformation to a new coordinate system 
        // transforms point 1 to origin, point2 to (1, 0), and point3 to (0, 1) 
        float2x2 mtrx = float2x2(d3.y, -d2.y, -d3.x, d2.x) / (d2.x * d3.y - d3.x * d2.y); 
        float2 pNew = mtrx * (outCoord() - point1); 
         
        // repeat the edge colors on the outside 
        pNew.xy = clamp(pNew.xy, 0.0, 1.0); // set the range to 0.0 ... 1.0 
         
        // interpolating the output color or alpha value 
        dst = mix(mix(color1, color2, pNew.x), color3, pNew.y); 
    } 
}
 

 

package 
{ 
    import flash.display.Shader; 
    import flash.display.Sprite; 
    import flash.events.Event; 
    import flash.geom.Point; 
    import flash.net.URLLoader; 
    import flash.net.URLLoaderDataFormat; 
    import flash.net.URLRequest; 
     
    public class ThreePointGradient extends Sprite 
    { 
        private var canvas:Sprite; 
        private var shader:Shader; 
        private var loader:URLLoader; 
         
        private var topMiddle:Point; 
        private var bottomLeft:Point; 
        private var bottomRight:Point; 
         
        private var colorAngle:Number = 0.0; 
        private const d120:Number = 120 / 180 * Math.PI; // 120 degrees in radians 
         
         
        public function ThreePointGradient() 
        { 
            init(); 
        } 
         
        private function init():void 
        { 
            canvas = new Sprite(); 
            addChild(canvas); 
             
            var size:int = 400; 
            topMiddle = new Point(size / 2, 10); 
            bottomLeft = new Point(0, size - 10); 
            bottomRight = new Point(size, size - 10); 
             
            loader = new URLLoader(); 
            loader.dataFormat = URLLoaderDataFormat.BINARY; 
            loader.addEventListener(Event.COMPLETE, onLoadComplete); 
            loader.load(new URLRequest("ThreePointGradient.pbj")); 
        } 
         
        private function onLoadComplete(event:Event):void 
        { 
            shader = new Shader(loader.data); 
             
            shader.data.point1.value = [topMiddle.x, topMiddle,y]; 
            shader.data.point2.value = [bottomLeft.x, bottomLeft.y]; 
            shader.data.point3.value = [bottomRight.x, bottomRight.y]; 
             
            addEventListener.Event.ENTER_FRAME, updateShaderFill); 
        } 
         
        private function updateShaderFill(event:Event):void 
        { 
            colorAngle += .06; 
             
            var c1:Number = 1 / 3 + 2 / 3 * Math.cos(colorAngle); 
            var c2:Number = 1 / 3 + 2 / 3 * Math.cos(colorAngle + d120); 
            var c3:Number = 1 / 3 + 2 / 3 * Math.cos(colorAngle - d120; 
             
            shader.data.color1.value = [c1, c2, c3, 1.0]; 
            shader.data.color2.value = [c3, c1, c2, 1.0]; 
            shader.data.color3.value = [c2, c3, c1, 1.0]; 
             
            canvas.graphics.clear(); 
            canvas.graphics.beginShaderFill(shader); 
             
            canvas.graphics.moveTo(topMiddle.x, topMiddle.y); 
            canvas.graphics.lineTo(bottomLeft.x, bottomLeft.y); 
            canvas.graphics.lineTo(bottomRight.x, bottomLeft.y); 
             
            canvas.graphics.endFill(); 
        } 
    } 
}

 

使用着色器作为混合模式

 

使用着色器作为混和模式与使用其它混和模式类似。着色器定义的外观取决于将两个显示对象混和在一起的视觉效果。若要将着色器用于混和模式,请将 Shader 对象指派给前景显示对象的 blendShader 属性。如果为 blendShader 属性指定非 null 值,显示对象的 blendMode 属性将自动设置为 BlendMode.SHADER 。下面的清单演示如何使用着色器作为混和模式。注意,此示例假定存在名为 foreground 的显示对象。该对象与其它显示内容包含在显示列表的同一父级中,而 foreground

与其它内容重叠:

 

foreground.blendShader = myShader;

 

使用着色器作为混和模式时,着色器必须由至少两个输入定义。如示例所示,您未在代码中设置输入值。而是将两个混和后的图像自动用作着色器的输入。前 景图像设置为第二个图像。(此显示对象便是要对其应用混和模式的对象。)背景图像由前景图像边框后的所有像素组合而成。背景图像设置为第一个输入图像。如 果所用着色器要求两个以上的输入,则还需为前两个之外的其它输入提供值。

下面的示例演示如何使用着色器作为混和模式。此示例使用基于亮度的加亮混和模式。混和的结果是以任一混和对象中最亮的像素值显示该像素。

注: 此示例的代码由 Mario Klingemann 编写。感谢 Mario 分享此示例。若要查看 Mario 的更多作品及阅读他的文章,请访问 www.quasimondo.com/

这段重要的 ActionScript 代码用到下面两个方法:

  • init() :应用程序加载时调用 init() 方法。在此方法中,代码加载着色器字节代码文件。

  • onLoadComplete() :在 onLoadComplete() 方法中,代码创建名为 shader 的 Shader 对象。然后绘制三个对象。第一个对象 backdrop 是混和对象后的深灰色背景。第二个对象 backgroundShape 是绿色渐变椭圆。第三个对象 foregroundShape 是橙色渐变椭圆。

    foregroundShape 椭圆是混和的前景对象。混和的背景图像由部分 backdrop 和部分 backgroundShape 构成,并叠加了 foregroundShape 对象的边框。foregroundShape 对象是位于显示列表最前面的对象。它与 backgroundShape 部分重叠,与 backdrop 全部重叠。由于上述重叠的存在,如果不应用混和模式,橙色椭圆 (foregroundShape ) 将全部显示,并遮盖住绿色椭圆 (backgroundShape ) 的一部分:

 

<languageVersion : 1.0;> 
kernel LumaLighten 
< 
    namespace : "com.quasimondo.blendModes"; 
    vendor : "Quasimondo.com"; 
    version : 1; 
    description : "Luminance based lighten blend mode"; 
> 
{ 
    input image4 background; 
    input image4 foreground; 
 
    output pixel4 dst; 
     
    const float3 LUMA = float3(0.212671, 0.715160, 0.072169); 
 
    void evaluatePixel() 
    { 
        float4 a = sampleNearest(foreground, outCoord()); 
        float4 b = sampleNearest(background, outCoord()); 
        float luma_a = a.r * LUMA.r + a.g * LUMA.g + a.b * LUMA.b; 
        float luma_b = b.r * LUMA.r + b.g * LUMA.g + b.b * LUMA.b; 
         
        dst = luma_a > luma_b ? a : b; 
    } 
}
 
package 
{ 
    import flash.display.BlendMode; 
    import flash.display.GradientType; 
    import flash.display.Graphics; 
    import flash.display.Shader; 
    import flash.display.Shape; 
    import flash.display.Sprite; 
    import flash.events.Event; 
    import flash.geom.Matrix; 
    import flash.net.URLLoader; 
    import flash.net.URLLoaderDataFormat; 
    import flash.net.URLRequest; 
     
    public class LumaLighten extends Sprite 
    { 
        private var shader:Shader; 
        private var loader:URLLoader; 
         
        public function LumaLighten() 
        { 
            init(); 
        } 
         
        private function init():void 
        { 
            loader = new URLLoader(); 
            loader.dataFormat = URLLoaderDataFormat.BINARY; 
            loader.addEventListener(Event.COMPLETE, onLoadComplete); 
            loader.load(new URLRequest("LumaLighten.pbj")); 
        } 
         
         
        private function onLoadComplete(event:Event):void 
        { 
            shader = new Shader(loader.data); 
             
            var backdrop:Shape = new Shape(); 
            var g0:Graphics = backdrop.graphics; 
            g0.beginFill(0x303030); 
            g0.drawRect(0, 0, 400, 200); 
            g0.endFill(); 
            addChild(backdrop); 
             
            var backgroundShape:Shape = new Shape(); 
            var g1:Graphics = backgroundShape.graphics; 
            var c1:Array = [0x336600, 0x80ff00]; 
            var a1:Array = [255, 255]; 
            var r1:Array = [100, 255]; 
            var m1:Matrix = new Matrix(); 
            m1.createGradientBox(300, 200); 
            g1.beginGradientFill(GradientType.LINEAR, c1, a1, r1, m1); 
            g1.drawEllipse(0, 0, 300, 200); 
            g1.endFill(); 
            addChild(backgroundShape); 
             
            var foregroundShape:Shape = new Shape(); 
            var g2:Graphics = foregroundShape.graphics; 
            var c2:Array = [0xff8000, 0x663300]; 
            var a2:Array = [255, 255]; 
            var r2:Array = [100, 255]; 
            var m2:Matrix = new Matrix(); 
            m2.createGradientBox(300, 200); 
            g2.beginGradientFill(GradientType.LINEAR, c2, a2, r2, m2); 
            g2.drawEllipse(100, 0, 300, 200); 
            g2.endFill(); 
            addChild(foregroundShape); 
             
            foregroundShape.blendShader = shader; 
            foregroundShape.blendMode = BlendMode.SHADER; 
        } 
    } 
}
 

 

 

<!----> <!----> <!---->
<!---->

使用着色器作为滤镜

<!----> <!---->
<!---->

使用着色器作为滤镜与在 ActionScript 中使用任何其它滤镜类似。使用着色器作为滤镜时,过滤出的图像(显示对象或 BitmapData 对象)将传递给着色器。着色器使用输入图像来创建滤镜输出,该输出通常为原始图像经过修改的版本。如果过滤出的对象是显示对象,着色器输出将显示在屏幕 上,代替过滤出的显示对象。如果过滤出的对象是 BitmapData 对象,着色器输出将成为 BitmapData 对象的内容,并调用该对象的 applyFilter() 方法。

若要使用着色器作为滤镜,您首先要创建 Shader 对象,如加载或嵌入着色器 中所述。接下来,您需要创建链接到该 Shader 对象的 ShaderFilter 对象。ShaderFilter 对象便是将应用到所过滤对象的滤镜。将滤镜应用于对象的方式与应用任何滤镜的方式相同。将其传递给显示对象的 filters 属性,或者对 BitmapData 对象调用 applyFilter() 方法。例如,下面的代码创建 ShaderFilter 对象,并将此滤镜应用到名为 homeButton 的显示对象。

var myFilter:ShaderFilter = new ShaderFilter(myShader); 
homeButton.filters = [myFilter];

在使用着色器作为滤镜时,着色器必须由至少一个输入定义。如示例所示,您未在代码中设置输入值。而是将过滤出的显示对象或 BitmapData 对象设置为输入图像。如果所用着色器要求一个以上的输入,则还需为第一个之外的其它输入提供值。

在某些情况下,滤镜会改变原始图像的尺寸。例如,典型的投影效果会添加额外的像素,这些像素组成为图像添加的阴影。在使用改变图像尺寸的着色器时,需设置 leftExtensionrightExtensiontopExtensionbottomExtension 属性,指明所需图像尺寸变化量。

下面的示例演示如何使用着色器作为滤镜。此示例中的滤镜将反转图像红绿蓝三色通道的值。其结果为该图像的“负片”版本。

注: 此示例使用的着色器为 Pixel Bender 工具包中附带的 invertRGB.pbk Pixel Bender 内核。您可以从 Pixel Bender 工具包安装目录中加载此内核的源代码。编译源代码,然后将字节代码文件保存到源代码所在的目录。

这段重要的 ActionScript 代码用到下面两个方法:

  • init() :应用程序加载时调用 init() 方法。在此方法中,代码加载着色器字节代码文件。

  • onLoadComplete() :在 onLoadComplete() 方法中,代码创建名为 shader 的 Shader 对象。然后创建并绘制名为 target 的对象的内容。target 对象是填充有线性渐变色的矩形:左边是红色,中间是黄绿色,右边是淡蓝色。未过滤的对象看上去是这样:


    应用了滤镜后,颜色反转,矩形变成这样:


此示例使用的着色器为 Pixel Bender 工具包中附带的“invertRGB.pbk”Pixel Bender 范例内核。源代码位于 Pixel Bender 工具包安装目录的“invertRGB.pbk”文件中。编译源代码,然后以文件名“invertRGB.pbj”将字节代码文件保存在 ActionScript 源代码所在的目录中。

下面是此示例的 ActionScript 代码。使用此类作为 Flex 中仅包含 ActionScript 项目的主应用程序类,或者作为 Flash 创作工具中 FLA 文件的文档类:

package 
{ 
    import flash.display.GradientType; 
    import flash.display.Graphics; 
    import flash.display.Shader; 
    import flash.display.Shape; 
    import flash.display.Sprite; 
    import flash.filters.ShaderFilter; 
    import flash.events.Event; 
    import flash.geom.Matrix; 
    import flash.net.URLLoader; 
    import flash.net.URLLoaderDataFormat; 
    import flash.net.URLRequest; 
     
    public class InvertRGB extends Sprite 
    { 
        private var shader:Shader; 
        private var loader:URLLoader; 
         
        public function InvertRGB() 
        { 
            init(); 
        } 
         
        private function init():void 
        { 
            loader = new URLLoader(); 
            loader.dataFormat = URLLoaderDataFormat.BINARY; 
            loader.addEventListener(Event.COMPLETE, onLoadComplete); 
            loader.load(new URLRequest("invertRGB.pbj")); 
        } 
         
         
        private function onLoadComplete(event:Event):void 
        { 
            shader = new Shader(loader.data); 
             
            var target:Shape = new Shape(); 
            addChild(target); 
             
            var g:Graphics = target.graphics; 
            var c:Array = [0x990000, 0x445500, 0x007799]; 
            var a:Array = [255, 255, 255]; 
            var r:Array = [0, 127, 255]; 
            var m:Matrix = new Matrix(); 
            m.createGradientBox(w, h); 
            g.beginGradientFill(GradientType.LINEAR, c, a, r, m); 
            g.drawRect(10, 10, w, h); 
            g.endFill(); 
             
            var invertFilter:ShaderFilter = new ShaderFilter(shader); 
            target.filters = [invertFilter]; 
        } 
    } 
}

有关应用滤镜的详细信息,请参阅创建和应用滤镜

 
<!---->

使用着色器作为滤镜

使用着色器作为滤镜与在 ActionScript 中使用任何其它滤镜类似。使用着色器作为滤镜时,过滤出的图像(显示对象或 BitmapData 对象)将传递给着色器。着色器使用输入图像来创建滤镜输出,该输出通常为原始图像经过修改的版本。如果过滤出的对象是显示对象,着色器输出将显示在屏幕 上,代替过滤出的显示对象。如果过滤出的对象是 BitmapData 对象,着色器输出将成为 BitmapData 对象的内容,并调用该对象的 applyFilter() 方法。

若要使用着色器作为滤镜,您首先要创建 Shader 对象,如加载或嵌入着色器 中所述。接下来,您需要创建链接到该 Shader 对象的 ShaderFilter 对象。ShaderFilter 对象便是将应用到所过滤对象的滤镜。将滤镜应用于对象的方式与应用任何滤镜的方式相同。将其传递给显示对象的 filters 属性,或者对 BitmapData 对象调用 applyFilter() 方法。例如,下面的代码创建 ShaderFilter 对象,并将此滤镜应用到名为 homeButton 的显示对象。

 

 

var myFilter:ShaderFilter = new ShaderFilter(myShader); 
homeButton.filters = [myFilter];
 

在使用着色器作为滤镜时,着色器必须由至少一个输入定义。如示例所示,您未在代码中设置输入值。而是将过滤出的显示对象或 BitmapData 对象设置为输入图像。如果所用着色器要求一个以上的输入,则还需为第一个之外的其它输入提供值。

在某些情况下,滤镜会改变原始图像的尺寸。例如,典型的投影效果会添加额外的像素,这些像素组成为图像添加的阴影。在使用改变图像尺寸的着色器时,需设置 leftExtensionrightExtensiontopExtensionbottomExtension 属性,指明所需图像尺寸变化量。

下面的示例演示如何使用着色器作为滤镜。此示例中的滤镜将反转图像红绿蓝三色通道的值。其结果为该图像的“负片”版本。

注: 此示例使用的着色器为 Pixel Bender 工具包中附带的 invertRGB.pbk Pixel Bender 内核。您可以从 Pixel Bender 工具包安装目录中加载此内核的源代码。编译源代码,然后将字节代码文件保存到源代码所在的目录。

这段重要的 ActionScript 代码用到下面两个方法:

  • init() :应用程序加载时调用 init() 方法。在此方法中,代码加载着色器字节代码文件。

  • onLoadComplete() :在 onLoadComplete() 方法中,代码创建名为 shader 的 Shader 对象。然后创建并绘制名为 target 的对象的内容。target 对象是填充有线性渐变色的矩形:左边是红色,中间是黄绿色,右边是淡蓝色。未过滤的对象看上去是这样:


应用了滤镜后,颜色反转,矩形变成这样:

 


 

 

在独立模式下使用着色器

 

在独立模式下使用着色器时,着色器处理的运行独立于其输出结果的用途。指定要执行的着色器、设置输入值和参数值,及指定用于放置结果数据的对象。在以下两种情形中,可以考虑以独立模式使用着色器:

  • 处理非图像数据:在独立模式下,您可以选择将任意二进制数据或数值数据(而非位图图像数据)传递给着色器。除位图图像数据外,您还可以选择将着色器结果以二进制数据或数值数据的形式返回。

  • 背景处理:以独立模式运行着色器时,着色器默认为异步运行。这表示,在您的应用程序继续运行的同时,着色器以后台方式运行,并在其处理结束时通知您的代码。您可以使用运行耗时的着色器,它在运行时不会导致应用程序用户界面或其它处理响应迟缓。

使用 ShaderJob 对象以独立模式执行着色器。首先创建 ShaderJob 对象,并将其链接到代表要执行的着色器的 Shader 对象:

 

 

var job:ShaderJob = new ShaderJob(myShader);

 接下来,设置着色器需要的所有输入值或参数值。如果着色器在后台运行,还需要为 ShaderJob 对象的

complete

事件注册一个侦听器。着色器完成其处理时,将调用该侦听器

 

 

function completeHandler(event:ShaderEvent):void 
{ 
    // do something with the shader result 
} 
 
job.addEventListener(ShaderEvent.COMPLETE, completeHandler);
 

接下来,创建着色器操作完成时,向其中写入操作结果的对象。将该对象指派给 ShaderJob 对象的 target

属性:

 

 

var jobResult:BitmapData = new BitmapData(100, 75); 
job.target = jobResult;
 

 

如果使用 ShaderJob 执行图像处理,则为 target 属性指派一个 BitmapData 实例。如果要处理二进制数据或数值数据,则指派 ByteArray 对象或 Vector.<Number> 实例给 target 属性。在该情形下,您必须设置 ShaderJob 对象的 widthheight 属性,以指定输出到 target 对象的数据量。

注: 您可以一步完成 ShaderJob 对象 shadertargetwidthheight 属性的设置,方法是将相应的参数传递给 ShaderJob() 构造函数,如:var job:ShaderJob = new ShaderJob(myShader, myTarget, myWidth, myHeight);

准备好执行着色器时,调用 ShaderJob 对象的 start( ) 方法:

job.start();

默认情况下,调用 start() 导致 ShaderJob 以异步方式执行。在这种情况下,程序立即继续执行下一行代码,而不等待着色器完成处理。着色器操作完成时,ShaderJob 对象调用其 complete 事件的侦听器,通知它们操作已完成。在此(即 complete 事件侦听器代码中),target 对象获得着色器操作结果。

注: 也可以不使用 target 属性对象,直接从传递给侦听器方法的事件对象处取得着色器结果。该事件对象是一个 ShaderEvent 实例。根据设置为 target 属性的对象的数据类型,ShaderEvent 对象有三个可用于访问结果的属性:ShaderEvent.bitmapDataShaderEvent.byteArrayShaderEvent.vector

或者,可以将 true 参数传递给 start() 方法。在该情形下,着色器操作将同步执行。所有代码(包括与用户界面及所有其它事件的交互)在着色器执行时暂停。着色器完成处理后,target 对象包含着色器结果,程序继续执行下一行代码。

job.start(true);

 

 

 

 

  • 大小: 40 KB
  • 大小: 57.1 KB
  • 大小: 53.3 KB
  • 大小: 35.4 KB
  • 大小: 35.4 KB
分享到:
评论
1 楼 yanmie 2014-12-31  
您的文章已被我们收录
地址:http://www.airmyth.com/forum.php?mod=viewthread&tid=42
如果您不想被收录,请告知,谢谢!!!

相关推荐

    基于 Flash 的 Pixel Bender 基础

    通过学习Pixel Bender,我们可以实现各种复杂的视觉特效,包括但不限于图像模糊、锐化、色彩调整、光照效果以及高级的图像处理算法。 Pixel Bender的核心是基于数学的滤镜语言,它可以编写成PBK(Pixel Bender ...

    pixel_bender_basics.zip_adobe flash_pixelbender_roundwps

    总之,“pixel_bender_basics.zip”是一个学习和实践Adobe Pixel Bender技术的好资源,通过研究其中的示例,你可以掌握如何在ActionScript项目中创建、应用和控制自定义的图像处理效果。对于想要提升Flash应用视觉...

    Adobe.Pixel.Bender.Kernel.Filter.Writing.Tutorial.zh-CN

    这只是一个简单的示例,实际上Pixel Bender支持更复杂的图像处理算法和滤镜效果,你可以进一步探索和学习以增强你的图像处理能力。记住,Pixel Bender手册是获取更多内置函数和工具信息的重要资源。

    pixelbender

    3. **技术支持与社区**:尽管PixelBender拥有强大的功能,但对于新手来说可能存在一定的学习曲线。因此,建议加入官方社区获取帮助和支持。 4. **版本兼容性**:随着Adobe软件的更新迭代,PixelBender的某些特性可能...

    AS3技术文档

    你可以管理日历日期和时间,控制时间间隔,并通过示例学习如何创建一个简单的模拟时钟。这涉及到`Date`对象的使用,了解如何设置和获取日期时间,以及如何进行时间间隔的计算。 ### 使用字符串 字符串是AS3中最...

    actionscript专注图片处理的新书

    本书将指导读者如何使用Pixel Bender技术来开发自己的ActionScript着色器,从而实现对图像的高级滤镜效果。通过学习这些技术,开发者可以创建出复杂的混合模式、填充模式以及其他视觉特效,这些都可以应用于位图上,...

    Flex4 SDK 新特性

    - **Pixel Bender集成**:Pixel Bender是一种用于图像处理的技术,Flex 4通过集成Pixel Bender,使得开发者可以直接在Flex应用程序中实现复杂的图像滤镜效果。 - **Spark文本组件**:基于Text Layout Framework的...

    Flex3 Explorer四合一本地版本之Flex2FilterExplorer

    GlowFilter、InnerGlowFilter、InvertFilter、MatrixFilter、MotionBlurFilter、Pixel Bender Filter、ShadowFilter、SparkFilter等。通过这个工具,开发者可以快速理解和掌握每个过滤器的工作原理及其参数的调整...

    flash_cs5_help.pdf

    及其标志、Adobe AIR、Adobe Premiere、ActionScript、After Effects、AIR、Authorware、ColdFusion、Creative Suite、Director、Dreamweaver、...InDesign、Kuler、Pixel Bender、Photoshop、PostScript、Soundbooth 和...

    android air开发文档(英文版)

    - Adobe及其徽标、Adobe AIR、ActionScript、AIR、Flash、Flash Builder、Flash Lite、Flex、MXML和Pixel Bender是Adobe Systems Incorporated在美国和其他国家/地区的注册商标或商标。 #### 六、注意事项 - 本...

Global site tag (gtag.js) - Google Analytics