Angeben von Shader-Eingaben und -Parameterwerten

Flash Player 10 und höher, Adobe AIR 1.5 und höher

Die Definition zahlreicher Pixel Bender-Shader sieht vor, dass ein oder mehrere Eingabebilder für die Shader-Verarbeitung verwendet werden. Ein Shader kann beispielsweise ein Quellbild akzeptieren und dieses Bild mit einem bestimmten Effekt ausgeben, der darauf angewendet wurde. Abhängig von der Verwendung des Shaders kann der Eingabewert entweder automatisch festgelegt werden, oder Sie müssen einen Wert explizit angeben. Ebenso geben zahlreiche Shader Parameter an, mit deren Hilfe die Ausgabe des Shaders angepasst wird. Sie müssen für jeden Parameter explizit einen Wert festlegen, bevor Sie den Shader verwenden.

Verwenden Sie die data -Eigenschaft des Shader-Objekts, um Shader-Eingaben und -Parameter festzulegen und um zu bestimmen, ob ein bestimmter Shader Eingaben oder Parameter voraussetzt. Die data -Eigenschaft ist eine ShaderData-Instanz.

Identifizieren von Shader-Eingaben und -Parametern

Beim Angeben von Shader-Eingaben und -Parameterwerten müssen Sie zunächst ermitteln, ob der verwendete Shader Eingabebilder oder Parameter voraussetzt. Jede Shader-Instanz verfügt über eine data -Eigenschaft, die ein ShaderData-Objekt enthält. Wenn der Shader Eingaben oder Parameter definiert, erfolgt der Zugriff auf diese als Eigenschaften des ShaderData-Objekts. Die Namen der Eigenschaften stimmen mit den Namen überein, die im Shader-Quellcode für die Eingaben und Parameter angegeben sind. Wenn der Shader beispielsweise eine Eingabe mit dem Namen src definiert, enthält das ShaderData-Objekt eine Eigenschaft mit dem Namen src für diese Eingabe. Jede Eigenschaft, die eine Eingabe darstellt, ist eine ShaderInput-Instanz. Eigenschaften, die einen Parameter darstellen, sind ShaderParameter-Instanzen.

Im Idealfall stellt der Ersteller des Shaders entsprechende Dokumentation bereit, in der angegeben wird, welche Eingabebildwerte und Parameter der Shader voraussetzt, wofür diese stehen, wie die zulässigen Werte lauten usw.

Wenn keine Dokumentation zum Shader verfügbar ist (und Sie den Quellcode nicht haben), können Sie die Shader-Daten analysieren, um die Eingaben und Parameter zu ermitteln. Die Eigenschaften, die Eingaben und Parameter repräsentieren, werden dynamisch zum ShaderData-Objekt hinzugefügt. Sie können daher eine for..in -Schleife nutzen, um das ShaderData-Objekt zu analysieren und zu ermitteln, ob der zugehörige Shader Eingaben oder Parameter definiert. Wie bereits im Abschnitt Zugreifen auf Shader-Metadaten erläutert wurde, wird auf alle Metadatenwerte, die für einen Shader definiert sind, auch als dynamische Eigenschaft zugegriffen, die der Shader.data -Eigenschaft hinzugefügt wird. Wenn Sie dieses Verfahren zum Identifizieren von Shader-Eingaben und -Parametern verwenden, müssen Sie den Datentyp der dynamischen Eigenschaften überprüfen. Wenn eine Eigenschaft eine ShaderInput-Instanz ist, stellt diese eine Eingabe dar. Handelt es sich um eine ShaderParameter-Instanz, stellt sie einen Parameter dar. Andernfalls handelt es sich um einen Metadatenwert. Das folgende Beispiel veranschaulicht, wie Sie mit der for..in -Schleife die dynamischen Eigenschaften der data -Eigenschaft eines Shaders überprüfen. Jede Eingabe (ShaderInput-Objekt) wird einer Vector-Instanz mit dem Namen inputs hinzugefügt. Jeder Parameter (ShaderParameter-Objekt) wird einer Vector-Instanz mit dem Namen parameters hinzugefügt. Schließlich werden alle Metadateneigenschaften einer Vector-Instanz mit dem Namen metadata hinzugefügt. Beachten Sie, dass für dieses Beispiel bereits eine Shader-Instanz mit dem Namen myShader erstellt sein muss.

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

Angeben von Shader-Eingabewerten

Viele Shader setzen mindestens ein Eingabebild voraus, das in der Shader-Verarbeitung verwendet wird. Häufig wird eine Eingabe bei der Verwendung des Shader-Objekts automatisch angegeben. Beispiel: Ein Shader setzt eine Eingabe voraus und dieser Shader wird als Filter verwendet. Wenn der Filter auf ein Anzeigeobjekt oder ein BitmapData-Objekt angewendet wird, wird dieses Objekt automatisch als Eingabe festgelegt. In diesem Fall müssen Sie nicht explizit einen Eingabewert angeben.

