Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I'm trying to create a basic post-processing shader, like I did many times before but somehow today it's just not working, I guess it's something basic that I missed.

Anyway my setup:

I have 3 render targets rts[0], rts1, and rts[2], I draw a simple model in each one of them. I then draw the render targets to the screen using the following code:

GraphicsDevice.SetRenderTarget(null);
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null);

spriteBatch.Draw(rts[0], new Rectangle(0, 0, GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2), Color.White);
spriteBatch.Draw(rts[1], new Rectangle(GraphicsDevice.Viewport.Width / 2, 0, GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2), Color.White);
spriteBatch.Draw(rts[2], new Rectangle(0, GraphicsDevice.Viewport.Height / 2, GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2), Color.White);

spriteBatch.End();

This gives me the following picture: 3 rendertargets rendered with a spritebatch Which is exactly what I expect it to be :)

Now I feed these 3 render targets as textures to my shader like this: (shaderTexture is a black 1x1 texture)

cutAwayEffect.Parameters["lowTexture"].SetValue(rts[0]);
cutAwayEffect.Parameters["highTexture"].SetValue(rts[1]);
cutAwayEffect.Parameters["cutTexture"].SetValue(rts[2]);

spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque, null, null, null, cutAwayEffect);


spriteBatch.Draw(shaderTexture, new Rectangle(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2, GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2), Color.White);

spriteBatch.End();

And the shader:

texture lowTexture;
sampler lowSampler = sampler_state
{
    Texture = (lowTexture);
};

texture highTexture;
sampler highSampler = sampler_state
{
    Texture = (highTexture);
};

texture cutTexture;
sampler cutSampler = sampler_state
{
    Texture = (cutTexture);
};

float4 PixelShaderFunction(float2 texCoord: TEXCOORD0) : COLOR0
{    
    float4 baseColour = tex2D(lowSampler, texCoord).rgba;
    float4 highColour = tex2D(highSampler, texCoord).rgba;
    float4 cutColour = tex2D(cutSampler, texCoord).rgba;
    float4 finalColour = baseColour + highColour * cutColour;


    return finalColour;
}

technique CutAway
{
    pass Pass1
    { 
        PixelShader = compile ps_2_0 PixelShaderFunction();
    }
}

Now I would expect to see a combination of all 3 render targets in the bottom right corner, however I don't see any data from baseColour. When I change finalColour to just baseColour I only see black, same goes for just highColour and just cutColour. Even finalColour = highColour*cutColour only gives me black while finalColour = baseColour + highColour*cutColour; does give me something.

The shader does seem to be working, changing final Colour to float4(1,0,1,1) gives me the expected pink square. There seems to be a problem reading the data from the textures, but I've got no clue why.

share|improve this question
    
Does it make a difference if you set the shader parameters after you call .Begin()? –  Richard Marskell - Drackir May 19 '12 at 12:02
    
@RichardMarskell-Drackir unfortunately not –  Roy T. May 19 '12 at 12:11
add comment

1 Answer

up vote 0 down vote accepted

In the end I've made the following changes and it now works

In the shader I replaced the lowTexture + lowSampler by this

sampler lowSampler : register(s0);

The draw code is now:

 cutAwayEffect.Parameters["highTexture"].SetValue(rts[1]);
            cutAwayEffect.Parameters["cutTexture"].SetValue(rts[2]);
            cutAwayEffect.Parameters["blurWidth"].SetValue(0.07f);

            spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, null, null, null, cutAwayEffect);
            spriteBatch.Draw(rts[0], new Rectangle(GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2, GraphicsDevice.Viewport.Width / 2, GraphicsDevice.Viewport.Height / 2), Color.White);
            spriteBatch.End();

Why this solves the problem? I'm not 100% sure. The spritebatch now automatically puts rts[0] in to register(s0) and I don't have to use the dummy texture anymore. Maybe that was giving problems but I'm still not sure. So if someone has a suggestion why this works, or better: why the original code didn't, feel free to post your answer.

share|improve this answer
    
All I know is that the SpriteBatch shader samples use registers. I don't know what the implications are but you can be rest assured you are now doing it the correct way. –  Jonathan Dickinson May 23 '12 at 8:17
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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