Ange skuggningsindata och parametervärden

Flash Player 10 och senare, Adobe AIR 1.5 och senare

Många Pixel Bender-skuggningar definieras till att använda en eller flera indatabilder som används i skuggningsbearbetningen. Det är till exempel vanligt att en skuggning accepterar en källbild och skapar utdata av den bilden med en viss effekt. Beroende på hur skuggningen används kan indatavärdet anges automatiskt eller så måste du explicit ange ett värde. Många skuggningar anger på ett liknande sätt parametrar som används för att anpassa skuggningens utdata. Du måste också explicit ange ett värde för varje parameter innan du använder skuggningen.

Du använder Shader-objektets data -egenskap för att ange skuggningsindata och -parametrar och för att ta reda på om en viss skuggning förväntar sig indata eller parametrar. Egenskapen data är en ShaderData-instans.

Identifiera skuggningsindata och -parametrar

Det första steget i att ange skuggningsindata och -parametervärden är att ta reda på om skuggningen som du använder förväntar sig några indatabilder eller parametrar. Varje Shader-instans har en data -egenskap som innehåller ett ShaderData-objekt. Om skuggningen definierar några indata eller parametrar, nås de som egenskaper i det ShaderData-objektet. Egenskapens namn matchar namnen som anges för indata och parametrar i skuggningens källkod. Om en skuggning till exempel definierar indata med namnet src har ShaderData-objektet en egenskap med namnet src som representerar dessa indata. Varje egenskap som representerar indata är en ShaderInput-instans, och varje egenskap som representerar en parameter är en ShaderParameter-instans.

Det bästa är att den som utvecklar skuggningen dokumenterar den, där det anges vilka indatavärden och parametrar som skuggningen förväntar sig, vad de representerar, lämpliga värden o.s.v.

Om skuggningen emellertid inte dokumenteras (och du inte har källkoden) kan du granska skuggningens data för att på så sätt identifiera indata och parametrar. Egenskaperna som representerar indata och parametrar läggs till dynamiskt i ShaderData-objektet. Du kan därför använda en for..in -slinga när du undersöker ShaderData-objektet för att ta reda på om dess tillhörande skuggning definierar några indata eller parametrar. Så som beskrivs i Få tillgång till skuggningens metadata kan alla metadatavärden som definieras för en skuggning också nås som en dynamisk egenskap som läggs till i egenskapen Shader.data . När du använder den här metoden för att identifiera skuggningens indata och parametrar, kontrollerar du datatypen för de dynamiska egenskaperna. Om en egenskap är en ShaderInput-instans representerar den indata. Om den är en ShaderParameter-instans representerar den en parameter. Annars är den ett metadatavärde. Följande exempel visar hur du använder en for..in -slinga för att undersöka de dynamiska egenskaperna i en skuggnings data -egenskap. Varje indata (ShaderInput-objekt) läggs till i en Vector-instans med namnet inputs . Varje parameter (ShaderParameter-objekt) läggs till i en Vector-instans med namnet parameters . Alla metadataegenskaper läggs slutligen till i en Vector-instans med namnet metadata . I det här exemplet förutsätts det att en Shader-instans med namnet myShader redan har skapats:

var shaderData:ShaderData = myShader.data; 
var inputs:Vector.<ShaderInput> = new Vector.<ShaderInput>(); 
var parameters:Vector.<ShaderParameter> = new Vector.<ShaderParameter>(); 
var metadata:Vector.<String> = new Vector.<String>(); 
 
for (var prop:String in shaderData) 
{ 
    if (shaderData[prop] is ShaderInput) 
    { 
        inputs[inputs.length] = shaderData[prop]; 
    } 
    else if (shaderData[prop] is ShaderParameter) 
    { 
        parameters[parameters.length] = shaderData[prop]; 
    } 
    else 
    { 
        metadata[metadata.length] = shaderData[prop]; 
    } 
} 
 
// do something with the inputs or properties

Ange indatavärden för skuggningen

Många skuggningar förväntar en eller flera indatabilder som ska användas i skuggningsbearbetningen. I många fall anges indata automatiskt när Shader-objektet används. Anta att en skuggning kräver ett indatavärde, och att skuggningen används som ett filter. När filtret används på ett visningsobjekt eller BitmapData-objekt, ställs det objektet in automatiskt som indata. I så fall behöver du inte ställa in indatavärdet explicit.

I vissa fall, speciellt om en skuggning definierar flera indatavärden, måste du emellertid ställa in ett värde explicit. Varje indatavärde som definieras i en skuggning representeras i ActionScript med ett ShaderInput-objekt. ShaderInput-objektet är en egenskap i ShaderData-instansen i Shader-objektets data -egenskap, vilket beskrivs i Identifiera skuggningsindata och -parametrar . Anta att en skuggning definierar ett indatavärde med namnet src , och att skuggningen länkas till ett Shader-objekt med namnet myShader . I så fall får du tillgång till det ShaderInput-objekt som motsvarar src -indatavärdet med följande identifierare:

