سؤال

أحاول النظر في استخدام فئة WPF WriteableBitmap للسماح لتطبيقي بتطبيق قناع العتامة على الصورة.

في الأساس، لدي مستطيل أزرق كصورة، وصورة أخرى مستطيلة خضراء شفافة بنسبة 100% أعلى الصورة الزرقاء.

عندما يقوم المستخدم بتحريك الماوس فوق الصورة الخضراء (الشفافة)، أريد تطبيق قناع العتامة (ربما باستخدام شكل بيضاوي بسيط) بحيث يبدو وكأنه يحدث توهج أخضر.

أنا لا أفعل هذا عمدًا بتأثيرات XAML وتأثيرات WPF القياسية لأنني أحتاج حقًا إلى أن تكون فائقة الأداء وسأقوم في النهاية باستبدال الشكل الناقص بنقطة أكثر تقدمًا...

أي أفكار؟؟

شكرًا!

هل كانت مفيدة؟

المحلول

أنا آسف، أنا لا أفهم نواياك تماما.ربما لو تمكنت من رؤية الصورة، لأتمكنت من الإجابة بشكل صحيح منذ البداية، ولكن هذه هي إجابتي الأولى التي ربما تكون خاطئة.

إذا قلت الأداء الفائق، فربما تريد إلقاء نظرة على تظليل البكسل.تتم معالجتها بواسطة زPU، مدعوم بـ WPF في شكل تأثير مخصص وسهل التنفيذ.يمكنك أيضًا تطبيق التظليل على تشغيل الفيديو، بينما يصعب القيام بذلك باستخدام WritableBitmap.

لكتابة تظليل بكسل، يجب أن يكون لديك مترجم FX (fxc.exe) من ديريكتكس SDK و أداة شزام - مترجم WYSIWYG WPF Shaders بواسطة والت ريتشر.

عندما تحصل على كليهما، تابع وجرب رمز 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:

أتمنى أن يساعدك هذا :)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top