Domanda

Sto cercando di esaminare l'uso della classe WriteableBitmap di WPF per consentire alla mia applicazione di applicare una maschera di opacità a un'immagine.

Fondamentalmente ho un rettangolo blu come immagine e un'altra immagine di rettangolo verde trasparente al 100% sopra quella blu.

Quando l'utente sposta il mouse sull'immagine verde (trasparente), voglio applicare la maschera di opacità (forse usando una semplice ellisse) in modo che sembri che si stia verificando un bagliore verde.

Non sto intenzionalmente facendo questo è XAML ed effetti WPF standard perché ho davvero bisogno che sia super performante e alla fine cambierò l'ellisse con un blob più avanzato ...

Qualche pensiero ??

Grazie!

È stato utile?

Soluzione

Mi dispiace, non capisco bene le tue intenzioni. Forse se potessi vedere l'immagine, potrei rispondere correttamente dall'inizio, ma ecco la mia prima risposta forse sbagliata.

Se dici super performante, probabilmente vuoi guardare pixel shader. Sono elaborati da G PU, supportati da WPF in una forma di effetto personalizzato e sono facili da implementare. Inoltre puoi applicare shader alla riproduzione di video, mentre è difficile avere a che fare con WritableBitmap.

Per scrivere un pixel shader, devi avere FX Compiler (fxc.exe) da DirectX SDK e strumento Shazzam - WYSIWYG WPF Shaders compilatore di Walt Ritscher.

Quando li ottieni entrambi, vai avanti e prova il seguente codice 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;
}

Questo ti dà il seguente effetto 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);
            }
        }
    }
}

Ora puoi tenere traccia della posizione del mouse e impostare le proprietà corrispondenti dell'effetto per attivare le modifiche. Una cosa da notare qui: X e Y nel codice HLSL vanno da 0 a 1. Quindi dovrai convertire le coordinate effettive in percentuali, prima di passarle allo shader.

Cose da leggere di più su pixel shader e WPF:

Spero che questo aiuti :)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top