2009-10-27 6 views
0

J'essaie d'utiliser la classe WPF WriteableBitmap pour permettre à mon application d'appliquer un masque d'opacité à une image. Fondamentalement, j'ai un rectangle bleu comme une image, et une autre image rectangle 100% transparent vert sur le dessus du bleu. Lorsque l'utilisateur déplace sa souris sur l'image verte (transparente), je souhaite appliquer le masque d'opacité (en utilisant peut-être une ellipse simple) de façon à ce qu'il apparaisse comme une lueur verte.WPF WriteableBitmap et les effets

Im font volontairement pas est XAML et les effets standards WPF parce que je vraiment besoin d'être super et je performant éventuellement échanger sur l'ellipse avec un blob plus avancée ...

Toutes les pensées ??

Merci!

Répondre

2

Je suis désolé, je ne comprends pas très bien vos intentions. Peut-être que si je pouvais voir l'image, je pourrais répondre correctement dès le début, mais voici ma première réponse, peut-être fausse.

Si vous dites super-performant, vous voulez probablement regarder les pixel shaders. Ils sont traités par G PU, pris en charge par WPF sous la forme d'un effet personnalisé et sont faciles à mettre en œuvre. Vous pouvez également appliquer des shaders à la lecture de vidéos, alors que c'est difficile à faire avec WritableBitmap.

Pour écrire un pixel shader, vous devez avoir FX Compiler (fxc.exe) de DirectX SDK et Shazzam tool - compilateur WYSIWYG WPF Shaders de Walt Ritscher.

Lorsque vous les obtenez à la fois, allez-y et essayez le code HLSL suivant

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; 
} 

Cela vous donne l'effet suivant 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); 
      } 
     } 
    } 
} 

Maintenant, vous pouvez suivre la position de la souris, et ensemble correspondant propriétés de votre effet pour déclencher des modifications. Une chose à noter ici: X et Y dans le code HLSL sont compris entre 0 et 1. Vous devrez donc convertir les coordonnées réelles en pourcentages, avant de les transmettre au shader.

choses à en savoir plus sur les pixel shaders et WPF:

Hope this helps :)

+0

Hey merci Anvaka, thats une excellente réponse! Je vais essayer et lire un peu plus, si cela ne vous dérange pas, je vais passer à la prochaine partie de la question. Im après l'effet où je veux une lueur autour de la souris, mais je veux que cette lueur soit un masque d'opacité sur une image devant mon image de fond (comme une texture fixe qui est exposée lorsque vous déplacez la souris sur elle). Cela peut-il être réalisé en utilisant des pixel shaders? – Mark

+0

Bien sûr, vous pouvez le faire. Vous pouvez modifier le canal alpha de la couleur comme vous le souhaitez à partir du code HLSL. C'est aussi simple que de définir finalColor.a = 0.75; Cela définit 75% en alpha. – Anvaka

+0

génial! merci pour l'aide, cela a été incroyablement intéressant pour moi! – Mark

Questions connexes