0
\$\begingroup\$

I'm trying to port a blur effect from an XNA project over to SharpDx, and I get a "Null Reference Exception" wich I'm unable to find the reason for.

    private void blurShadow(RenderTarget2D to, RenderTarget2D from, int dir)
    {
        _graphicsDevice.SetRenderTargets(to);
        _shadowBlurEffect.CurrentTechnique.Passes[dir].Apply();
        _spriteBatch.Begin(SpriteSortMode.Deferred, _shadowBlurEffect);
        _spriteBatch.Draw(from, Vector2.Zero, Color.White);
        _spriteBatch.End();  // <-- Null Reference Exception here
    }

    public void Draw()
    {
        _graphicsDevice.SetRenderTargets(_graphicsDevice.DepthStencilBuffer, ShadowDepthTarget);
        _graphicsDevice.Clear(Color.White); // Clear the render target to 1 (infinite depth)
        foreach (var obj in ShadowCastingObjects)
            obj.Draw(Camera, DrawingReason.ShadowDepthMap, this);

        blurShadow(_shadowBlurTarg, ShadowDepthTarget, 0);
        blurShadow(ShadowDepthTarget, _shadowBlurTarg, 1);

        _graphicsDevice.SetRenderTargets(_graphicsDevice.DepthStencilBuffer, _graphicsDevice.BackBuffer);
    }

The render targets are created like this:

    ShadowDepthTarget = RenderTarget2D.New(_graphicsDevice, width, height, PixelFormat.R16G16.Float);
    _shadowBlurTarg = RenderTarget2D.New(_graphicsDevice, width, height, PixelFormat.R16G16.Float);

This is the shader code, I have tried variuos versions of the method signatures - in vain:

Texture2D Texture;
SamplerState TextureSampler;

// Precalculated weights and offsets
float weights[15] = { 0.1061154, 0.1028506, 0.1028506, 0.09364651, 0.09364651, 
    0.0801001, 0.0801001, 0.06436224, 0.06436224, 0.04858317, 0.04858317, 
    0.03445063, 0.03445063, 0.02294906, 0.02294906 };

float offsets[15] = { 0, 0.00125, -0.00125, 0.002916667, -0.002916667, 
    0.004583334, -0.004583334, 0.00625, -0.00625, 0.007916667, -0.007916667, 
    0.009583334, -0.009583334, 0.01125, -0.01125 };

float4 BlurHorizontal(
    float2 UV : TEXCOORD0) : SV_Target
{
    float4 output = float4(0, 0, 0, 1);
    for (int i = 0; i < 15; i++)
        output += Texture.Sample(TextureSampler, UV + float2(offsets[i], 0)) * weights[i];
    return output;
}

float4 BlurVertical(
    float2 UV : TEXCOORD0) : SV_Target
{
    float4 output = float4(0, 0, 0, 1);
    for (int i = 0; i < 15; i++)
        output += Texture.Sample(TextureSampler, UV + float2(0, offsets[i])) * weights[i];
    return output;
}


technique Tech
{
    pass Horizontal
    {
        SetGeometryShader(0);
        SetVertexShader(0);
        SetPixelShader(CompileShader(ps_4_0, BlurHorizontal()));
    }

    pass Verical
    {
        SetGeometryShader(0);
        SetVertexShader(0);
        SetPixelShader(CompileShader(ps_4_0, BlurVertical()));
    }
}
\$\endgroup\$
  • \$\begingroup\$ You barely showed enough code to be assisted with this. And either way, you are simply asking for debugging help, which is a no no around this place. \$\endgroup\$ – RecursiveCall Nov 21 '14 at 16:45
  • \$\begingroup\$ @RecursiveCall, I don't see how any other code could be relevant, and I'm not at all asking for debugging help at all. I'm hoping that someone will tell me that a custom shader passed to a sprite batch must be written in a specific way, or that there are restrictions on the target types, or something like that. I'm come to a grinding halt on debugging this, after hours of experimenting and googling. And if this problem can be diagnosed and documented here, it will help others walking the same path. Why do you say that that should be a no no??? \$\endgroup\$ – danbystrom Nov 21 '14 at 16:51
  • \$\begingroup\$ @RecursiveCall, see my answer to myself below. I finally found a sample showing how this must be done. The code I gave was perfectly sufficient. I didn't need debugging help, I needed documentation. Downvoting this question was really bad style. \$\endgroup\$ – danbystrom Nov 21 '14 at 19:36
1
\$\begingroup\$

It turns out that an effect passed to SpriteBatch.Begin must follow specific conventions:

Texture2D<float4> Texture : register(t0);

// SpriteBatch expects that default texture sampler parameter will have name 'TextureSampler'
sampler TextureSampler : register(s0);

// SpriteBatch expects that default vertex transform parameter will have name 'MatrixTransform'
row_major float4x4 MatrixTransform;

void VSMain(
    inout float4 color    : COLOR0,
    inout float2 texCoord : TEXCOORD0,
    inout float4 position : SV_Position)
{
    position = mul(position, MatrixTransform);
}

// Precalculated weights and offsets
float weights[15] = { 0.1061154, 0.1028506, 0.1028506, 0.09364651, 0.09364651, 
    0.0801001, 0.0801001, 0.06436224, 0.06436224, 0.04858317, 0.04858317, 
    0.03445063, 0.03445063, 0.02294906, 0.02294906 };

float offsets[15] = { 0, 0.00125, -0.00125, 0.002916667, -0.002916667, 
    0.004583334, -0.004583334, 0.00625, -0.00625, 0.007916667, -0.007916667, 
    0.009583334, -0.009583334, 0.01125, -0.01125 };


// Blurs the input image horizontally
float4 PSBlurHorizontal(
    float4 color: COLOR,
    float2 UV : TEXCOORD0) : SV_Target
{
    float4 output = float4(0, 0, 0, 1);
    for (int i = 0; i < 15; i++)
        output += Texture.Sample(TextureSampler, UV + float2(offsets[i], 0)) * weights[i];
    return output * color;
}

// Blurs the input image vertically
float4 PSBlurVertical(
    float4 color: COLOR,
    float2 UV : TEXCOORD0) : SV_Target
{
    float4 output = float4(0, 0, 0, 1);
    for (int i = 0; i < 15; i++)
        output += Texture.Sample(TextureSampler, UV + float2(0, offsets[i])) * weights[i];
    return output * color;
}


technique Tech
{
    pass Horizontal
    {
        SetGeometryShader(0);
        SetVertexShader(CompileShader(vs_4_0, VSMain()));
        SetPixelShader(CompileShader(ps_4_0, PSBlurHorizontal()));
    }

    pass Verical
    {
        SetGeometryShader(0);
        SetVertexShader(CompileShader(vs_4_0, VSMain()));
        SetPixelShader(CompileShader(ps_4_0, PSBlurVertical()));
    }
}
\$\endgroup\$
  • \$\begingroup\$ Please mark this as answered if it solved your problem because it seems like useful 'mystical' information that other people may find useful. If you can change the title of the question to be more specific to the problem it will also help others find it. \$\endgroup\$ – Steven Nov 21 '14 at 19:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.