WPF WriteableBitmap и эффекты - PullRequest
       16

WPF WriteableBitmap и эффекты

0 голосов
/ 28 октября 2009

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

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

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

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

Есть мысли ??

Спасибо!

1 Ответ

2 голосов
/ 28 октября 2009

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

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

Чтобы написать пиксельный шейдер, вам нужен FX Compiler (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:

Надеюсь, это поможет:)

...