UPDATE :: Le mode de fusion présenté est disponible ici)
Voici une suite assez courte de ma série d’articles sur les shaders dans le Flash Player 10.
Si vous n’avez pas lu l’article précédent sur les shaders, filtres et surtout Pixel Bender, vous devriez probablement commencer par là :).
» Création d’un mode de fusion dans Pixel Bender
Un mode de fusion d’images consiste à manipuler une série de couleurs ARGB pour renvoyer en sortie une couleur ARGB unique.
On considére chaque pixel pour chacune des images à fusionner, et cela aux mêmes coordonnées relatives au repère local formée par l’image de fond.
Le cas minimal et le plus classique consiste à fusionner deux images : un arrière-plan et un premier plan. Ainsi, nous avons besoin de définir un minimum de 2 inputs de type image4 (image 4 canaux) pour un kernel Pixel Bender visant à être utilisé comme un mode de fusion.
input image4 background; input image4 foreground;
Nous devons ensuite combiner ces deux images. Une opération simple consiste par exemple à obtenir une image moyennée des deux entrées :
input image4 background;
input image4 foreground;
output pixel4 result;
void evaluatePixel()
{
pixel4 b = sampleNearest(background,outCoord());
pixel4 f = sampleNearest(foreground,outCoord());
result = (b+f)*0.5;
}
J’ai remarqué que les modes de fusion disponibles dans flash n’incluent pas le mode de type couleur. Ce mode, basé sur le modèle de couleur HSL, conserve la saturation et la luminosité de l’arrière plan, et lui applique la teinte de l’image de premier plan. C’est donc le premier mode de fusion que j’entreprends de faire. Le résultat obtenu est plutôt convaincant, s’approchant très fortement de celui de Photoshop. J’ai également testé une version s’appuyant sur HSV, qui, malgré l’asymétrie des valeurs donne des résultats sympathiques, généralement plus lumineux, et dont les couleurs chaudes sont moins ternes (proche du résultat obtenu dans Artweaver).
Exemple :
» Intégration dans Flash
Pour utiliser notre nouveau mode de fusion dans le Flash Player 10, c’est assez simple.
On embarque les deux images (arriere plan + premier plan), ainsi que le bytecode du kernel :
public class BlendShader extends Sprite
{
[Embed(source='../assets/img/a1.png')]
private static var Background:Class;
[Embed(source='../assets/img/bluePurple.jpg')]
private static var Foreground:Class;
[Embed(source="colorBlendMode/ColorBlendMode.pbj",
mimeType="application/octet-stream")]
private static var ShaderByteCode:Class;
…
On ajoute ensuite les deux images à la display list :
public function BlendShader()
{
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
var background:Bitmap = new Background() as Bitmap;
addChild(background);
var foreground:Bitmap = new Foreground() as Bitmap;
addChild(foreground);
...
On crée le shader du mode de fusion et on l’applique à l’image au premier plan:
var blendShader:Shader = new Shader(new ShaderByteCode()); foreground.blendMode = BlendMode.SHADER; foreground.blendShader = blendShader;
Remarque :
Il est possible de créer des mode de fusion avec plus de deux entrées. Dans ce cas, ces entrées supplémentaires ne doivent pas se trouver aux indexs 0 et 1, ceux-ci étant automatiquement défini lors de l’application du mode de fusion. On peut vérifier l’index d’un input ainsi :
shader.data.myThirdInput.index;
où myThirdInput est le nom de l’input tel que vous l’avez défini dans votre kernel Pixel Bender.
Le shader crée automatiquement les instances de ses input et paramètres à partir du bytecode chargé. Ainsi, lorsqu’on veut affecter la valeur d’un input supplémentaire, on ne crée pas d’instance de ShaderInput qu’on affecte au shader ; on affecte directement la valeur de l’input à celle existante :
Sinon, on reçoit l’exception de type ArgumentError nous spécifiant que le type d’entrée est incompatible.
// don't do that var shaderInput:ShaderInput = new ShaderInput(); shaderInput.input = myBitmapData; shader.data.myThirdInput = shaderInput; myDisplayObject.blendShader = shader; // throws an ArgumentError // instead, do like this shader.data.myThirdInput.input = myBitmapData; myDisplayObject.blendShader = shader; // it's ok
Ok. Il ne reste qu’à compiler et lancer tout ça. (mêmes images d’entrées que précédemment)
Vous devez vous rendre compte que ça ne colle pas :). On obtient un rouge vif à la place du cyan. Le violet n’est pas correct non plus.
Etant donné que l’algo est correct dans Pixel Bender, je penche soit pour des soucis d’interprétation du bytecode hydra dans le flash player 10, soit pour un typage des variables erroné dans mon code entraînant des erreurs dans flash et pas dans Pixel Bender. Ce souci n’est pas spécifique aux blend modes : j’ai d’autres filtres utilisant HSL/HSV qui donnent la même incohérence entre fp10 et Pixel Bender. En attendant confirmation de tout cela, je préfère ne pas proposer le code du kernel du Color blendmode et vous le garde au chaud pour plus tard :).
09/09/08 à 08:09:20 





[...] parlais déjà dans un post précédent “à l’aube” de Pixel Bender, mais le rendu était différent entre Pixel Bender [...]
Pingback par public class Lunar-Dev extends Blog { » Pixel Bender : BlendMode Color for Flash Player 10 | Blog d’un développeur Actionscript 3 - Flex - AIR — 28 f 2009 #