Verwenden eines Shaders als Mischmodus

Flash Player 10 und höher, Adobe AIR 1.5 und höher

Die Verwendung eines Shaders als Mischmodus ist nicht anders als die Verwendung anderer Mischmodi. Der Shader definiert das Erscheinungsbild, das durch das visuelle Mischen zweier Anzeigeobjekte entsteht. Um einen Shader als Mischmodus zu verwenden, weisen Sie Ihr Shader-Objekt der blendShader -Eigenschaft des Vordergrundanzeigeobjekts zu. Die Zuweisung eines anderen Werts als null zur blendShader -Eigenschaft setzt die blendMode -Eigenschaft des Anzeigeobjekts automatisch auf BlendMode.SHADER . Im folgenden Beispiel wird die Verwendung eines Shaders als Mischmodus verdeutlicht. Beachten Sie, dass in diesem Beispiel davon ausgegangen wird, dass ein Anzeigeobjekt mit dem Namen foreground im gleichen übergeordneten Objekt auf der Anzeigeliste wie andere Anzeigeinhalte enthalten ist, wobei foreground andere Inhalte überlappt.

foreground.blendShader = myShader;

Wenn Sie einen Shader als Mischmodus verwenden, muss der Shader mit mindestens zwei Eingaben definiert werden. Wie im Beispiel dargestellt, setzen Sie die Eingabewerte nicht in Ihrem Code. Stattdessen werden die beiden gemischten Bilder automatisch als Shader-Eingaben verwendet. Das Vordergrundbild wurde als zweites Bild gesetzt. (Dies ist das Anzeigeobjekt, auf das der Mischmodus angewendet wird.) Ein Hintergrundbild wird durch die Zusammenfügung aller Pixel hinter dem Begrenzungsrahmen des Vordergrundbilds erzeugt. Dieses Hintergrundbild wird als erstes Eingabebild gesetzt. Wenn Sie einen Shader verwenden, der mehr als zwei Eingaben erwartet, geben Sie einen Wert für die Eingaben an, die über die ersten beiden hinausgehen.

Im folgenden Beispiel wird die Verwendung eines Shaders als Mischmodus verdeutlicht. In diesem Beispiel wird ein aufhellender Mischmodus basierend auf Luminanz verwendet. Im Ergebnis der Mischung wird der hellste Pixelwert der miteinander gemischten Objekte angezeigt.

Hinweis: Der Code für dieses Beispiel wurde von Mario Klingemann geschrieben. Vielen Dank an Mario für die Bereitstellung dieses Beispiels. Sie können Marios Arbeiten und Texte unter www.quasimondo.com/ einsehen.

Der wichtige ActionScript-Code befindet sich in diesen beiden Methoden:

  • init() : Die init() -Methode wird beim Laden der Anwendung aufgerufen. In dieser Methode lädt der Code die Shader-Bytecodedatei.

  • onLoadComplete() : In der onLoadComplete() -Methode erstellt der Code das Shader-Objekt mit dem Namen shader . Der Code zeichnet dann drei Objekte: Das erste, backdrop , ist ein dunkelgrauer Hintergrund hinter den eingemischten Objekten. Das zweite, backgroundShape , ist eine grün verlaufende Ellipse. Das dritte Objekt, foregroundShape , ist eine in Orange verlaufende Ellipse.

    Die foregroundShape -Ellipse ist das Vordergrundobjekt der Mischung. Das Hintergrundbild der Mischung wird durch den Teil von backdrop und backgroundShape erzeugt, der durch den Begrenzungsrahmen des foregroundShape -Objekts überlappt wird. Das foregroundShape -Objekt ist das erste Objekt in der Anzeigeliste. Es überlappt das backgroundShape -Objekt teilweise und das backdrop -Objekt vollständig. Aufgrund dieser Überlappung würde die orangefarbene Ellipse ( foregroundShape ) ohne Mischmodus vollständig angezeigt und die grüne Ellipse ( backgroundShape ) würde teilweise von ihr überdeckt:

    Mit aktiviertem Mischmodus scheint der hellere Teil der grünen Ellipse jedoch durch, da er heller ist als der Teil des foregroundShape -Objekts, das sie überlappt:

Im Folgenden wird der ActionScript-Code für dieses Beispiel angezeigt. Verwenden Sie diese Klasse als Hauptanwendungsklasse für ausschließlich in ActionScript erstellte Projekte in Flash Builder oder als Dokumentklasse für die FLA-Datei in Flash Professional:

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

Im Folgenden ist der Quellcode für den Kernel des LumaLighten-Shaders dargestellt, der zum Erstellen der Pixel Bender-Bytecodedatei „LumaLighten.pbj“ verwendet wurde:

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

Weitere Informationen zur Verwendung von Mischmodi finden Sie unter Anwenden von Mischmodi .

Hinweis: Wenn ein Pixel Bender-Shaderprogramm im Mischmodus in Flash Player oder AIR ausgeführt wird, verhalten sich die Sampling- und die outCoord() -Funktionen anders als in jedem anderen Kontext. Im Mischmodus gibt die Sampling-Funktion immer das aktuelle Pixel zurück, das vom Shader evaluiert wird. Beispielsweise können Sie kein Offset in Bezug auf outCoord() verwenden, um das Sampling eines angrenzenden Pixels durchzuführen. Genauso werden bei Verwendung der outCoord() -Funktion außerhalb einer Sampling-Funktion die Koordinaten immer mit 0 ausgewertet. Es ist beispielsweise nicht möglich, mit der Position eines Pixels zu beeinflussen, wie die gemischten Bilder kombiniert werden.