In anderen Fällen, insbesondere wenn der Shader mehrere Eingaben definiert, legen Sie den Wert für eine Eingabe explizit fest. Jede Eingabe, die in einem Shader definiert ist, wird in ActionScript durch ein ShaderInput-Objekt dargestellt. Das ShaderInput-Objekt ist eine Eigenschaft der ShaderData-Instanz in der data -Eigenschaft des Shader-Objekts, wie unter Identifizieren von Shader-Eingaben und -Parametern beschrieben. Beispiel: Ein Shader definiert eine Eingabe mit dem Namen src und dieser Shader ist mit einem Shader-Objekt mit dem Namen myShader verknüpft. In diesem Fall greifen Sie auf das ShaderInput-Objekt für die Eingabe src unter Verwendung des folgenden Bezeichners zu:

myShader.data.src

Jedes ShaderInput-Objekt verfügt über eine input -Eigenschaft, mit der der Wert für die Eingabe festgelegt wird. Legen Sie für die input -Eigenschaft eine BitmapData-Instanz fest, um Bilddaten anzugeben. Sie können für die input -Eigenschaft auch eine BitmapData- oder Vector.<Number>-Instanz festlegen, um binäre Daten oder Zahlen anzugeben. Weitere Informationen zur Verwendung einer BitmapData- oder Vector.<Number>-Instanz als Eingabe finden Sie im Eintrag zu ShaderInput.input im ActionScript 3.0-Referenzhandbuch für die Adobe Flash-Plattform .

Zusätzlich zur input -Eigenschaft verfügt ein ShaderInput-Objekt über Eigenschaften, mit denen Sie den Bildtyp ermitteln können, der von der Eingabe vorausgesetzt wird. Hierzu zählen die Eigenschaften width , height und channels . Jedes ShaderInput-Objekt verfügt außerdem über eine index -Eigenschaft, anhand derer Sie feststellen können, ob für die Eingabe ein expliziter Wert angegeben werden muss. Wenn ein Shader mehr Eingaben als die automatisch festgelegte Anzahl erfordert, müssen Sie Werte für diese Eingaben festlegen. Weitere Informationen zu den Verwendungsmöglichkeiten von Shadern sowie zur automatischen Einstellung von Eingabewerten finden Sie unter Verwenden eines Shaders .

Angeben von Shader-Parameterwerten

Einige Shader definieren Parameterwerte, die der Shader zum Erstellen der Ergebnisse nutzt. Ein Shader, der die Helligkeit eines Bilds ändert, kann beispielsweise einen Parameter für die Helligkeit angeben, der festlegt, inwieweit die Helligkeit durch den Vorgang angepasst wird. Für einen einzelnen, in einem Shader definierten Parameter können ein oder mehrere Werte vorausgesetzt werden, je nach Parameterdefinition im Shader. Jeder Parameter, der in einem Shader definiert ist, wird in ActionScript durch ein ShaderParameter-Objekt dargestellt. Das ShaderParameter-Objekt ist eine Eigenschaft der ShaderData-Instanz in der data-Eigenschaft des Shader-Objekts, wie unter Identifizieren von Shader-Eingaben und -Parametern beschrieben. Beispiel: Ein Shader definiert einen Parameter mit dem Namen brightness und dieser Shader wird durch ein Shader-Objekt mit dem Namen myShader dargestellt. In diesem Fall greifen Sie auf das ShaderParameter-Objekt für den Parameter brightness unter Verwendung des folgenden Bezeichners zu:

myShader.data.brightness

Um einen oder mehrere Werte für den Parameter anzugeben, erstellen Sie ein ActionScript-Array mit den Werten und weisen dieses Array der value -Eigenschaft des ShaderParameter-Objekts zu. Die value -Eigenschaft ist als Array-Instanz definiert, da ein einzelner Shader-Parameter mehrere Werte voraussetzen kann. Selbst wenn der Shader-Parameter nur einen Wert erfordert, müssen Sie den Wert in das Array-Objekt einschließen, um ihn der ShaderParameter.value -Eigenschaft zuzuweisen. Im Folgenden wird die Einstellung eines einzelnen Werts als value -Eigenschaft erläutert.

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

Wenn der Pixel Bender-Quellcode des Shaders einen Standardwert für den Parameter definiert, wird beim Erstellen des Shader-Objekts ein Array mit den Standardwerten erstellt und der value -Eigenschaft des ShaderParameter-Objekts zugewiesen. Nachdem der value -Eigenschaft ein Array zugewiesen wurde (auch wenn es das Standard-Array ist), können Sie den Parameterwert ändern, indem Sie den Wert des Array-Elements bearbeiten. Sie müssen kein neues Array erstellen und der value -Eigenschaft zuweisen.

