Introduction
Hardware accelerated effects for WPF were first introduced in .NET 3.5 SP1. Very complex effects and graphically rich applications can be created with little impact on performance, thanks to the huge computing power of modern graphic cards. However, if you want to take advantage of this feature, you first need to learn a thing or two. The purpose of this article is to provide all the information you need to get started with Effects.
What is an Effect?
Effects are an easy-to-use API to create (surprisingly) graphical effects. For example, if you want a button to cast a shadow, there are several ways to accomplish the task, but the simplest and most efficient method is to assign the "Effect" property of the button, either from code or in XAML:
MyButton.Effect = new DropShadowEffect() { ... };
<Button Name="MyButton" ... >
<Button.Effect>
<DropShadowEffect ... />
</Button.Effect>
</Button>
As you can see, effects are so easy to use that you don't need any further explanation. The fun starts when you decide to write your own effects...
BitmapEffect, Effect, ShaderEffect... What?
First of all, there are several .NET classes that share the "Effect" suffix, and to make it even more confusing, they are all in the System.Windows.Media.Effects namespace. However, not all of those classes are useful when it comes to hardware acceleration, in fact some of them are completely useless.
BitmapEffect
The BitmapEffect class and its subclasses were originally supposed to provide the functionality of effects. However, this API doesn't use any hardware acceleration and it has been marked obsolete in .NET 4.0. It's strongly recommended to avoid using the BitmapEffect class or any of its subclasses!
Effect and its Derived Classes
As stated above, you apply an effect to a control by assigning the control's Effect property (the property is actually inherited from UIElement, just in case you needed to know). Now the question is... What needs to be assigned to the Effect property? The answer is as simple as it can be - it's an object of type Effect.
The Effect class is the base class of all hardware accelerated effects. It has three subclasses: BlurEffect, DropShadowEffect and ShaderEffect. The first two are ready-to-use effects included directly in the .NET library. The ShaderEffect class is the base class of all custom effects.
Why BlurEffect and DropShadowEffect?
Why are there only 2 fully implemented effects in the library and why don't these 2 effects derive from ShaderEffect? I can't answer the first question, but I can tell you what makes BlurEffect and DropShadowEffect so special.
Both DropShadowEffect and BlurEffect are using complex algorithms that require multiple passes, but multi-pass effects are not normally possible. However, the guys at Microsoft probably did a few dirty hacks deep inside the unmanaged core of the WPF rendering engine and created these two effects.
Note: It is possible to create a single-pass blurring algorithm, but such algorithm is terribly slow compared to multi-pass blurring. Anyway, there are probably more reasons why these 2 effects are implemented in a special way.
How Does It Work?
If you want to take advantage of hardware acceleration, you first need to know how the whole thing works.
A Few Words about the GPU Architecture
The architecture of Graphic Processing Units (GPUs) is different than the architecture of CPUs. GPUs are not general-purpose, they are designed to perform simple operations on large data sets. The operations are executed with high amount of parallelism, which results in great performance.
Modern GPUs are becoming more and more programmable and the range of tasks that can be executed on GPUs is growing (although there are several restrictions described below). Small programs executed on GPU are called shaders. There are several kinds of shaders - vertex shaders and geometry shaders are used when rendering 3D objects (not used by WPF Effects) and pixel shaders are used to perform simple operations on pixels.
There are even attempts to use the sheer computing power of GPUs for general purpose programming... Unfortunately there are several restrictions, such as limited number of instructions in one program, no ability to work with advanced data structures, limited memory management abilities, etc. Amazing speed comes with several trade-offs...
Pixel Shaders
A pixel shader is a short program that defines a simple operation executed on each pixel of the output image. That's pretty much all you need to create all kinds of interesting pixel-based effects.
Before You Write your First Effect...
WPF objects, including Effects, are rendered using the DirectX engine. DirectX shaders are written in High Level Shader Language (HLSL) and then compiled into bytecode. Therefore HLSL is one of the things you need to learn to write your own Effects (more about HLSL further in this article).
Some people will tell you that you need to download and install the entire DirectX SDK in order to compile HLSL code. Fortunately, this is not true. All you need is to download a Visual Studio add-in written by Greg Schechter and Gerhard Schneider. It is called Shader Effects BuildTask and you can get it from the CodePlex WPF site. This add-in reportedly works with Visual Studio 2008 and 2010.
Once the add-in is installed, a new project template called "WPF Shader Effect Library" will appear in Visual Studio. The best thing about this add-in is that you can write HLSL code directly in Visual Studio (without intellisense support and syntax-highlighting though) and all your shaders will be compiled automatically when you build your project.
Read more: Codeproject
Hardware accelerated effects for WPF were first introduced in .NET 3.5 SP1. Very complex effects and graphically rich applications can be created with little impact on performance, thanks to the huge computing power of modern graphic cards. However, if you want to take advantage of this feature, you first need to learn a thing or two. The purpose of this article is to provide all the information you need to get started with Effects.
What is an Effect?
Effects are an easy-to-use API to create (surprisingly) graphical effects. For example, if you want a button to cast a shadow, there are several ways to accomplish the task, but the simplest and most efficient method is to assign the "Effect" property of the button, either from code or in XAML:
MyButton.Effect = new DropShadowEffect() { ... };
<Button Name="MyButton" ... >
<Button.Effect>
<DropShadowEffect ... />
</Button.Effect>
</Button>
As you can see, effects are so easy to use that you don't need any further explanation. The fun starts when you decide to write your own effects...
BitmapEffect, Effect, ShaderEffect... What?
First of all, there are several .NET classes that share the "Effect" suffix, and to make it even more confusing, they are all in the System.Windows.Media.Effects namespace. However, not all of those classes are useful when it comes to hardware acceleration, in fact some of them are completely useless.
BitmapEffect
The BitmapEffect class and its subclasses were originally supposed to provide the functionality of effects. However, this API doesn't use any hardware acceleration and it has been marked obsolete in .NET 4.0. It's strongly recommended to avoid using the BitmapEffect class or any of its subclasses!
Effect and its Derived Classes
As stated above, you apply an effect to a control by assigning the control's Effect property (the property is actually inherited from UIElement, just in case you needed to know). Now the question is... What needs to be assigned to the Effect property? The answer is as simple as it can be - it's an object of type Effect.
The Effect class is the base class of all hardware accelerated effects. It has three subclasses: BlurEffect, DropShadowEffect and ShaderEffect. The first two are ready-to-use effects included directly in the .NET library. The ShaderEffect class is the base class of all custom effects.
Why BlurEffect and DropShadowEffect?
Why are there only 2 fully implemented effects in the library and why don't these 2 effects derive from ShaderEffect? I can't answer the first question, but I can tell you what makes BlurEffect and DropShadowEffect so special.
Both DropShadowEffect and BlurEffect are using complex algorithms that require multiple passes, but multi-pass effects are not normally possible. However, the guys at Microsoft probably did a few dirty hacks deep inside the unmanaged core of the WPF rendering engine and created these two effects.
Note: It is possible to create a single-pass blurring algorithm, but such algorithm is terribly slow compared to multi-pass blurring. Anyway, there are probably more reasons why these 2 effects are implemented in a special way.
How Does It Work?
If you want to take advantage of hardware acceleration, you first need to know how the whole thing works.
A Few Words about the GPU Architecture
The architecture of Graphic Processing Units (GPUs) is different than the architecture of CPUs. GPUs are not general-purpose, they are designed to perform simple operations on large data sets. The operations are executed with high amount of parallelism, which results in great performance.
Modern GPUs are becoming more and more programmable and the range of tasks that can be executed on GPUs is growing (although there are several restrictions described below). Small programs executed on GPU are called shaders. There are several kinds of shaders - vertex shaders and geometry shaders are used when rendering 3D objects (not used by WPF Effects) and pixel shaders are used to perform simple operations on pixels.
There are even attempts to use the sheer computing power of GPUs for general purpose programming... Unfortunately there are several restrictions, such as limited number of instructions in one program, no ability to work with advanced data structures, limited memory management abilities, etc. Amazing speed comes with several trade-offs...
Pixel Shaders
A pixel shader is a short program that defines a simple operation executed on each pixel of the output image. That's pretty much all you need to create all kinds of interesting pixel-based effects.
Before You Write your First Effect...
WPF objects, including Effects, are rendered using the DirectX engine. DirectX shaders are written in High Level Shader Language (HLSL) and then compiled into bytecode. Therefore HLSL is one of the things you need to learn to write your own Effects (more about HLSL further in this article).
Some people will tell you that you need to download and install the entire DirectX SDK in order to compile HLSL code. Fortunately, this is not true. All you need is to download a Visual Studio add-in written by Greg Schechter and Gerhard Schneider. It is called Shader Effects BuildTask and you can get it from the CodePlex WPF site. This add-in reportedly works with Visual Studio 2008 and 2010.
Once the add-in is installed, a new project template called "WPF Shader Effect Library" will appear in Visual Studio. The best thing about this add-in is that you can write HLSL code directly in Visual Studio (without intellisense support and syntax-highlighting though) and all your shaders will be compiled automatically when you build your project.
Read more: Codeproject