Top > Programming > .NetFramework > WPF > HowToUsePixelShader_CustomEffect
Last-modified: Tue, 09 Oct 2012 08:17:05 JST
Counter:2202 Today:1 Yesterday:2 Online:6
このエントリーをはてなブックマークに追加

PixelShaderを使ったCustomEffect

Now Editing!

About

 WPFではHLSLを使って記述したPixelShaderをCustomEffectとして適用する事ができます。端的にいえば、PixelShaderを使う事で、GPUを介して画像(UI)に特殊な効果を施すことができる、ということです。

How to

 利用するPixelShaderはあらかじめコンパイルされている必要があります。つまりHLSLを用いて記述された「.fxファイル」のままではWPFからその関数(PixelShader)を呼び出して実行する事ができないということです。シェーダのコンパイルについては次のページを参照されたい。

シェーダにパラメータを渡す

テクスチャ(sampler)

 参照用テクスチャの情報を与える場合などは、

        /// <summary>
        /// Shader内で参照するテクスチャ(Sampler)を設定するためのプロパティ。
        /// </summary>
        public Brush RefTexture
        {
            get { return (Brush)GetValue(Property_Tex2d_RefTexture); }
            set { SetValue(Property_Tex2d_RefTexture, value); }
        }

        public static readonly DependencyProperty Property_Tex2d_RefTexture
            = ShaderEffect.RegisterPixelShaderSamplerProperty
            ("RefTexture",//シェーダ内でのSampler(グローバル変数)の名前
            typeof(SimpleCustomShader),//このクラスの名前
            1,//シェーダ内でのSamplerのレジスタ番号
            SamplingMode.NearestNeighbor//シェーダ内でのSampling方法
            );

制限

この内容はHLSLやその他の環境でシェーダを利用したことがある方に向けられています

 WPFでPixelShaderを利用する場合には、サンプラ(sampler)に直接値を引き渡すためか、シェーダ内で定義した「sampler_state」は全て適用されません(≒sampler_stateで参照するテクスチャを定義しない)。つまり他のDirectXで利用されていたPixelShaderなどを使いまわさない場合は、シェーダ内でTextureを用意して、「sampler_state」から参照するなどの記述が一切必要ないわけです。使い回しによって「sampler_state」が記述されている場合でも問題なく動作しますが、sampler_stateに設定した全てのパラメータは有効とならない点に注意する必要があります。

 サンプリング方法に関しては、DependencyPropertyの「SamplingMode」でのみ設定できる様です。しかしここには「NearestNeighbor」か「BiLinear」しかありません。「MagFilter = Point;」などの設定も無効化されるわけですから、事実上「ドットバイドット(dot by dot)≒ピクセル単位」でサンプリングする事ができないことになります。出力結果自体はWPFのUI設定でピクセル単位の描画にすることは出来ますが、サンプリング自体がどうしようもないので、例えば8bitのファミコンの絵などを出力する場合には、凄くぼやけた絵が得られます。

その他のパラメータ(float)

 floatで表すことのできるパラメータを与える場合などは

        /// <summary>
        /// シェーダ内で参照する任意の値を設定するためのプロパティ。
        /// ここでは赤成分を操作するための値とする。
        /// </summary>
        public float RedValue
        {
            get { return (float)GetValue(Property_RedValue); }
            set { SetValue(Property_RedValue, value); }
        }

        public static readonly DependencyProperty Property_RedValue
            = DependencyProperty.Register(
            "RedValue",//シェーダ内でのグローバル変数の名前
            typeof(float),//与えるデータの型
            typeof(SimpleCustomShader));//,//このクラスの名前

Rendartargetについて

マルチターゲット(パス)レンダリングのためのRendarTargetの指定は、XNAやDirectXでプログラミングするようには出来ないようです(やり方があったら教えて頂きたい)。ただし、空の画像(RendarTarget)に対してレンダリングする、という意味で、1つのRendarTargetを指定するような事は可能です。その場合は、RendarTargetBitmapのインスタンスを利用します。事実上、空のBitmapとして扱う事ができるので、RendarTargetを1つ指定するのと同様の挙動を可能にします。

References