I’ve been working on a deferred rendering system for my game but I’m having trouble with some of the effects. Ideally the user would be able to enable/disable some of them (SSAO, FXAA, etc.) but I’ve been stuck for the best way to achieve this.
My current code runs a pixel shader on each stage using a sprite batch:
_effect.CurrentTechnique = _effect.Techniques["Shadows"];
GraphicsDevice.SetRenderTarget(_renderTarget);
SpriteBatch.Begin(effect: _effect, samplerState: _samplerState, rasterizerState: _rasterizerState);
SpriteBatch.Draw(_dataRenderImage, new Rectangle(0, 0, width, height), Color.White);
SpriteBatch.End();
_renderImage = (Texture2D)_renderTarget;
if (FXAA)
{
_effect.CurrentTechnique = _effect.Techniques["FXAA"];
SpriteBatch.Begin(effect: _effect, samplerState: _samplerState, rasterizerState: _rasterizerState);
SpriteBatch.Draw(_renderImage, new Rectangle(0, 0, width, height), Color.White);
SpriteBatch.End();
_renderImage = (Texture2D)_renderTarget;
}
GraphicsDevice.SetRenderTarget(null);
_effect.CurrentTechnique = _effect.Techniques["Final"];
SpriteBatch.Begin(effect: _effect, samplerState: _samplerState, rasterizerState: _rasterizerState);
SpriteBatch.Draw(_renderImage, new Rectangle(0, 0, width, height), Color.White);
SpriteBatch.End();
This works when FXAA is disabled:
But applying FXAA produces a black screen
(Yes, the screenshot was necessary, shut up)
I’m guessing that this is because I am trying to render to the same buffer that I’m reading from which probably isn’t a great thing to do. If it’s not, and I’m doing something else wrong, disregard below.
I have a few potential fixes in mind, but none work particularly well:
- Create a new buffer for every pass. This would take up far more VRAM than I need and it would be a hassle to select the last buffer for my ‘final’ pass anyway
- Create a set of techniques for each option and select the one that fits the options. This grows exponentially and is pretty repetitive so I can’t see this being the standard
- create ‘dud’ passes where the shader just passes on the value in the pixel if the option hasn’t been enabled. Although this runs less code than number 1, I feel like there’s probably a way to not run the pass at all if it isn’t needed
What is normally done?