Arkcann

This has been bugging me for a while, whenever I try to execute a multiple-pass technique that affects the entire screen, the only pass that makes any difference is the one executed last for example:

pass P0

{

PixelShader = compile ps_2_0 Blur();

}

pass P1

{

PixelShader = compile ps_2_0 GrayScale();

}

The screen is only changed by the GrayScale effect which is the last pass, I would like to be able to blur the screen, and then make it gray scale without having to make a seperate method that does this. Thankyou for any help, and I'm sorry if I'm unclear.



Re: XNA Game Studio Express Multiple Pass Post-Processing

Catalin Zima

I would say that both passes work on the same screen.

What I mean by this is: I assume you resolve your render target to a texture, than draw that texture over the whole screen, and apply the pixel shader.

Well, each pass works with the texture in which you resolved the render target. Let's call it SceneTexture.

So, you apply the blur to the SceneTexture. After that, when you apply the GrayScale, it doesn't apply it on the result of the blur, but rather on the SceneTexture again. So, after the second pass, you will onyl have the initial SceneTexture grayscaled. The blurred SceneTexture was overwritten.

I am currently unaware of any solution to this other than resolving the rendertarget after each pass. Something like:

...

graphics.GraphicsDevice.ResolveRenderTarget(0);

SceneTexture = sceneRenderTarget.GetTexture(); //sceneRenderTarget is the renderTarget to which the Scene was rendered. From this point forward it is used as a renderTarget for post processing

...

foreach (EffectPass pass in effect.CurrentTechnique.Passes)

{

pass.Begin();

//draw the screen using this pass, and SceneTexture

pass.End();

graphics.GraphicsDevice.ResolveRenderTarget(0);

SceneTexture = sceneRenderTarget.GetTexture();

}

Note: this is not working code. This is how I would try to do it, but haven't tried it yet. If you get it working and have good results, please confirm this was usefull. I tested a similar technique for multiple post-processing effects, not multiple passes, but this should do the job.





Re: XNA Game Studio Express Multiple Pass Post-Processing

Arkcann

Sadly that didn't seem to work, even with a lot of fiddling, well this is the code that I'm using for my post processing method it uses a tutorial from HazyMind so I'm not sure if his implementation restricts what can be done with multiple passes. It also has the things you mention, however I'm unsure as to what you meant by "//draw the screen using this pass, and SceneTexture", I assume you just meant to draw an image using SceneTexture as the texture. Thanks for your ongoing help!

public void PostRender(GraphicsDevice myDevice)

{

myDevice.ResolveRenderTarget(0);

SceneTexture = myRenderTarget.GetTexture();

myEffect.Begin();

mySpriteBatch.Begin(

SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.SaveState

);

foreach (EffectPass pass in myEffect.CurrentTechnique.Passes)

{

pass.Begin();

mySpriteBatch.Draw(SceneTexture, Vector2.Zero, Color.White);

pass.End();

SceneTexture = myRenderTarget.GetTexture();

myDevice.ResolveRenderTarget(0);

}

myDevice.SetRenderTarget(0, null);

mySpriteBatch.End();

myEffect.End();

}





Re: XNA Game Studio Express Multiple Pass Post-Processing

ProfEclipse

It appears you have the following two lines reversed in your foreach loop:

SceneTexture = myRenderTarget.GetTexture();

myDevice.ResolveRenderTarget(0);

You should resolve the target before setting SceneTexture (as was done before the foreach loop). I haven't tested any of this, but that would match Catalin's suggested method.





Re: XNA Game Studio Express Multiple Pass Post-Processing

Catalin Zima

How about trying it this way

public void PostRender(GraphicsDevice myDevice)

{

myDevice.ResolveRenderTarget(0);

SceneTexture = myRenderTarget.GetTexture();

myEffect.Begin();

foreach (EffectPass pass in myEffect.CurrentTechnique.Passes)

{

pass.Begin();

mySpriteBatch.Begin(

SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.SaveState

);

mySpriteBatch.Draw(SceneTexture, Vector2.Zero, Color.White);

mySpriteBatch.End();

pass.End();

myDevice.ResolveRenderTarget(0);

SceneTexture = myRenderTarget.GetTexture();

}

// myDevice.SetRenderTarget(0, null); <= this would basically erase everything you've drawn before, if I'm not mistaken, so don't use it.

myEffect.End();

}