WPF WriteableBitmapとエフェクト
-
06-07-2019 - |
質問
WPF WriteableBitmapクラスを使用して、アプリケーションが画像に不透明度マスクを適用できるようにすることを検討しています。
基本的に、画像として青い長方形があり、その上に100%透明な緑色の長方形の画像がもう1つあります。
ユーザーが緑色(透明)の画像の上にマウスを移動したときに、不透明なマスク(おそらく単純な楕円を使用)を適用して、緑色の輝きが発生しているようにします。
XAMLおよび標準のWPFエフェクトは、意図的にこれを行わないのは、本当に優れたパフォーマンスが必要であり、最終的に楕円をより高度なblobと交換するためです...
考えはありますか?
ありがとう!
解決
申し訳ありませんが、あなたの意図はよくわかりません。画像を見ることができれば、最初から正しく答えることができたかもしれませんが、ここに私の最初の間違った答えがあります。
スーパーパフォーマンスと言う場合、ピクセルシェーダーを確認する必要があります。これらは G PUによって処理され、カスタムエフェクトの形式でWPFによってサポートされ、実装が簡単です。また、ビデオの再生にシェーダーを適用できますが、WritableBitmapを使用するのは困難です。
ピクセルシェーダーを作成するには、 DirectX SDK および Shazzamツール-Walt RitscherによるWYSIWYG WPF Shadersコンパイラ。
両方を入手したら、次のHLSLコードを試してください
float X : register(C0); // Mouse cursor X position
float Y : register(C1); // Mouse cursor Y position
float4 Color : register(C2); // Mask color
float R : register(C3); // Sensitive circle radius.
sampler2D implicitInputSampler : register(S0);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 finalColor = tex2D(implicitInputSampler, uv);
if ( (uv.x - X) * (uv.x - X) + (uv.y - Y) * (uv.y - Y) < R*R)
{
finalColor = Color; // Blend/Change/Mask it as you wish here.
}
return finalColor;
}
これにより、次のC#効果が得られます。
namespace Shazzam.Shaders {
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Effects;
public class AutoGenShaderEffect : ShaderEffect {
public static DependencyProperty InputProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(AutoGenShaderEffect), 0);
public static DependencyProperty XProperty = DependencyProperty.Register("X", typeof(double), typeof(AutoGenShaderEffect), new System.Windows.UIPropertyMetadata(new double(), PixelShaderConstantCallback(0)));
public static DependencyProperty YProperty = DependencyProperty.Register("Y", typeof(double), typeof(AutoGenShaderEffect), new System.Windows.UIPropertyMetadata(new double(), PixelShaderConstantCallback(1)));
public static DependencyProperty ColorProperty = DependencyProperty.Register("Color", typeof(System.Windows.Media.Color), typeof(AutoGenShaderEffect), new System.Windows.UIPropertyMetadata(new System.Windows.Media.Color(), PixelShaderConstantCallback(2)));
public static DependencyProperty RProperty = DependencyProperty.Register("R", typeof(double), typeof(AutoGenShaderEffect), new System.Windows.UIPropertyMetadata(new double(), PixelShaderConstantCallback(3)));
public AutoGenShaderEffect(PixelShader shader) {
// Note: for your project you must decide how to use the generated ShaderEffect class (Choose A or B below).
// A: Comment out the following line if you are not passing in the shader and remove the shader parameter from the constructor
PixelShader = shader;
// B: Uncomment the following two lines - which load the *.ps file
// Uri u = new Uri(@"pack://application:,,,/glow.ps");
// PixelShader = new PixelShader() { UriSource = u };
// Must initialize each DependencyProperty that's affliated with a shader register
// Ensures the shader initializes to the proper default value.
this.UpdateShaderValue(InputProperty);
this.UpdateShaderValue(XProperty);
this.UpdateShaderValue(YProperty);
this.UpdateShaderValue(ColorProperty);
this.UpdateShaderValue(RProperty);
}
public virtual System.Windows.Media.Brush Input {
get {
return ((System.Windows.Media.Brush)(GetValue(InputProperty)));
}
set {
SetValue(InputProperty, value);
}
}
public virtual double X {
get {
return ((double)(GetValue(XProperty)));
}
set {
SetValue(XProperty, value);
}
}
public virtual double Y {
get {
return ((double)(GetValue(YProperty)));
}
set {
SetValue(YProperty, value);
}
}
public virtual System.Windows.Media.Color Color {
get {
return ((System.Windows.Media.Color)(GetValue(ColorProperty)));
}
set {
SetValue(ColorProperty, value);
}
}
public virtual double R {
get {
return ((double)(GetValue(RProperty)));
}
set {
SetValue(RProperty, value);
}
}
}
}
マウスの位置を追跡し、エフェクトの対応するプロパティを設定して変更をトリガーできるようになりました。ここで注意すべき点が1つあります。HLSLコードのXとYの範囲は0〜1です。したがって、シェーダーに渡す前に、実際の座標をパーセンテージに変換する必要があります。
ピクセルシェーダーとWPFの詳細:
これが役立つことを願って:)