2009-10-27 4 views
0

Я пытаюсь изучить класс WPable WriteableBitmap, чтобы мое приложение применило маску непрозрачности к изображению.WPF WriteableBitmap и эффекты

В принципе у меня есть синий прямоугольник в качестве изображения, а еще 100% прозрачный зеленый прямоугольник на верхней части синего.

Когда пользователь наводит указатель мыши на зеленый (прозрачный) образ, я хочу применить маску непрозрачности (возможно, используя простой эллипс), чтобы она выглядела как зеленое свечение.

Im намеренно не делает это XAML и стандартные эффекты WPF, потому что мне действительно нужно, чтобы это было супер производительным, и я в конечном итоге поменять эллипс с более заранее сгустка ...

Любые мысли ??

Спасибо!

ответ

2

Извините, я не совсем понимаю ваши намерения. Возможно, если бы я мог видеть изображение, я мог бы правильно ответить с самого начала, но вот мой первый, может быть, неправильный ответ.

Если вы говорите супер-исполнитель, вы, вероятно, захотите взглянуть на пиксельные шейдеры. Они обрабатываются G PU, поддерживаемые WPF в форме пользовательского эффекта и просты в реализации. Также вы можете использовать шейдеры для воспроизведения видео, в то время как это трудно сделать с WritableBitmap.

Чтобы написать пиксельный шейдер, вам необходимо иметь компилятор FX (fxc.exe) от DirectX SDK и Shazzam tool - компилятор WYSIWYG WPF Shaders от Walt Ritscher.

Когда вы их обоих, идти вперед и попробовать следующий код 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); 
      } 
     } 
    } 
} 

Теперь вы можете отслеживать положение курсора мыши, и установить соответствующие свойства вашего эффекта для инициирования изменений. Здесь следует отметить следующее: X и Y в коде HLSL варьируются от 0 до 1. Таким образом, вам нужно будет преобразовать фактические координаты в проценты, прежде чем передавать их в шейдер.

вещи, чтобы узнать больше о пиксельных шейдеров и WPF:

Надеется, что это помогает :)

+0

Эй спасибо Anvaka, то большой ответ! Если вы не возражаете, я приготовлю это, и я прочитаю немного больше, но я перейду к следующей части вопроса. Im после эффекта, когда я хочу свечение вокруг мыши, но я хочу, чтобы это свечение было маской непрозрачности на изображении перед моим фоновым изображением (например, фиксированной текстурой, которая отображается при перемещении мыши над ней). Может ли это быть достигнуто с использованием пиксельных шейдеров? – Mark

+0

Конечно, вы можете это сделать. Вы можете изменить альфа-канал цвета, как вы хотите, из кода HLSL. Это так же просто, как установка finalColor.a = 0.75; Это устанавливает 75% в альфа. – Anvaka

+0

потрясающий! спасибо за помощь, это было невероятно интересно для меня! – Mark