Example approach
This creates a greyscale shader:
- Create a folder for your custom shaders
- Create a new class to interface the shader:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
Imports System.Windows.Media.Effects Public Class GrayscaleEffect Inherits ShaderEffect Private Shared _pixelShader As PixelShader = New PixelShader() With { .UriSource = New Uri("pack://application:,,,/WpfWorkspace;component/ShaderEffects/GrayscaleEffect.ps") } Public Sub New() PixelShader = _pixelShader UpdateShaderValue(InputProperty) UpdateShaderValue(DesaturationFactorProperty) End Sub Public Shared ReadOnly InputProperty As DependencyProperty = ShaderEffect.RegisterPixelShaderSamplerProperty("Input", GetType(GrayscaleEffect), 0) Public Property Input As Brush Get Return CType(GetValue(InputProperty), Brush) End Get Set(ByVal value As Brush) SetValue(InputProperty, value) End Set End Property Public Shared ReadOnly DesaturationFactorProperty As DependencyProperty = DependencyProperty.Register("DesaturationFactor", GetType(Double), GetType(GrayscaleEffect), New UIPropertyMetadata(0.0, PixelShaderConstantCallback(0), AddressOf CoerceDesaturationFactor)) Public Property DesaturationFactor As Double Get Return CDbl(GetValue(DesaturationFactorProperty)) End Get Set(ByVal value As Double) SetValue(DesaturationFactorProperty, value) End Set End Property Private Shared Function CoerceDesaturationFactor(ByVal d As DependencyObject, ByVal value As Object) As Object Dim effect As GrayscaleEffect = CType(d, GrayscaleEffect) Dim newFactor As Double = CDbl(value) If newFactor < 0.0 OrElse newFactor > 1.0 Then Return effect.DesaturationFactor End If Return newFactor End Function End Class |
3. Create two new text files: GrayscaleEffect.ps and GrayscaleEffect.fx
4. Open the fx file in notepad and SaveAs – choose ANSI as the format
5. Add hlsl code to GrayscaleEffect.fx:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
sampler2D implicitInput : register(s0); float factor : register(c0); float4 main(float2 uv : TEXCOORD) : COLOR { float4 color = tex2D(implicitInput, uv); float gray = color.r * 0.3 + color.g * 0.59 + color.b *0.11; float4 result; result.r = (color.r - gray) * factor + gray; result.g = (color.g - gray) * factor + gray; result.b = (color.b - gray) * factor + gray; result.a = color.a; return result; } |
6. Set GrayscaleEffect.ps to Resource in properties
7. You need to set up the build to compile the shader on project build. Ensure you have fxc.exe
on your system. If not, download the Direct X SDK Here . Then, on the project compile>BuildEvents, put the following into Pre-build event:
1 |
C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Utilities\Bin\x64\fxc.exe" /T ps_2_0 /E main /Fo"$(SolutionDir)WpfWorkspace\ShaderEffects\GrayscaleEffect.ps" "$(SolutionDir)WpfWorkspace\ShaderEffects\GrayscaleEffect.fx |
Obviously changing your paths accordingly. That’s it – shader available to your app!
Example implementation:
1 2 3 4 5 6 |
Dim myGreyScaleEffect As New GrayscaleEffect Dim im As New Image With im .Source = New BitmapImage(New Uri("C:\Users\Dave\Pictures\CaveMan.png")) .Effect = myGreyScaleEffect End With |
Leave a Reply