2009-10-27 73 views
0

我试图调查使用WPF WriteableBitmap类,以允许我的应用程序将不透明蒙版应用于图像。WPF WriteableBitmap和效果

基本上我有一个蓝色矩形作为图像,另一个100%透明的绿色矩形图像在蓝色的顶部。

当用户将他们的鼠标移动到绿色(透明)图像上时,我想应用不透明蒙版(可能使用简单的椭圆),使其看起来像绿色发光。

林故意没有这样做,这是XAML和WPF标准的影响,因为我真的需要它是超高性能和我最终会掉出椭圆用更先进的斑点......

有什么想法?

谢谢!

回答

2

对不起,我不太明白你的意图。也许如果我能看到图像,我可以从头开始正确回答,但这是我的第一个也许是错误的答案。

如果你说super-performant,你可能想看像素着色器。它们由G PU处理,由WPF以自定义效果的形式支持,易于实现。您也可以将着色器应用于播放视频,而使用WritableBitmap很难做到这一点。

要编写像素着色器,您需要使用DirectX SDKShazzam tool的FX编译器(fxc.exe) - 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); 
      } 
     } 
    } 
} 

现在您可以跟踪鼠标的位置,并设置相应的您的效果属性触发更改。有一点需要注意:HLSL代码中的X和Y的范围是从0到1.因此,在将实际坐标传递给着色器之前,必须将实际坐标转换为百分比。

观光阅读更多关于像素着色器和WPF:

希望这有助于:)

+0

嘿感谢Anvaka,那是一个伟大的答案!如果你不介意的话,我会放弃一些,多读一些,我会扩展到问题的下一部分。我想要在鼠标周围发光的效果之后,但我希望这种发光成为背景图像前面的图像上的不透明蒙版(就像在将鼠标移到它上面时暴露的固定纹理一样)。这可以使用像素着色器来实现吗? – Mark 2009-10-28 01:10:34

+0

当然,你可以做到这一点。您可以根据您希望从HLSL代码修改颜色的Alpha通道。这与设置finalColor.a = 0.75一样简单;这将75%设置为alpha。 – Anvaka 2009-10-28 17:04:13

+0

太棒了!感谢您的帮助,这对我来说非常有趣! – Mark 2009-10-29 00:26:08