none
WPFで加算半透明を使いたいのですが RRS feed

  • 質問

  • XAMLを用いてアプリケーションのインターフェイスを記述しているのですが、
    透明度を設定する事はできても、加算や乗算などのブレンディングの条件を設定する事はできないのでしょうか。

    XAMLでのポリゴン表示ではEmissive設定があり、
    ポリゴン表示に限っては加算ブレンディングができるようなので、
    ポリゴン以外のXAMLオブジェクトも加算描画を行う方法がないものかと思い調べたのですが、
    どうしても見あたりませんでした・・・。

    ブレンド条件も設定できれば、より凝ったインターフェイスが作れるのではないかと思うのですが・・・。
    方法があれば教えて頂きたく思います。
    よろしくお願いします。
    2009年11月18日 11:26

回答

  • PixelShader を自作してみてはいかがでしょうか。
    ↓こちらにサンプルがありますので改造してみてください。
    http://wpffx.codeplex.com/

    ↓の私の回答にも少し手順を書きました。
    http://social.msdn.microsoft.com/Forums/ja-JP/wpfja/thread/f829869c-44b8-459d-8d2c-b1773d3d5dc5


    サンプルの改造から始めれば、そんなに面倒じゃないです。
    2009年11月18日 16:57
  • 背景と合成する場合は、背景画像(backImage)とその上に描画する画像(bltImage)の二つをシェーダーに渡します。
    ↓のような感じ。

    sampler2D  bltImage: register(S0);
    sampler2D  backImage : register(S1);

    wpffxの、TransitionEffectの方が参考になるかもしれません。
    TransitionEffectは、サンプルテクスチャとして、フェード前とフェード後の2枚の画像を渡します。
    HLSL内で、二つの画像を遷移の進行率(progress)に合わせてブレンドしています。

    背景の上にぴったり重なるように画像を描画するならこれだけでもOKですけど、背景画像内の任意の位置に描画するのであれば、背景に対する相対座標(矩形)を渡す必要がありますね。
    つまり、GDIで言う所のBitBlt()とか、GDI+でいうところのDrawImage()と同じようなパラメーターを、シェーダーに渡す必要があります。

    もしくは、WPF側で前処理して、backImageとしてbltImageの描画位置に相当する部分を切り抜いて渡してあげるとか。
    拡大鏡のサンプルとかを見れば、もしかしたら簡単に任意の場所を切り抜いて渡せるかもしれません。(未確認)


    思ったより、ちょっと面倒でしたね。でもWPFなら、自前でメモリを確保してピクセル演算するより、HLSLで書いちゃった方が楽な気もします。
    2009年11月21日 5:12

すべての返信

  • PixelShader を自作してみてはいかがでしょうか。
    ↓こちらにサンプルがありますので改造してみてください。
    http://wpffx.codeplex.com/

    ↓の私の回答にも少し手順を書きました。
    http://social.msdn.microsoft.com/Forums/ja-JP/wpfja/thread/f829869c-44b8-459d-8d2c-b1773d3d5dc5


    サンプルの改造から始めれば、そんなに面倒じゃないです。
    2009年11月18日 16:57
  • 返信ありがとうございます。

    PixelShader内では背景にある色を取得する事はできないようで、
    DirectXの場合でも背景とのブレンディング条件の設定はシェーダ外で定義するようです。

    Windowsの半透明処理はどのように行われているのか詳細までは知らないのですが、
    DirectXで画面の描画がされてるVista以降でならブレンド条件を設定する方法がどこかにないものかと思うのですが・・・。
    2009年11月21日 0:49
  • 背景と合成する場合は、背景画像(backImage)とその上に描画する画像(bltImage)の二つをシェーダーに渡します。
    ↓のような感じ。

    sampler2D  bltImage: register(S0);
    sampler2D  backImage : register(S1);

    wpffxの、TransitionEffectの方が参考になるかもしれません。
    TransitionEffectは、サンプルテクスチャとして、フェード前とフェード後の2枚の画像を渡します。
    HLSL内で、二つの画像を遷移の進行率(progress)に合わせてブレンドしています。

    背景の上にぴったり重なるように画像を描画するならこれだけでもOKですけど、背景画像内の任意の位置に描画するのであれば、背景に対する相対座標(矩形)を渡す必要がありますね。
    つまり、GDIで言う所のBitBlt()とか、GDI+でいうところのDrawImage()と同じようなパラメーターを、シェーダーに渡す必要があります。

    もしくは、WPF側で前処理して、backImageとしてbltImageの描画位置に相当する部分を切り抜いて渡してあげるとか。
    拡大鏡のサンプルとかを見れば、もしかしたら簡単に任意の場所を切り抜いて渡せるかもしれません。(未確認)


    思ったより、ちょっと面倒でしたね。でもWPFなら、自前でメモリを確保してピクセル演算するより、HLSLで書いちゃった方が楽な気もします。
    2009年11月21日 5:12
  • 返信遅れましてすいません。

    wpfで加算半透明を扱うにはDirectXみたいにパラメータを設定するだけでできる様な物ではできないんですね。
    OSの描画結果をテクスチャ読み込みするとなるとXPでは動かなさそうですね・・・。

    WPFのピクセルシェーダの機能はもう少し勉強してみます。
    貴重な情報、どうもありがとうございました。
    2009年12月2日 5:20
  • フォーラムオペレーターの高橋春樹です。

    NIM5さん、こんにちは。
    アドバイス有難うございました。

    -yuu-さん、初めまして。
    MSDNフォーラムのご利用有難うございます。
    思ったより大変そうですね・・・NIM5さんから頂いた情報を元に、いろいろ試して頂ければと思います。

    今回、問題解決にはなってないようですが、NIM5さんからの投稿が、
    このフォーラムを閲覧している方にとっても、有用な情報になると思いましたので、
    NIM5さんの投稿に、回答マークを付けさせてもらいました。
    この回答マークはスレッドの終了を意味するものでは無いので、
    もし何かしら良い方法がありましたら、スレッドに返信を頂きたいと思います。

    今後ともMSDNフォーラムをよろしくお願いします(^_^)


    マイクロソフト株式会社 フォーラム オペレーター 高橋春樹
    2009年12月10日 7:37
  • こんな記事を見つけました。

    http://www.cplotts.com/2009/11/29/blend-modes-hue-saturation-color-and-luminosity-with-wpf-4-0/

    WPF4.0 で、ShaderModel3.0を使っているようですが、情報として貼っておきます。

    現在のβ版では、プロジェクトにSM3.0とSM2.0を切り替えるオプションがないそうです。
    なので、手動でシェーダーコンパイラ(fxc.exe)を使ってFXファイルをコンパイルする必要があるようです。


    あと、これはWPF3.5SP1のPixelShaderでも同じですが、ハードウェアがPixelShaderに対応していない場合、Effectプロパティはそっくり無視されてしまうようです。
    エラーで止まることもない代わりに、特になにも警告がでることもなくEffectが適用されてない画面が出てくるそうです。

    ShaderModel2.0に対応していないような古いPCでも動作させる必要があるプロジェクトでは注意が必要です。
    2010年1月11日 5:21