Использование шейдера в качестве заливки

Flash Player 10 и более поздних версий, Adobe AIR 1.5 и более поздних версий

Когда шейдер используется для создания заливки рисунка, необходимо создать векторную фигуру с помощью API-методов рисования. Вывод шейдера используется для заливки фигуры так же, как растровое изображение используется в качестве растровой заливки с помощью API-интерфейса рисования. Чтобы создать заливку шейдером, в том месте кода, где начинается отрисовка фигуры, вызовите метод beginShaderFill() объекта Graphics. Передайте объект Shader в качестве первого аргумента методу beginShaderFill() , как показано ниже.

var canvas:Sprite = new Sprite(); 
canvas.graphics.beginShaderFill(myShader); 
canvas.graphics.drawRect(10, 10, 150, 150); 
canvas.graphics.endFill(); 
// add canvas to the display list to see the result

Когда шейдер используется в качестве заливки рисунка, необходимо задать значения входного изображения и значения параметров, необходимых шейдеру.

В следующем примере демонстрируется использование шейдера в качестве заливки рисунка. В данном примере шейдер создает градиент с тремя вершинами. Этот градиент имеет три цвета, каждый из них находится у вершины треугольника, между которыми образуется заливка градиентом. В дополнение, цвета меняются местами, создавая эффект анимированного вращения цветов.

Примечание. Код для этого примера написан Пeтри Лескиненом (Petri Leskinen). Мы благодарим Петри за предоставление этого кода. Примеры и учебные материалы, предоставленные Петри, можно найти по адресу http://pixelero.wordpress.com .

Код ActionScript строится на трех методах.

  • init() : метод init() вызывается при загрузке приложения. В этом методе код задает начальные значения для объектов Point, представляющих вершины треугольника. Также код создает экземпляр Sprite с именем canvas . Позднее, в методе updateShaderFill() , код рисует результат шейдера в объекте canvas по одному разу в каждом кадре. В завершение, код загружает файл байт-кода шейдера.

  • onLoadComplete() : в методе onLoadComplete() код создает объект Shader с именем shader . Также задаются начальные значения параметров. В завершение код добавляет метод updateShaderFill() в качестве прослушивателя события enterFrame , то есть он вызывается в каждом кадре один раз для создания эффекта анимации.

  • updateShaderFill() : метод updateShaderFill() вызывается один раз для каждого кадра для создания эффекта анимации. В этом методе код вычисляет и задает значения параметров шейдера. После этого код вызывает метод beginShaderFill() , чтобы создать заливку шейдером, а затем вызываются другие API-методы для отрисовки результата шейдера в треугольнике.

Ниже приводится код ActionScript для этого примера. Используйте этот класс в качестве основного класса приложения для проекта, созданного только на базе ActionScript в Flash Builder, или в качестве класса документа для FLA-файла в инструменте Flash Professional.