myShader.data.src

Varje ShaderInput-objekt har en input -egenskap som används för att ställa in värdet på indata. Du ställer in egenskapen input till en BitmapData-instans när du vill ange bilddata. Du kan också ställa in input -egenskapen till en BitmapData eller Vector.<Number>-instans om du vill ange binära eller numeriska data. Mer information och restriktioner för hur du använder en BitmapData- eller Vector.<Number>-instans som indata. Läs mer i avsnittet om ShaderInput.input i Referenshandbok för ActionScript 3.0 i Adobe Flash-plattformen .

Förutom input -egenskapen har ett ShaderInput-objekt egenskaper som kan användas för att ta reda på vilken typ av bild som indata förväntar sig. Dessa egenskaper är bland andra width , height och channels . Varje ShaderInput-objekt har också en index -egenskap, som är användbar när du vill ta reda på om ett explicit värde måste anges för indata. Om en skuggning förväntar fler indata än det antal som ställs in automatiskt, ställer du in värden för dessa indata. Mer information om hur du kan använda en skuggning på olika sätt, och om indatavärdena ställs in automatiskt, finns i Använda en skuggning .

Ange parametervärden för skuggningen

Vissa skuggningar definierar parametervärden som skuggningen använder för att skapa resultatet. En skuggning som till exempel ändrar intensiteten för en bild kanske anger en intensitetsparameter som bestämmer hur mycket åtgärden påverkar intensiteten. En enda parameter som definieras i en skuggning kan förvänta ett enda värde eller flera värden, enligt parameterdefinition i skuggningen. Varje parameter som definieras i en skuggning representeras i ActionScript med ett ShaderParameter-objekt. ShaderParameter-objektet är en egenskap till ShaderData-instansen i Shader-objektets dataegenskap, vilket beskrivs i Identifiera skuggningsindata och -parametrar . Anta att en skuggning definierar en parameter med namnet brightness , och att skuggningen representeras av ett Shader-objekt med namnet myShader . I så fall får du tillgång till den ShaderParameter som motsvarar brightness -parametern med följande identifierare:

myShader.data.brightness

Om du vill ställa in ett eller flera värden för parametern skapar du en ActionScript-array som innehåller värdet eller värdena och tilldelar den till ShaderParameter-objektets value -egenskap. Egenskapen value definieras som en Array-instans eftersom det är möjligt att en enda skuggningsparameter kräver flera värden. Även om skuggningsparametern bara förväntar sig ett enda värde, måste du placera värdet i ett Array-objekt för att kunna tilldela den till egenskapen ShaderParameter.value . I exemplet nedan visas hur du ställer in ett enda värde som egenskapen value :

myShader.data.brightness.value = [75];

Om Pixel Bender-källkoden för skuggningen definierar ett standardvärde för parametern, skapas en array med standardvärdet eller -värdena och den tilldelas till ShaderParameter-objektets value -egenskap när Shader-objektet skapas. När en array har tilldelats till value -egenskapen (inklusive om det är standardarrayen) kan parametervärdet ändras genom att värdet på arrayelementet ändras. Du behöver inte skapa en ny array och tilldela den till value -egenskapen.

I exemplet nedan visas hur du ställer in en skuggnings parametervärde i ActionScript. I det här exemplet definierar skuggningen en parameter med namnet color . Parametern color deklareras som en float4 -variabel i Pixel Bender-källkoden, vilket innebär att det är en array med fyra flyttal. I exemplet ändras color -parametervärdet fortlöpande, och varje gång det ändras används skuggningen för att rita en färgad rektangel på skärmen. Resultatet blir en animerad färgändring.

Obs! Koden i det här exemplet har skrivits av Ryan Taylor. Vi tackar Ryan för att han delat med sig. Fler exempel på Ryans arbete och kod finns på www.boostworthy.com/ .

ActionScript-koden centreras kring tre metoder:

  • init() : I metoden init() läser koden in Pixel Bender-bytekodfilen som innehåller skuggningen. När filen läses in anropas metoden onLoadComplete() .

  • onLoadComplete() : I metoden onLoadComplete() skapar koden Shader-objektet med namnet shader . Den skapar också en Sprite-instans med namnet texture . I metoden renderShader() ritar koden skuggningsresultatet i texture en gång per bildruta.

  • onEnterFrame() : Metoden onEnterFrame() anropas en gång per bildruta, vilket skapar animeringseffekten. I den här metoden ställer koden in skuggningsparameterns värde till den nya färgen och anropar sedan metoden renderShader() för att rita skuggningsresultatet som en rektangel.

  • renderShader() : I metoden renderShader() anropar koden metoden Graphics.beginShaderFill() för att ange en skuggningsfyllning. Den ritar sedan en rektangel vars fyllning definieras av skuggningsresultatet (den färg som skapas). Mer information om hur du använder en skuggning på det här sättet finns i Använda en skuggning som teckningsfyllning .

