以前紹介したバンプマッピングのPixel BenderをFlashで使おうとしてみたのですが、なぜかうまくいきませんでした・・・。
真っ黒でなにもでなかったり、明らかにおかしな色になってしまったのです。その際、色々試した結果をここでちょっと報告したいと思います。
まずは、上の画像がいったいなんなのかを説明します。
outCoord()の値を可視化する
上の画像は、outCoord()の値からx座標の値をR成分に、y座標の値をG成分にしたものです。
これには、以下のPixel Benderのコードを使っています。
<languageVersion : 1.0;> kernel SampleFilter < namespace : "jp.flup"; vendor : "Flup Inc."; version : 1; description : "outCoord test filter"; > { input image4 src; output pixel4 dst; void evaluatePixel() { dst.r = (outCoord().x-100.0)/200.0; dst.g = (100.0-outCoord().y)/200.0; dst.b = 0.0; dst.a = 1.0; } }
これは、Pixel Bender Toolkit で生成した画像を出力したもので、Flashはこの時点では関係ありません。
ShaderFilterの適用
次に、ShaderFilterで単一の入力イメージに対してフィルタを適用してみます。これはActionScriptになります。
package { import flash.display.*; import flash.filters.*; public class filter_test extends Sprite { [Embed(source="test.pbj", mimeType="application/octet-stream")] private static var ShaderByteCode:Class; [Embed(source="dummy.jpg")] private static var Image1:Class; private var bmp1:Bitmap; public function filter_test() { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; bmp1 = new Image1() as Bitmap; addChild(bmp1); var shader:Shader = new Shader(new ShaderByteCode()); bmp1.filters = [new ShaderFilter(shader)]; } } }
実行すると、左のようになります。これは実際作成したswfファイルになっています。
最初の生成画像と全く同じになっていることが分かります。
blendShaderにすると・・・
次に、2枚の画像に対してブレンドモードでShaderを適用してみます。フィルタも若干(といっても入力を増やすだけですが)変更します。
<languageVersion : 1.0;> kernel SampleFilter < namespace : "jp.flup"; vendor : "Flup Inc."; version : 1; description : "outCoord test filter"; > { input image4 src; input image4 src2; output pixel4 dst; void evaluatePixel() { dst.r = (outCoord().x-100.0)/200.0; dst.g = (100.0-outCoord().y)/200.0; dst.b = 0.0; dst.a = 1.0; } }
このようにして、入力画像を2つ使うことができるようにします(実際使ってはいませんが・・)。
次に、ActionScript側も入力画像を2つ使ってblendShaderを指定するように変更します。
package { import flash.display.*; import flash.filters.*; public class filter_test extends Sprite { [Embed(source="test.pbj", mimeType="application/octet-stream")] private static var ShaderByteCode:Class; [Embed(source="dummy.jpg")] private static var Image1:Class; private var bmp1:Bitmap; private var bmp2:Bitmap; public function filter_test() { stage.align = StageAlign.TOP_LEFT; stage.scaleMode = StageScaleMode.NO_SCALE; bmp1 = new Image1() as Bitmap; addChild(bmp1); bmp2 = new Image1() as Bitmap; addChild(bmp2); var shader:Shader = new Shader(new ShaderByteCode()); bmp2.blendMode = BlendMode.SHADER; bmp2.blendShader = shader; } } }
実際には入力画像はつかっておらず、outCoord()の値のみで出力画像を生成しているので、結果は以前と変わらないはずですが・・・。
このように、緑色のベタ塗りになってしまいました・・・。最初の画像と異なっているのは一目瞭然ですね。
どういうことなのか?
これが仕様なのかバグなのかは私には分かりませんし、私の方法が悪いのかもしれませんが、blendShaderでpbjを使うと、outCoord()が出力ピクセル毎に(ほぼ)同じ値になってしまうようです。ほぼ、と書いたのは全く同じかどうか確認することができず、座標系が異なっている可能性もあるので・・。
ただ、Pixel Benderでは1ピクセルにつき座標を1増減するつもりで記述している(し、Pixel Bender Toolkitではそれで問題なく動作を確認している)ので、outCoord()の値によってピクセル値を制御することをblendShaderでやりたい場合は今回のような問題が発生しそうです。
一体これはどういうことなんでしょうね?どなたか原因が分かる方いらっしゃったらお教えください・・・。