Blurred image after applying the shader effect

I came across strange pixel shader behavior in WPF.

This problem is 100% reproducible, so I wrote a small demo program. You can download the source code here .

The root of all evil is a tiny class called MyFrameworkElement:

internal sealed class MyFrameworkElement : FrameworkElement
{
    public double EndX
    {
        get
        {
            return (double)this.GetValue(MyFrameworkElement.EndXProperty);
        }
        set
        {
            this.SetValue(MyFrameworkElement.EndXProperty, value);
        }
    }

    public static readonly DependencyProperty EndXProperty =
        DependencyProperty.Register("EndX",
            typeof(double),
            typeof(MyFrameworkElement),
            new FrameworkPropertyMetadata(0d, FrameworkPropertyMetadataOptions.AffectsRender));

    protected override void OnRender(DrawingContext dc)
    {
        dc.DrawLine(new Pen(Brushes.Red, 2), new Point(0, 0), new Point(this.EndX, 100));
        dc.DrawLine(new Pen(Brushes.Green, 3), new Point(10, 300), new Point(200, 10));
    }
}

As you can see, this framework element displays 2 lines: the bottom line has constant coordinates, but the top line depends on the EndX dependency property.

So this framework element is an object for the pixel shader effect. For simplicity, I use the grayscale effect found here . So I applied GrayscaleEffect to MyFrameworkElement. You can see the result, it looks beautiful.

EndX.

, !

, , .

- , ? , ?

+5
4

, .

, .

, , :

Geometry clip = new RectangleGeometry(new Rect(0,0,this.ActualWidth, this.ActualHeight));

dc.PushClip(clip);

dc.DrawLine(new Pen(Brushes.Red, 2), new Point(0, 0), new Point(this.EndX, 100));
dc.DrawLine(new Pen(Brushes.Green, 3), new Point(200, 10), new Point(10, 300));

dc.Pop();

UPDATE:

, , ( )... .... .

, ( , ).

.NET 4 , ... , Fant... , , .

http://10rem.net/blog/2010/05/16/more-on-image-resizing-in-net-4-vs-net-35sp1-bilinear-vs-fant

UPDATE2:

, .

Windows Performance Toolkit/Suite ( Windows SDK), , , , . , , ... .

enter image description here

UPDATE3:

"Software Renderer" (Tier 0), , - ... , / . , Bilinear.

RenderOptions.SetBitmapScalingMode Fant, -, ( , , ).

Application_Startup, :

RenderOptions.ProcessRenderMode = RenderMode.SoftwareOnly;
+1

, , .

, , . 8198 * 8192. "", , 16384. , virtualBox 16384 * 16384. . .

, WPF , . , , , , .

: : with shader applied

, , .

+1

, ! , WCF PresentationCore, , BlurEffect . , BlurEffect Effect.GetRenderBounds, GrayscaleEffect. , GrayscaleEffect PresentationCore v 3.0.0, Effect GetRenderBound.

, 3- 4- WPF. :

  • GrayscaleEffect - 4.0.0.
  • 3. *.
  • GrayscaleEffect, , GrayscaleEffect, (v4) .

, .

+1

, , Custom ShaderEffect.

OP , ShaderEffects WPFShadersLibrary , .

What I noticed is that this image has shifted by a tiny bit, which led to "pixel splitting", so I created two new properties for the selected ShaderEffect: XOffset and YOffset and applied them in HLSL (see code below), and then bound them for sliders in XAML:

float2 newPos;
newPos.x = uv.x + offsetX;
newPos.y = uv.y + offsetY;

Then I experimented with some arbitrary offsets and was able to re-align the image. There is still some minimal blur (or loss in detail), but the result was noticeably better.

The problem with this solution at present is that I don’t know how to predict the offset depending on the resolution or size of the window.

0
source

All Articles