Microsoft Communities

Welcome to WindowsClient.net | Sign in | Join

More WPF Custom Effects: Motion Blur and Grayscale Samples

Designing visually appealing UI is now easier and more performant with the addition of custom shader-based effects in WPF for .NET 3.5 Service Pack 1. This article describes the process of creating a simple Greyscale effect and integrating a motion blur effect into a ScrollViewer control.

Before we get started, please familiarize yourself with Greg Schechter’s article on "Writing custom GPU-based Effects for WPF". It's a good introduction to custom shader effects in WPF.

The steps below describe the general process for implementing a custom shader-based effect for use in WPF applications. The download links for the Greyscale and Motion Blur effect sample projects are available at the bottom of this post.

  • Implement the pixel shader for your effect using High Level Shader Language (HLSL) and compile it to generate the pixel shader bytecode that will be loaded in the WPF application. Details on how to compile the shader can be found in Greg Schechter's article or in the next section. Please keep in mind that WPF currently supports Pixel Shader 2.0 only.
  • Subclass the WPF ShaderEffect class and create a PixelShader object that will load the pixel shader file from the previous step. Refer to the GreyEffect.cs or DirectionalBlurEffect.cs files from the sample projects for the source code and the explanation of how this is done.

Compiling a Pixel Shader

Install the DirectX SDK to get the tools necessary to compile HLSL (*.fx) source code to *.ps bytecode that can be loaded using WPF's PixelShader class. Fxc.exe is the HLSL compiler used to compile *.fx HLSL shader files. The following command shows how to compile Greyscale.fx:

> fxc.exe /T ps_2_0 /E PS /FoGreyscale.ps Greyscale.fx

A few notes on each parameter:

/T ps_2_0 Compiles against the ps_2_0 target pixel shader level that WPF currently supports
/E PS Marks the function 'PS' as the entry point
/FoGreyscale.ps Greyscale.fx Takes the file Greyscale.fx as input and output to Greyscale.ps. Note that there is no space between /Fo and Greyscale.ps

The command above can be copied into a batch file to be used in the pre-build event of a Visual Studio project to automate the build process. For example:

> call cd "$(ProjectDir)CustomEffects " && "compile.cmd"

A Sample Greyscale Pixel Shader

Effective interaction with the user is an important factor when designing application UI. One technique is to bring the users' attention to a specific area of the application when an event occurs. This can be done in different ways, one of which is by using a custom effect. The screenshots below illustrate the use of a grayscale effect to deemphasize regions and provide focus on the active portion of the UI where the mouse pointer has moved to.

This is the HLSL used in the above example:

GreyscaleEffectApp\CustomEffects\Source\Greyscale.fx

    sampler2D  ImageSampler : register(S0);  //take ImageSampler from S0 register. 
    // 'uv' vector from TEXCOORD0 semantics is our 
        texture coordinate, two floating point numbers in the range 0-1.
    float4 PS( float2 uv : TEXCOORD) : COLOR
    {
        float4 color = tex2D( ImageSampler, uv); // get the color 
            of texture at the current point
        color.rgb = dot(color.rgb, float3(0.3, 0.59, 0.11)); //compose 
            correct luminance value
        return color;
    }

A Sample Directional Blur Pixel Shader

It can be useful to provide visual feedback as content quickly changes location such as in a ScrollViewer. User may have difficulty tracking the scrolling direction if its content is scrolled to by page using the Page Up or Page Down keys. The scrolling animation will appear less jarring and more natural if a motion blur effect provides a cue of the direction that the page is being transitioned to. The amount of blur is proportional to the distance the content is moved. The following screenshots from the sample project illustrates this effect:

This is the pixel shader HLSL used in the directional blur effect:

MotionBlurEffectApp\CustomEffects\Source\DirectionalBlur.fx

    float Angle : register(C0);  // Defines the blurring direction
    float BlurAmount : register(C1);  // Defines the blurring magnitude
    sampler2D ImageSampler : register(S0);  // Defines the image/texture to be blurred

    float4 PS( float2 uv : TEXCOORD) : COLOR
    {
        float4 output = 0;  // Defines the output color of a pixel
        float2 offset;  // Defines the blurring direction as a direction vector
        int count = 24;  // Defines the number of blurring iterations

        //First compute a direction vector which defines the direction of blurring. 
            This is done using the sincos instruction and the Angle input parameter, 
            and the result is stored in the offset variable. This vector is of unit 
            length. Multiply this unit vector by BlurAmount to adjust its length to 
            reflect the blurring magnitude.
        sincos(Angle, offset.y, offset.x);
        offset *= BlurAmount;

        // To generate the blurred image, we 
            generate multiple copies of the input image, shifted 
            according to the blurring direction vector, and then sum 
            them all up to get the final image.
        for(int i=0; i<count; i++)
             {
                  output += tex2D(ImageSampler, uv - offset * i);
             }
        output /= count; // Normalize the color

        return output;
    }

The custom MotionScrollViewer in the sample project extends the standard ScrollViewer class and applies the above effect to its content. When the user scrolls the content of our ScrollViewer, it computes the direction of movement, amount of blurring, and updates the DirectionalBlur pixel shader parameters. This is done in the MotionBlurScrollViewer.cs file in the sample project.

Sample Projects

These projects require .NET Framework 3.5 SP1:

Greyscale Effect: This is the source code (Visual Studio 2008 solution) and binaries of this sample project can be downloaded from here:

GreyscaleEffectApp_src.zip [GreyscaleEffectApp_src.zip]   GreyscaleEffectApp_bin.zip [GreyscaleEffectApp_bin.zip]

Motion Blur Effect: The source code (Visual Studio 2008 solution) and binaries of this sample project can be downloaded from here:


MotionBlurEffectApp_src.zip [MotionBlurEffectApp_src.zip]   MotionBlurEffectApp_bin.zip [MotionBlurEffectApp_bin.zip]

Contributors

The following team members for Windows Presentation Foundation at Microsoft contributed to this article: Meisam Seyed Aliroteh,a Software Design Engineer in Test, Dennis Cheng, a Lead Software Design Engineer in Test, Tim Cowley, a Software Design Engineer in Test, Greg Schechter, an Architect, and Linzhen Xuan, a Software Design Engineer in Test.

Comments: 2

You must Login to comment.
 

modplug: On November 16, 2008 7:48 AM said:

Very nice control, i have some issues with it though. I put it inside a listbox control template, and made it parent of a itemscontrol. None of the items show up in the scroller, any ideas why?

 
 

slouge: On November 30, 2008 12:44 PM said:

I've the same issue :-(

 

Featured Item

Page view counter