Pregunta

Estoy tratando de analizar el uso de la clase WPF WriteableBitmap para permitir que mi aplicación aplique una máscara de opacidad a una imagen.

Básicamente tengo un rectángulo azul como imagen, y otra imagen de rectángulo verde 100% transparente sobre la parte superior del azul.

Cuando el usuario mueve su mouse sobre la imagen verde (transparente), quiero aplicar la máscara de opacidad (quizás usando una elipse simple) para que parezca que está ocurriendo un resplandor verde.

No estoy haciendo esto a propósito, es XAML y los efectos estándar de WPF porque realmente necesito que sea súper eficiente y eventualmente cambiaré la elipse con un blob más avanzado ...

¿Algún pensamiento?

¡Gracias!

¿Fue útil?

Solución

Lo siento, no entiendo tus intenciones. Tal vez si pudiera ver la imagen, podría responder correctamente desde el principio, pero aquí está mi primera respuesta quizás incorrecta.

Si dice superperformante, probablemente quiera ver los sombreadores de píxeles. Son procesados ??por G PU, soportados por WPF en forma de un efecto personalizado y son fáciles de implementar. También puede aplicar sombreadores a la reproducción de video, mientras que es difícil de hacer con WritableBitmap.

Para escribir un sombreador de píxeles, debe tener el Compilador FX (fxc.exe) de DirectX SDK y Herramienta Shazzam - Compilador WYSIWYG WPF Shaders de Walt Ritscher.

Cuando los obtenga a ambos, continúe y pruebe el siguiente código 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;
}

Esto le brinda el siguiente efecto 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);
            }
        }
    }
}

Ahora puede rastrear la posición del mouse y establecer las propiedades correspondientes de su efecto para activar los cambios. Una cosa a tener en cuenta aquí: X e Y en el código HLSL tienen un rango de 0 a 1. Por lo tanto, deberá convertir las coordenadas reales en porcentajes, antes de pasarlas al sombreador.

Cosas para leer más sobre sombreadores de píxeles y WPF:

Espero que esto ayude :)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top