Pixel BenderのblendShader使用時の謎

result1

以前紹介したバンプマッピングの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でやりたい場合は今回のような問題が発生しそうです。

一体これはどういうことなんでしょうね?どなたか原因が分かる方いらっしゃったらお教えください・・・。

LINEで送る
Pocket

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です