GPU Effects & Blurry Text

About a month ago, I ran into a weird issue … that literally confounded me … and irked me to no end. The issue was that whenever I applied a drop shadow effect to a border that contained text … the text would blur a little bit.

So, if I did the following:

<Window
    x:Class="EffectsAndBlurryText.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Effects and Blurry Text (Good)"
    Height="300"
    Width="500"
>
    <Grid>
        <Border
            Margin="20"
            Background="White"
            BorderBrush="DarkBlue"
            BorderThickness="3"
            CornerRadius="25"
        >
            <TextBlock
                Text="This text is not blurry."
                FontSize="24"
                TextWrapping="Wrap"
                Foreground="DarkBlue"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
            />
        </Border>
    </Grid>
</Window>

I would get nice looking text:

ClearText

 

But if I added the drop shadow effect:

<Window
    x:Class="EffectsAndBlurryText.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Effects and Blurry Text (Bad)"
    Height="300"
    Width="500"
>
    <Grid>
        <Border
            Margin="20"
            Background="White"
            BorderBrush="DarkBlue"
            BorderThickness="3"
            CornerRadius="25"
        >
            <Border.Effect>
                <DropShadowEffect Color="DarkGray"/>
            </Border.Effect>
            <TextBlock
                Text="Why, oh, why is this text blurry?"
                FontSize="24"
                TextWrapping="Wrap"
                Foreground="DarkBlue"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
            />
        </Border>
    </Grid>
</Window>

I would get blurry text (click on the image to better see the issue):

BlurryText

 

So, how can we get around this annoying issue? Here is what I came up with: wrap the Border in a Grid and put another Border underneath the one you had originally. Put the BorderBrush and Background on the new Border and apply the drop shadow effect there instead.

Here is the xaml:

<Window
    x:Class="EffectsAndBlurryText.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Effects and Blurry Text (Fixed)"
    Height="300"
    Width="500"
>
    <Grid>
        <Border
            Margin="20"
            BorderThickness="3"
            CornerRadius="25"
            Background="White"
            BorderBrush="DarkBlue"
        >
            <Border.Effect>
                <DropShadowEffect Color="DarkGray"/>
            </Border.Effect>
        </Border>
        <Border
            Margin="20"
            BorderThickness="3"
            CornerRadius="25"
        >
            <TextBlock
                Text="Ah, now, the text is not blurry."
                FontSize="24"
                TextWrapping="Wrap"
                Foreground="DarkBlue"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
            />
        </Border>
    </Grid>
</Window>

 

I would love to hear if anyone has any better ideas to solve this … or just if others have noticed it as well.

I hope this helps someone … I know at least one other person has run into this. See his January 28th blog entry.

 

Note: this issue seems intermittent at times. In particular, sometimes you can see it only in the designer (both Visual Studio and Blend). However, that being said, it is not just in the designer … I have seen it in running executables.

Update 1: Others seem to have run into this issue as well. There is a current forum post about this, in fact.

Update 2: Initially, I thought this was an NVIDIA driver issue, but others have seen it on ATI cards and Intel integrated solutions. Walt Ritscher says its a known issue. I wonder if it is related to another issue that I’ve had.

13 thoughts on “GPU Effects & Blurry Text”

  1. To run an effect on a sub-tree (graph), WPF renders the effect into a DX texture. The texture format we use is PARGB. We need an alpha channel in the texture because anything in WPF can be translucent. Note that there is only a single alpha channel and it is shared between all the color channels. Cleartype on the other hand requires an alpha channel per color channel. Since there is only one alpha channel for all color channels in the texture, we disable Cleartype and instead render text using a traditional gray scale anti-aliasing method. (There are ways to fix this, either by restricting the scenario or introducing an alpha channel per color channel. Unfortunately this has other performance consequences). AA text doesn’t look as good as Cleartype to most people which is part of the reason the text doesn’t look as good with the drop shadow on the border.
    After the texture has been produced, we draw the texture into the destination buffer using the drop shadow shader. If things don’t align properly, the texture will get filtered using bilinear filtering which will add additional blurriness. We could have forced everything to align, but that has other limitations.
    We are considering for a future release to give you the choice of aligning to pixels or getting precise positioning.
    Even if we offer the precise pixel positing as an option, you still will not get Cleartype below an effect. Therefore the work-around you describe is probably the best solution as it gives you a drop shadow and retains Cleartype. In future release of our platform we might make it easier to achieve your effect.

  2. Thanks Gerhard.

    Also, can you explain why this issue seems to be intermittent at times?

    I mean, at times, it shows up in the designer surfaces only … other times it shows up in the running executable only … other times it shows up in both places.

    Do you think this issues is related at all to losing anti-aliasing on a rotated border (see link in my Update 2 section).

  3. Update: it looks as if the blurry text issue is different from losing anti-aliasing on a rotated border. Brendan Clark of Microsoft responded here and here about the latter issue.

  4. If the effect’s input texture pixels align with the destination pixels, you won’t see the bilinear filtering artifacts because bilinear filtering won’t do any averaging of pixels. You can observe the difference by writing a simple identity (pass through) shader effect and comparing the use of Bilinear and NearestNeighbor filtering on the implicit input while moving the element with the effect by sub-pixel offsets.

  5. This looks like a good solution, but I am actually trying to have my text drop a shadow, not the border around it.

    I figured I could use a copy of the text created with a VisualBrush as a background to the actual text and drop a shadow from that background copy, but I am having some issues with positioning.

  6. @xyzzer
    Actually, it turned out that a VisualBrush based on a frameless Border with a TextBlock inside will only use the TextBlock as its dimensions, so the fix for the alignment issue … was to use a Border with a BorderThickness of 1, but BorderBrush set to Transparent.

    The text is a bit stronger with the blurred version in the background VisualBrush, but it is still better and will do for now. It could possibly be improved if I used a custom pixel shader instead of using DropShadowEffect.

    I still think it is a bug in WPF.

  7. @Chris, heh heh, glad my post was helpful!

    Yeah, there is always something new I’m learning about WPF … even now, almost 4 years after first diving into this technology. 🙂

Leave a Reply