DirectX11.1 introduced a bunch of built in effects into Direct2D that span the following categories
In my previous posts I showed how you could use SharpDx to call and render some of these effects inside your XAML Managed Metro apps.
However in the case where you want to do something that these effects don’t cover, or if you want to create a more optimal effect than custom effects is what you want!
HLSL (a custom pixel shader)
HLSL is the “high level shader language” developed by Microsoft for DirectX for defining their shaders.
DirectX11.1 and Visual Studio 12 introduces a much needed revamped HLSL editing/developing experience. The editor is available in C# & C++ projects, BUT the compilation functionality is only switched on in C++ projects.
Below is a screenshot of what you see when choosing a pixel shader file to add to your C++ project.
Below is a sample of a .HLSL file that is filled in for a simple effect. In this case it’s the algorithm to produce a “Ripple” effect.
In a C++ project you can right click on the .hlsl file and configure how VS compiles that resource. You will see in the screenshot below the yellow highlights the specific outputs for my custom pixel shader
So when this project is compiled this particular resource (Ripple.hlsl) will generate a pixel shader with an extension of .cso (custom shader object)
Remember ALL the above is only possible in a C++ project because that is where the compile logic for shaders exists. I’m hoping, but highly doubt, that these compile features for hlsl arrive in C# projects.
*.CSO in our managed apps
So once we have this compiled custom shader object (cso) we can use SharpDx to instantiate a CustomEffect for it for use in our managed metro app.
So in the sample above take the Ripple.cso and include it as “Content” in your XAML/C# metro app
You’ll notice that we included the Ripple.hlsl file as well, this is a good habbit to get into as it gives you valuable information in understanding how the shader is suppose to work and more importantly how to create a “CUSTOM EFFECT” for the cso.
Our custom effect’s properties
Once we have the cso in our managed project we need to create all the managed wrappers around it to be able to use it. SharpDx makes this process easy …
This ripple.cso takes a bunch of properties as inputs, we are going to put those in a separate file and call it RippleEffects.cs
Now if you refer back to the ripple.hlsl you’ll remember that there was a “Constants” area that defines the effects properties
Now we know what properties are needed for our custom effect, let’s create a wrapper for our effect and pass these properties into it.
Custom effect wrapper
Now its’ time to load up our cso and pass in our properties and execute this effect! We are going to wrap all this up in a RippleEffect custom effect class!
SharpDx has done all the hard work for us and made doing this easy!
Below you can see we create a RippleEffect class and give it the functionality of a “CustomEffectBase” which is a SharpDx abstraction for a DirectX Direct2D CustomEffect.
Next step is to implement the Properties for our effects that we defined earlier. It’s also important to know that we can define default values for our effect properties!
Because we implemented the “CustomEffectBase” we need to override the “Initialize” method,it is in there that we load our cso and assign it to our custom RippleEffect.cs
Also in the Initialize we pass through an “EffectContext”, which is where we are going to load our RippleEffect into. This effect context is important because it has a lot of useful libraries for all things effect related!
I should point out that when we load up our custom effect we need to give it a unique guid “GUID_RipplePixelShader” so that it is unique within the effect context.
Everything else in RippleEffect.cs can easily be understood, just step through the code at your convenience. The important ones I’ve already explained
Using our custom Ripple effect
ok now that we have created our custom “RippleEffect” let’s call it!
In the demos all rendering logic sits in “Render” classes, in our case its called an “EffectRenderer”.
To use this ripple effect I will use it as part of an effect graph. The first step of the effect graph is to create a BitmapSource Effect, which is basically just loading up a bitmap image. We will then pass this bitmap effect into the Ripple Effect creating an effect graph
RippleEffect in a SwapChainBackgoundPanel
This is what this effect looks like when we apply it to a SwapChainBackgroundPanel
RippleEffect in a SurfaceImageSource
This is what this effect looks like when we apply it to a SurfaceImageSource
Creating custom effects from a cso via SharpDx is dead simple, it’s actually quite fun. SharpDx has made easy to wrap the effect in a managed wrapper which leaves you more valuable time to spend on your actual hlsl
And the other thing I should point out is that SharpDx is a very thin wrapper on Dx and actually mirrors quite a lot of the api’s one for one, which means if you get used to the calling syntax of SharpDx you will feel right at home in the Cx/Dx world!
This post only covered custom “pixel shader” effects, stay tuned as there are other cool effects that I want to cover!!