Nedan finns ActionScript-koden för det här exemplet. Använd den här klassen som huvudprogramklass för ett ActionScript-projekt i Flash Builder, eller som dokumentklass för FLA-filen i Flash Professional:

package 
{ 
    import flash.display.Shader; 
    import flash.display.Sprite; 
    import flash.events.Event; 
    import flash.net.URLLoader; 
    import flash.net.URLLoaderDataFormat; 
    import flash.net.URLRequest; 
     
    public class ColorFilterExample extends Sprite 
    { 
        private const DELTA_OFFSET:Number = Math.PI * 0.5; 
        private var loader:URLLoader; 
        private var shader:Shader; 
        private var texture:Sprite; 
        private var delta:Number = 0; 
         
        public function ColorFilterExample() 
        { 
            init(); 
        } 
         
        private function init():void 
        { 
            loader = new URLLoader(); 
            loader.dataFormat = URLLoaderDataFormat.BINARY; 
            loader.addEventListener(Event.COMPLETE, onLoadComplete); 
            loader.load(new URLRequest("ColorFilter.pbj")); 
        } 
         
        private function onLoadComplete(event:Event):void 
        { 
            shader = new Shader(loader.data); 
             
            texture = new Sprite(); 
             
            addChild(texture); 
             
            addEventListener(Event.ENTER_FRAME, onEnterFrame); 
        } 
        private function onEnterFrame(event:Event):void 
        { 
            shader.data.color.value[0] = 0.5 + Math.cos(delta - DELTA_OFFSET) * 0.5; 
            shader.data.color.value[1] = 0.5 + Math.cos(delta) * 0.5; 
            shader.data.color.value[2] = 0.5 + Math.cos(delta + DELTA_OFFSET) * 0.5; 
            // The alpha channel value (index 3) is set to 1 by the kernel's default 
            // value. This value doesn't need to change. 
             
            delta += 0.1; 
             
            renderShader(); 
        } 
         
        private function renderShader():void 
        { 
            texture:graphics.clear(); 
            texture.graphics.beginShaderFill(shader); 
            texture.graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight); 
            texture.graphics.endFill(); 
        } 
    } 
}

Nedan finns källkoden för ColorFilter-skuggningskärnan, som används för att skapa Pixel Bender-filen med bytekod, ”ColorFilter.pbj”:

<languageVersion : 1.0;> 
kernel ColorFilter 
< 
    namespace : "boostworthy::Example"; 
    vendor : "Ryan Taylor"; 
    version : 1; 
    description : "Creates an image where every pixel has the specified color value."; 
> 
{ 
    output pixel4 result; 
     
    parameter float4 color 
    < 
        minValue:float4(0, 0, 0, 0); 
        maxValue:float4(1, 1, 1, 1); 
        defaultValue:float4(0, 0, 0, 1); 
    >; 
     
    void evaluatePixel() 
    { 
        result = color; 
    } 
}

Om du använder en skuggning vars parametrar inte dokumenteras kan du ta reda på hur många element och av vilken typ som måste inkluderas i arrayen genom att kontrollera ShaderParameter-objektets type -egenskap. Egenskapen type anger parameterns datatyp, som definieras i själva skuggningen. En lista med antal och typ av element som förväntas av respektive parametertyp finns i egenskapslistan för ShaderParameter.value i referensinformationen till ActionScript 3.0.

Varje ShaderParameter-objekt har också en index -egenskap, som anger var parametern passar in i ordningen för skuggningens parametrar. Förutom dessa egenskaper kan ett ShaderParameter-objekt ha fler egenskaper som innehåller metadatavärden som anges av den som utvecklat skuggningen. Utvecklaren kan till exempel ange metadatavärden som minsta, högsta och standardvärden för en parameter. Alla metadatavärden som utvecklaren anger läggs till i ShaderParameter-objektet som dynamiska egenskaper. Du undersöker dessa egenskaper genom att göra en slinga över ShaderParameter-objektets dynamiska egenskaper med en for..in -slinga för att identifiera dess metadata. Följande exempel visar hur du använder en for..in -slinga för att identifiera ett ShaderParameter-objekts metadata. Varje metadatavärde läggs till i en Vector-instans med namnet metadata . Observera att det här exemplet förutsätter att en Shader-instans med namnet myShader redan har skapats, och att det är känt att den har en parameter med namnet brightness :

var brightness:ShaderParameter = myShader.data.brightness; 
var metadata:Vector.<String> = new Vector.<String>(); 
 
for (var prop:String in brightness) 
{ 
    if (brightness[prop] is String) 
    { 
        metadata[metadata.length] = brightness[prop]; 
    } 
} 
 
// do something with the metadata