Uso de un sombreado como modo de mezcla

Flash Player 10 y posterior, Adobe AIR 1.5 y posterior

La utilización de un sombreado como modo de mezcla es similar al uso de otros modos de mezcla. El sombreado define la apariencia que se obtiene de dos objetos de visualización que se mezclan de forma conjunta visualmente. Para utilizar un sombreado como modo de mezcla, asigne el objeto Shader a la propiedad blendShader del objeto de visualización del primer plano. Si se asigna una valor distinto a null a la propiedad blendShader , la propiedad blendMode del objeto de visualización se establece automáticamente en BlendMode.SHADER . En el siguiente listado se muestra el uso de un sombreado como modo de mezcla. Observe que en este ejemplo se da por hecho que existe un objeto de visualización llamado foreground , que se incluye en el mismo elemento principal de la lista de visualización que el resto de contenido de visualización, con el valor foreground que se superpone al resto de contenido:

foreground.blendShader = myShader;

Cuando se utiliza un sombreado como modo de mezcla, el sombreado se debe definir con dos entradas como mínimo. Tal y como muestra el ejemplo, en el código no se definen los valores de entrada. Sin embargo, las dos imágenes mezcladas se utilizan automáticamente como entradas del sombreado. La imagen en primer plano se establece como segunda imagen. (Este es el objeto de visualización al que se aplica el modo de mezcla.) Una imagen de primer plano se crea adoptando un compuesto de todos los píxeles detrás del cuadro delimitador de la imagen de primer plano. Esta imagen se establece como la primera imagen de entrada. Si se utiliza un sombreado que espera más de dos entradas, se proporciona un valor para todas las entradas posteriores a las dos primeras.

En el siguiente ejemplo se muestra el uso de un sombreado como modo de mezcla. El ejemplo utiliza un modo de mezcla de aclarado basado en la luminosidad. El resultado de la mezcla es que el valor de píxel más claro de cualquiera de los objetos mezclados pasa a ser el píxel que se muestra.

Nota: Mario Klingemann ha escrito el código de este ejemplo. Gracias Mario por compartir este ejemplo. Para obtener más información sobre el trabajo de Mario y consultar su material, visite www.quasimondo.com/ .

El código de ActionScript importante se encuentra en estos dos métodos:

  • init() : el método init() se llama cuando se carga la aplicación. En este método el código carga el archivo de código de bytes de sombreado.

  • onLoadComplete() : en el método onLoadComplete() el código crea el objeto Shader denominado shader . A continuación dibuja tres objetos. El primero, backdrop , es un fondo gris oscuro detrás de los objetos mezclados. El segundo, backgroundShape , es una elipse con degradado verde. El tercer objeto, foregroundShape , es una elipse con degradado naranja.

    La elipse foregroundShape es el objeto de primer plano de la mezcla. La imagen de fondo de la mezcla está formada por la parte de backdrop y la parte de backgroundShape , que se superponen mediante al cuadro delimitador del objeto foregroundShape . El objeto foregroundShape es el objeto de primer orden en la lista de visualización. Se superpone parcialmente a backgroundShape y completamente a backdrop . Debido a este solapamiento, si no se aplica un modo de mezcla, la elipse naranja ( foregroundShape ) se muestra completamente y parte de la elipse verde ( backgroundShape ) queda oculta:

    Sin embargo, cuando se aplica el modo de mezcla, la parte más clara de la elipse verde se “deja ver”, ya que es más clara que la parte de foregroundShape que se solapa con ella:

Este es el código de ActionScript de este ejemplo. Utilice esta clase como clase principal de aplicación para un proyecto solo ActionScript en Flex, o bien, como la clase de documento para el archivo FLA en 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 es el código fuente del núcleo del sombreado LumaLighten, que se utiliza para crear el archivo de código de bytes “LumaLighten.pbj” de 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; 
    } 
}

Para obtener más información sobre el uso de los modos de mezcla, consulte Aplicación de modos de mezcla .

Nota: cuando se ejecuta un programa de sombreado de Pixel Bender como mezcla en Flash Player o AIR, las funciones de muestra y outCoord() se comportan de forma distinta que en otros contextos. En una mezcla, una función de muestra siempre devuelve el píxel actual que está evaluando el sombreador. Por ejemplo, no se puede añadir un desplazamiento a outCoord() para obtener una muestra de un píxel vecino. Del mismo modo, si utiliza la función outCoord() fuera de una función de muestra, sus coordenadas siempre se calcularán como 0. Por ejemplo, no se puede utilizar la posición de un píxel para influir en la combinación de las imágenes mezcladas.