Certains shaders définissent des valeurs de paramètres qu’ils utilisent dans la création de leur résultat. Par exemple, un shader qui modifie la luminosité d’une image pourrait spécifier un paramètre de luminosité qui détermine dans quelle mesure l’opération affecte cette luminosité. Un paramètre unique défini dans un shader peut prévoir une ou plusieurs valeurs suivant la façon dont il a été spécifié dans le shader. Tout paramètre défini dans un shader est représenté dans ActionScript par un objet ShaderParameter. L’objet ShaderParameter est une propriété de l’occurrence de ShaderData dans la propriété des données de l’objet Shader. Une description se trouve dans la section
Identification des entrées et des paramètres d’un shader
. Par exemple, supposons qu’un shader qui définit un paramètre appelé
luminosité
soit représenté par un objet Shader appelé
myShader
. Vous accédez alors à l’objet ShaderParameter correspondant au paramètre
luminosité
à l’aide de l’identifiant suivant :
myShader.data.brightness
Pour spécifier une ou plusieurs valeurs pour le paramètre, créez un tableau ActionScript contenant la ou les valeurs et affectez-le à la propriété
value
de l’objet ShaderParameter. La propriété
value
est définie en tant qu’occurrence d’Array car il est possible qu’un seul paramètre du shader nécessite plusieurs valeurs. Même si le paramètre du shader ne prévoit qu’une seule valeur, il vous faut placer la valeur dans un objet Array pour l’affecter à la propriété
ShaderParameter.value
. Le code suivant montre comment définir une seule valeur pour la propriété
value
.
myShader.data.brightness.value = [75];
Si le code source Pixel Bender pour le shader spécifie une valeur par défaut pour le paramètre, un tableau contenant la ou les valeurs par défaut est créé et affecté à la propriété
value
de l’objet ShaderParameter lorsque l’objet Shader est créé. Dès qu’un tableau est affecté à la propriété
value
, même s’il s’agit de celui par défaut, la valeur du paramètre peut être modifiée en changeant la valeur de l’élément du tableau. Il n’est pas nécessaire de créer un autre tableau et de l’affecter à la propriété
value
.
L’exemple ci-dessous indique comment définir une valeur de paramètre dans un shader avec ActionScript. Dans cet exemple, le shader définit un paramètre appelé
color
. Ce paramètre
color
est déclaré en tant que variable
float4
dans le code source Pixel Bender, ce qui signifie qu’il s’agit d’un tableau à quatre nombres en virgule flottante. Dans l’exemple, la valeur du paramètre
color
change constamment. A chaque changement, le shader est utilisé pour dessiner un rectangle coloré à l’écran. Il en résulte un changement de couleur animé.
Remarque :
le code de cet exemple a été rédigé par Ryan Taylor. Merci Ryan de bien vouloir nous en faire profiter. Vous pouvez accéder aux exemples de Ryan et lire ses commentaires à l’adresse
www.boostworthy.com/
.
Le code ActionScript repose sur l’utilisation de trois méthodes :
-
init()
: dans la méthode
init()
, le code charge le fichier de pseudo-code binaire Pixel Bender contenant le shader. Lors du chargement du fichier, la méthode
onLoadComplete()
est appelée.
-
onLoadComplete()
: dans la méthode
onLoadComplete()
, le code crée l’objet Shader appelé
shader
. Il crée également une occurrence de Sprite appelée
texture
. Dans la méthode
renderShader()
, le code dessine une fois par image le résultat du shader dans
texture
.
-
onEnterFrame()
: la méthode
onEnterFrame()
est appelée une fois par image, créant ainsi un effet d’animation. Dans cette méthode, le code définit la valeur du paramètre du shader sur la nouvelle couleur, puis appelle la méthode
renderShader()
pour dessiner le résultat du shader sous forme de rectangle.
-
renderShader()
: dans la méthode
renderShader()
, le code appelle la méthode
Graphics.beginShaderFill()
pour définir un remplissage de shader. Il dessine ensuite un rectangle dont le remplissage est défini par la sortie du shader (la couleur générée). Pour plus d’informations sur ce type d’utilisation d’un shader, voir
Utilisation d’un shader comme outil de remplissage de dessin
.
Vous trouverez ci-dessous le code ActionScript associé à cet exemple : Utilisez cette classe en tant que classe d’application principale d’un projet ActionScript uniquement dans Flash Builder, ou en tant que classe de document du fichier FLA dans 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();
}
}
}
Vous trouverez ci-dessous le code source du noyau du shader ColorFilter, utilisé pour la création du fichier « ColorFilter.pbj » de pseudo-code binaire Pixel Bender.
<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;
}
}
Si vous utilisez un shader dont les paramètres ne sont pas documentés, c’est par le contrôle de la propriété
type
de l’objet ShaderParameter que vous pouvez évaluer le nombre d’éléments et leur type qu’il faut inclure dans le tableau. La propriété
type
indique le type de données du paramètre tel qu’il est défini dans le shader lui-même. Pour consulter la liste du nombre et du type d’éléments prévus par chaque type de paramètre, voir le code associé à la propriété
ShaderParameter.value
dans le Guide de référence ActionScript 3.0 pour Flash Professional.
Chaque objet ShaderParameter possède également une propriété
index
qui indique l’emplacement du paramètre dans l’ordre des paramètres du shader. En plus de ces propriétés, un objet ShaderParameter peut avoir des propriétés supplémentaires qui contiennent des valeurs de métadonnées fournies par le programmeur du shader. Par exemple, le programmeur peut définir pour un paramètre des valeurs de métadonnées telles que minimum, maximum et des valeurs par défaut. Toutes les valeurs de métadonnées spécifiées par le programmeur sont ajoutées à l’objet ShaderParameter en tant que propriétés dynamiques. Pour passer en revue ces propriétés, utilisez une boucle
for..in
pour boucler dans les propriétés dynamiques de l’objet ShaderParameter afin d’identifier ses métadonnées. L’exemple ci-dessous montre comment utiliser une boucle
for..in
afin d’identifier les métadonnées d’un objet ShaderParameter. Chaque valeur de métadonnées est ajoutée à une occurrence de Vector appelée
metadata
. Remarquez que cet exemple suppose qu’une occurrence de Shader appelée
myShader
existe déjà et qu’elle possède un paramètre appelé
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