使用着色器作为混合模式

Flash Player 10 和更高版本,Adobe AIR 1.5 和更高版本

使用着色器作为混合模式与使用其他混合模式类似。着色器定义的外观取决于将两个显示对象混合在一起的视觉效果。若要将着色器用于混合模式,请将 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) 的一部分:

    而在应用混合模式之后,绿色椭圆的较亮部分会“穿透”前景显示出来,因为该部分比遮盖它的那部分 foregroundShape 更亮。

下面是此示例的 ActionScript 代码。使用此类作为 Flash Builder 中纯 ActionScript 项目的主应用程序类,或者作为 Flash Professional 中 FLA 文件的文档类:

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; 
        } 
    } 
}

下面是 LumaLighten 着色器内核的源代码,用于创建“LumaLighten.pbj”Pixel Bender 字节代码文件:

<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; 
    } 
}

有关使用混合模式的详细信息,请参阅应用混合模式

注: 当 Pixel Bender 着色器程序以混合模式在 Flash Player 或 AIR 中运行时,采样和 outCoord() 函数的行为与在其他上下文中不同。在混合模式中,采样函数将始终返回着色器计算的当前像素。例如,您不能为了采集邻近像素而向 outCoord() 中添加偏移。同样,如果您使用 outCoord() 函数而不使用采样函数,则其坐标的计算结果将始终为 0。例如,您无法利用像素的位置来影响混合图像的合并方式。