Click or drag to resize
PixelShaderEffect Constructor
Initializes a new instance of the PixelShaderEffect class.

Namespace:  Microsoft.Graphics.Canvas.Effects
Assembly:  Microsoft.Graphics.Canvas (in Microsoft.Graphics.Canvas.dll) Version:
public PixelShaderEffect(
	byte[] shaderCode


Type: SystemByte

Custom pixel shaders are written in HLSL (High Level Shading Language) and compiled with the Direct3D Shader Compiler (fxc.exe). This tool can be found in the Visual Studio 2017 "Developer Command Prompt".

To compile your shader, invoke fxc twice using the options:

set INCLUDEPATH="%WindowsSdkDir%\Include\%WindowsSDKVersion%\um"

fxc MyShader.hlsl /nologo /T lib_4_0_level_9_3_ps_only /D D2D_FUNCTION /D D2D_ENTRY=main /Fl MyShader.fxlib /I %INCLUDEPATH%
fxc MyShader.hlsl /nologo /T ps_4_0_level_9_3 /D D2D_FULL_SHADER /D D2D_ENTRY=main /E main /setprivate MyShader.fxlib /Fo:MyShader.bin /I %INCLUDEPATH%

This generates a .bin file which can be included with your app, loaded (eg. via File.ReadAllBytes) and passed to this constructor. It also generates a .fxlib file, which is temporary and can be deleted.

The target profile "4_0_level_9_3" means Direct3D feature level 9.3, which is compatible with Windows Phone. If you need more advanced shader capabilities and do not care about supporting lower end hardware, remove the "_level_9_3" part and build your shaders for "4_0" instead.

For a complete example of how to compile custom shaders, see samples\ExampleGallery\Shared\Shaders\CompileShaders.cmd.

To integrate properly with Direct2D Image Effects, your shader should #include "d2d1effecthelpers.hlsli" and use the helper macros it provides. Here is a simple example that samples from a single input texture and multiplies by a tint color:

#define D2D_INPUT_COUNT 1

#include "d2d1effecthelpers.hlsli"

float4 tint;

    float4 color = D2DGetInput(0);

    return color * tint;

Defining the symbol D2D_INPUT{N}_SIMPLE indicates that texture input N uses simple sampling, i.e. is always sampled at the same location as the pixel being shaded. This define should be used when a texture is sampled by calling D2DGetInput. Using it in your shader code will initialize the corresponding SamplerCoordinateMapping property to OneToOne.

If your shader samples its texture in some other way than D2DGetInput, for instance calling D2DSampleInputAtOffset or D2DSampleInputAtPosition, then you should define D2D_INPUT{N}_COMPLEX to indicate that it is not a 1:1 texture coordinate mapping. This will initialize the corresponding SamplerCoordinateMapping property to Unknown. Depending on the behavior of your shader, you may wish to change this to Offset, and set MaxSamplerOffset to indicate the maximum number of pixels by which a texture coordinate will be displaced.

For instance an edge detection shader that uses a 3x3 filter kernel (which has a maximum offset of 1 pixel in any direction from the center tap) should configure itself as:

var effect = new PixelShaderEffect(File.ReadAllBytes("MyShader.bin"))
    Source1Mapping = SamplerCoordinateMapping.Offset,
    MaxSamplerOffset = 1

Using SamplerCoordinateMapping.Offset can be more efficient than SamplerCoordinateMapping.Unknown, as the extra knowledge allows the effect runtime to break up large images into smaller tiles and skip computing unused regions of the source images. But specifying this information wrongly (for instance if your shader actually samples further away from the current pixel than the specified MaxSamplerOffset) can give unpredictably wrong results. If in doubt, stick with SamplerCoordinateMapping.Unknown.

For more information see the shaders used by Example Gallery, and the MSDN articles:

See Also