Das folgende Beispiel veranschaulicht, wie Sie den Parameterwert eines Shaders in ActionScript festlegen. In diesem Beispiel definiert der Shader einen Parameter mit dem Namen color . Der color -Parameter ist als eine float4 -Variable im Pixel Bender-Quellcode deklariert, d. h. es handelt sich um ein Array mit vier Gleitkommazahlen. In diesem Beispiel wird der Wert des color -Parameters kontinuierlich geändert. Bei jeder Änderung wird der Shader verwendet, um ein farbiges Rechteck auf dem Bildschirm zu zeichnen. Das Ergebnis ist eine animierte Farbänderung.

Hinweis: Der Code für dieses Beispiel wurde von Ryan Taylor geschrieben. Vielen Dank an Ryan für die Bereitstellung dieses Beispiels. Unter www.boostworthy.com/ können Sie Ryans Mappe einsehen und seine Texte lesen.

Der ActionScript-Code basiert primär auf drei Methoden:

  • init() : In der init() -Methode lädt der Code die Pixel Bender-Bytecodedatei, die den Shader enthält. Beim Laden der Datei wird die onLoadComplete() -Methode aufgerufen.

  • onLoadComplete() : In der onLoadComplete() -Methode erstellt der Code das Shader-Objekt mit dem Namen shader . Er erstellt außerdem eine Sprite-Instanz mit dem Namen texture . In der renderShader() -Methode zeichnet der Code das Shader-Ergebnis pro Bild einmal in texture .

  • onEnterFrame() : Die onEnterFrame() -Methode wird einmal pro Bild aufgerufen und erzeugt den Animationseffekt. In dieser Methode legt der Code für den Shader-Parameterwert die neue Farbe fest. Anschließend wird die renderShader() -Methode aufgerufen, um das Ergebnis des Shaders in Form eines Rechtecks zu zeichnen.

  • renderShader() : In der renderShader() -Methode ruft der Code die Graphics.beginShaderFill() -Methode auf, um eine Füllung für den Shader anzugeben. Anschließend wird ein Rechteck gezeichnet, dessen Füllung durch die Shader-Ausgabe (die generierte Farbe) definiert wird. Weitere Informationen zu dieser Verwendung des Shaders finden Sie unter Verwenden eines Shaders als Füllmuster für Zeichnungen .

Im Folgenden wird der ActionScript-Code für dieses Beispiel angezeigt. Verwenden Sie diese Klasse als Hauptanwendungsklasse für ausschließlich in ActionScript erstellte Projekte in Flash Builder oder als Dokumentklasse für die FLA-Datei in 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(); 
        } 
    } 
}

Im Folgenden ist der Quellcode für den Kernel des ColorFilter-Shaders dargestellt, der zum Erstellen der Pixel Bender-Bytecodedatei „ColorFilter.pbj“ verwendet wurde:

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

Wenn Sie einen Shader verwenden, dessen Parameter nicht dokumentiert sind, können Sie die Art und Anzahl der Elemente, die in das Array eingeschlossen werden müssen, durch Überprüfen der type -Eigenschaft des ShaderParameter-Objekts ermitteln. Die type -Eigenschaft gibt den Datentyp des Parameters an, der im Shader selbst definiert ist. Eine Liste mit Informationen zu Art und Anzahl der Elemente, die von jedem Parametertyp vorausgesetzt werden, finden Sie im ActionScript 3.0-Referenzhandbuch unter ShaderParameter.value .

Jedes ShaderParameter-Objekt verfügt zudem über eine index -Eigenschaft, die die Position des Parameters in der Reihenfolge der Shader-Parameter angibt. Neben diesen Eigenschaften kann ein ShaderParameter-Objekt weitere Eigenschaften aufweisen, die vom Ersteller des Shaders bereitgestellte Metadatenwerte enthalten. Der Ersteller kann beispielsweise Metadatenwerte wie Minimum und Maximum sowie Standardwerte für einen Parameter festlegen. Alle vom Ersteller angegebenen Metadatenwerte werden dem ShaderParameter-Objekt als dynamische Eigenschaften hinzugefügt. Verwenden Sie zum Analysieren dieser Eigenschaften eine for..in -Schleife, um die dynamischen Eigenschaften des ShaderParameter-Objekts anzuzeigen und die zugehörigen Metadaten zu identifizieren. Das folgende Beispiel veranschaulicht, wie Sie mit der for..in -Schleife die Metadaten eines ShaderParameter-Objekts identifizieren. Jeder Metadatenwert wird einer Vector-Instanz mit dem Namen metadata hinzugefügt. Beachten Sie, dass für dieses Beispiel eine Shader-Instanz mit dem Namen myShader bereits erstellt sein muss und dass diese einen Parameter mit dem Namen brightness aufweisen muss:

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