使用著色器做為混合模式

Flash Player 10 以及更新的版本,Adobe AIR 1.5 以及更新的版本

使用著色器做為混合模式就像使用其它混合模式一樣。著色器會定義兩個顯示物件混合在一起所產生的視覺外觀。若要使用著色器做為混合模式,請將 Shader 物件指定給前景顯示物件的 blendShader 屬性。將 null 以外的值指定給 blendShader 屬性時,會自動將顯示物件的 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 橢圓是混合的前景物件,混合的背景影像則是由 foregroundShape 物件的範圍框所重疊之部分 backdrop 和部分 backgroundShape 所組成。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。例如,您無法使用像素的位置來影響混合影像的結合方式。