package 
{ 
    import flash.display.Shader; 
    import flash.display.Sprite; 
    import flash.events.Event; 
    import flash.geom.Point; 
    import flash.net.URLLoader; 
    import flash.net.URLLoaderDataFormat; 
    import flash.net.URLRequest; 
     
    public class ThreePointGradient extends Sprite 
    { 
        private var canvas:Sprite; 
        private var shader:Shader; 
        private var loader:URLLoader; 
         
        private var topMiddle:Point; 
        private var bottomLeft:Point; 
        private var bottomRight:Point; 
         
        private var colorAngle:Number = 0.0; 
        private const d120:Number = 120 / 180 * Math.PI; // 120 degrees in radians 
         
         
        public function ThreePointGradient() 
        { 
            init(); 
        } 
         
        private function init():void 
        { 
            canvas = new Sprite(); 
            addChild(canvas); 
             
            var size:int = 400; 
            topMiddle = new Point(size / 2, 10); 
            bottomLeft = new Point(0, size - 10); 
            bottomRight = new Point(size, size - 10); 
             
            loader = new URLLoader(); 
            loader.dataFormat = URLLoaderDataFormat.BINARY; 
            loader.addEventListener(Event.COMPLETE, onLoadComplete); 
            loader.load(new URLRequest("ThreePointGradient.pbj")); 
        } 
         
        private function onLoadComplete(event:Event):void 
        { 
            shader = new Shader(loader.data); 
             
            shader.data.point1.value = [topMiddle.x, topMiddle.y]; 
            shader.data.point2.value = [bottomLeft.x, bottomLeft.y]; 
            shader.data.point3.value = [bottomRight.x, bottomRight.y]; 
             
            addEventListener(Event.ENTER_FRAME, updateShaderFill); 
        } 
         
        private function updateShaderFill(event:Event):void 
        { 
            colorAngle += .06; 
             
            var c1:Number = 1 / 3 + 2 / 3 * Math.cos(colorAngle); 
            var c2:Number = 1 / 3 + 2 / 3 * Math.cos(colorAngle + d120); 
            var c3:Number = 1 / 3 + 2 / 3 * Math.cos(colorAngle - d120); 
             
            shader.data.color1.value = [c1, c2, c3, 1.0]; 
            shader.data.color2.value = [c3, c1, c2, 1.0]; 
            shader.data.color3.value = [c2, c3, c1, 1.0]; 
             
            canvas.graphics.clear(); 
            canvas.graphics.beginShaderFill(shader); 
             
            canvas.graphics.moveTo(topMiddle.x, topMiddle.y); 
            canvas.graphics.lineTo(bottomLeft.x, bottomLeft.y); 
            canvas.graphics.lineTo(bottomRight.x, bottomLeft.y); 
             
            canvas.graphics.endFill(); 
        } 
    } 
}

Ниже представлен исходный код для ядра шейдера ThreePointGradient, который используется для создания файла байт-кода Pixel Bender с именем «ThreePointGradient.pbj».

<languageVersion : 1.0;> 
kernel ThreePointGradient 
< 
    namespace : "Petri Leskinen::Example"; 
    vendor : "Petri Leskinen"; 
    version : 1; 
    description : "Creates a gradient fill using three specified points and colors."; 
> 
{ 
    parameter float2 point1 // coordinates of the first point 
    < 
        minValue:float2(0, 0); 
        maxValue:float2(4000, 4000); 
        defaultValue:float2(0, 0); 
    >; 
     
    parameter float4 color1 // color at the first point, opaque red by default 
    < 
        defaultValue:float4(1.0, 0.0, 0.0, 1.0); 
    >; 
     
    parameter float2 point2 // coordinates of the second point 
    < 
        minValue:float2(0, 0); 
        maxValue:float2(4000, 4000); 
        defaultValue:float2(0, 500); 
    >; 
     
    parameter float4 color2 // color at the second point, opaque green by default 
    < 
        defaultValue:float4(0.0, 1.0, 0.0, 1.0); 
    >; 
     
    parameter float2 point3 // coordinates of the third point 
    < 
        minValue:float2(0, 0); 
        maxValue:float2(4000, 4000); 
        defaultValue:float2(0, 500); 
    >; 
     
    parameter float4 color3 // color at the third point, opaque blue by default 
    < 
        defaultValue:float4(0.0, 0.0, 1.0, 1.0); 
    >; 
     
    output pixel4 dst; 
     
    void evaluatePixel() 
    { 
        float2 d2 = point2 - point1; 
        float2 d3 = point3 - point1; 
         
        // transformation to a new coordinate system 
        // transforms point 1 to origin, point2 to (1, 0), and point3 to (0, 1) 
        float2x2 mtrx = float2x2(d3.y, -d2.y, -d3.x, d2.x) / (d2.x * d3.y - d3.x * d2.y); 
        float2 pNew = mtrx * (outCoord() - point1); 
         
        // repeat the edge colors on the outside 
        pNew.xy = clamp(pNew.xy, 0.0, 1.0); // set the range to 0.0 ... 1.0 
         
        // interpolating the output color or alpha value 
        dst = mix(mix(color1, color2, pNew.x), color3, pNew.y); 
    } 
}
Примечание. Если заливка шейдером применяется в режиме визуализации с использованием графического процессора, цвет области заполнения будет голубым.

Дополнительные сведения о рисовании фигур с помощью API-интерфейса рисования см. в разделе Использование API рисования .