Uso de um sombreador como modo de mesclagem

Flash Player 10 e posterior, Adobe AIR 1.5 e posterior

O uso de um sombreador como modo de mesclagem é parecido com o uso de outros modos de mesclagem. O sombreador define a aparência resultante da mesclagem visual de dois objetos de exibição. Para usar um sombreador como modo de mesclagem, atribua o objeto Shader à propriedade blendShader do objeto de exibição em primeiro plano. A atribuição de um valor diferente de null à propriedade blendShader automaticamente define a propriedade blendMode do objeto de exibição como BlendMode.SHADER . A listagem a seguir demonstra o uso de um sombreador como modo de mesclagem. Observe que este exemplo pressupõe a existência de um objeto de exibição chamado foreground contido no mesmo pai na lista de exibição que outro conteúdo de exibição, com foreground se sobrepondo ao outro conteúdo:

foreground.blendShader = myShader;

Quando você usa um sombreador como modo de mesclagem, ele deve ser definido com pelo menos duas entradas. Como mostra o exemplo, você não define os valores de entrada no código. Em vez disso, as duas imagens mescladas são usadas automaticamente como entradas do sombreador. A imagem em primeiro plano é definida como a segunda imagem. (Este é o objeto de exibição ao qual o modo de mesclagem é aplicado.) Uma imagem em segundo plano é criada colocando-se a composição de todos os pixels atrás da caixa delimitadora da imagem em primeiro plano. Essa imagem em segundo plano é definida como a primeira imagem de entrada. Se usar um sombreador que espera mais de duas entradas, especifique um valor para qualquer entrada além das duas primeiras.

O exemplo a seguir demonstra o uso de um sombreador como modo de mesclagem. Este exemplo utiliza um modo de mesclagem de clareamento baseado na luminosidade. O resultado da mesclagem é que o valor de pixel mais claro de qualquer um dos objetos mesclados se torna o pixel que é exibido.

Nota: O código deste exemplo foi escrito por Mario Klingemann. Obrigado por compartilhar este exemplo, Mario. Para conhecer mais sobre o trabalho de Mario e ler seus artigos, acesse www.quasimondo.com/ .

O código ActionScript importante está nestes dois métodos:

  • init() : o método init() é chamado quando o aplicativo é carregado. Neste método, o código carrega o arquivo de código de bytes do sombreador.

  • onLoadComplete() : no método onLoadComplete() , o código cria o objeto Shader chamado shader . Em seguida, ele desenha três objetos. O primeiro, backdrop , é um plano de fundo cinza escuro atrás de objetos mesclados. O segundo, backgroundShape , é uma elipse gradiente verde. O terceiro objeto, foregroundShape , é uma elipse gradiente cor de laranja.

    A elipse foregroundShape é o objeto de primeiro plano da mesclagem. A imagem de fundo da mesclagem é formada pela parte de backdrop e pela parte de backgroundShape que são sobrepostas pela caixa delimitadora do objeto foregroundShape . O objeto foregroundShape é o objeto mais à frente na lista de exibição. Ele se sobrepõe parcialmente a backgroundShape e completamente a backdrop . Por causa dessa sobreposição, sem um modo de mesclagem aplicado, a elipse laranja ( foregroundShape ) é exibida por completo e parte da elipse verde ( backgroundShape ) é ocultada por ela:

    No entanto, com o modo de mesclagem aplicado, a parte mais brilhante da elipse verde “transparece” porque é mais clara do que a parte de foregroundShape que se sobrepõe a ela:

Veja abaixo o código ActionScript para este exemplo. Use esta classe com a classe de aplicativo principal em um projeto somente ActionScript no Flash Builder ou como a classe do documento para o arquivo FLA no 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; 
        } 
    } 
}

Este é o código-fonte para o kernel de sombreador LumaLighten, usado para criar o arquivo de código de bytes do Pixel Bender “LumaLighten.pbj”:

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

Para obter mais informações sobre como usar modos de mesclagem, consulte Aplicação de modos de mesclagem .

Nota: Quando um programa Pixel Bender shader é executado como mescla no Flash Player ou no AIR, as funções de amostragem e outCoord() comportam-se de forma diferente de outros contextos. Em uma mescla, a função de amostragem sempre retornará o pixel atual avaliado pelo shader. Por exemplo, não é possível adicionar um deslocamento em outCoord() para criar uma amostra do pixel vizinho. Da mesma forma, se você utilizar a função outCoord() fora de uma função de amostragem, as coordenadas serão avaliadas em 0. Não é possível, por exemplo, utilizar a posição de um pixel para influenciar como as imagens mescladas serão combinadas.