Użycie modułu cieniującego jako trybu mieszania

Flash Player 10 i nowsze wersje, Adobe AIR 1.5 i nowsze wersje

Korzystanie z modułu cieniującego w trybie mieszania przypomina korzystanie z innych trybów mieszania. Moduł cieniujący definiuje wygląd będący rezultatem widocznego mieszania dwóch obiektów wyświetlanych. W celu użycia modułu cieniującego jako trybu mieszania należy przypisać obiekt Shader do właściwości blendShader obiektu ekranowego znajdującego się na pierwszym planie. Przypisanie wartości innej niż null do właściwości blendShader powoduje automatyczne ustawienie właściwości blendMode obiektu ekranowego na BlendMode.SHADER . Poniższy fragment kodu prezentuje użycie modułu cieniującego jako trybu mieszania. W niniejszym przykładzie założono, że istnieje obiekt ekranowy o nazwie foreground , który jest zawarty w tym samym obiekcie nadrzędnym na liście wyświetlania co inna zawartość ekranowa, przy czym obiekt foreground jest nałożony na inną zawartość.

foreground.blendShader = myShader;

Jeśli moduł cieniujący jest używany jako tryb mieszania, wówczas moduł musi zostać zdefiniowany z co najmniej dwoma obiektami wejściowymi. Zgodnie z tym, co prezentuje przykład, obiekty wejściowe nie są ustawiane w kodzie. Zamiast tego dwa mieszane obrazy są automatycznie używane jako dane wejściowe modułu cieniującego. Obraz na pierwszym tle jest ustawiony jako drugi obraz. (Jest to obiekt wyświetlany, do którego zastosowany jest tryb mieszania). Obraz w tle jest tworzony poprzez wyświetlenie wszystkich pikseli za obwiednią obrazu na pierwszym tle. Obraz w tle jest ustawiony jako pierwszy obraz wejściowy. Jeśli używany jest moduł cieniujący, który oczekuje na więcej niż dwa obiekty wejściowe, należy udostępnić wartość dla każdego obiektu wejściowego następującego po dwóch pierwszych.

Poniższy przykład prezentuje użycie modułu cieniującego jako trybu mieszania. W tym przykładzie używany jest tryb mieszania z rozjaśnianiem oparty na jasności. Rezultat mieszania jest taki, że piksel najjaśniejszy z każdego obiektu mieszanego staje się wyświetlanym pikselem.

Uwaga: Autorem kodu tego przykładu jest Mario Klingemann. Dziękujemy Mario za udostępnienie tego przykładu. Prace Mario i jego artykuły są dostępne na stronie www.quasimondo.com .

Istotny kod ActionScript znajduje się w dwóch metodach:

  • init() : Metoda init() jest wywoływana podczas wczytywania aplikacji. W tej metodzie kod wczytuje plik kodu bajtowego modułu cieniującego.

  • onLoadComplete() : W metodzie onLoadComplete() kod tworzy obiekt Shader o nazwie shader . Następnie rysuje trzy obiekty. Pierwszy, backdrop , to ciemnoszare tło za mieszanymi obiektami. Drugi, backgroundShape , to zielona elipsa gradientowa. Trzeci, foregroundShape , jest pomarańczową elipsą gradientową.

    Elipsa foregroundShape jest w mieszaniu obiektem pierwszego planu. Obraz tła mieszania jest formowany przez część backdrop oraz część obiektu backgroundShape , na które nałożona jest obwiednia obiektu foregroundShape . Obiekt foregroundShape znajduje się najbardziej z przodu spośród obiektów z tej listy wyświetlania. Jest częściowo nałożony na obiekt backgroundShape i całkowicie nałożony na obiekt backdrop . Z powodu tego nakładania — przed zastosowaniem trybu mieszania — pomarańczowa elipsa ( foregroundShape ) jest widoczna w całości, a część zielonej elipsy ( backgroundShape ) jest ukryta pod pomarańczową.

    Jednak po zastosowaniu trybu mieszania jaśniejsza część zielonej elipsy staje się widoczna, ponieważ jest jaśniejsza niż część obiektu foregroundShape , który ją zasłania.

Oto kod tego przykładu w języku ActionScript. Ta aplikacja może być używana jako główna klasa aplikacji dla projektu zawierającego tylko kod ActionScript w programie Flash Builder lub jako klasa document dla pliku FLA w programie 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; 
        } 
    } 
}

Poniżej przedstawiono kod źródłowy dla jądra modułu cieniującego LumaLighten, który jest używany do utworzenia pliku kodu bajtowego „LumaLighten.pbj” modułu 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; 
    } 
}

Więcej informacji na temat korzystania z trybów mieszania zawiera sekcja Stosowanie trybów mieszania .

Uwaga: Gdy moduł cieniujący Pixel Bender działa w trybie mieszania w środowisku Flash Player lub AIR, działanie funkcji próbkowania i outCoord() jest inne niż w pozostałych kontekstach. W trybie mieszania funkcja próbkowania zawsze zwróci piksel analizowany w danej chwili przez moduł cieniujący. Nie można, na przykład, dodać przesunięcia do wartości outCoord() w celu spróbkowania sąsiedniego piksela. Podobnie użycie funkcji outCoord() poza funkcją próbkowania powoduje zawsze zwrócenie współrzędnych 0. Nie można, na przykład, wpływać na łączenie obrazów w trybie mieszania, zmieniając położenie piksela.