// Project: XnaShooter, File: ShadowMapBlur.cs
// Namespace: XnaShooter.Shaders, Class: ShadowMapBlur
// Path: C:\code\XnaShooter\Shaders, Author: Abi
// Code lines: 205, Size of file: 5,83 KB
// Creation date: 09.10.2006 18:25
// Last modified: 10.10.2006 12:47
// Generated with Commenter by abi.exDream.com
#region Using directives
using Microsoft.Xna.Framework.Graphics;
using System;
using XnaShooter.Graphics;
using XnaShooter.Helpers;
using XnaShooter.Game;
#endregion
namespace XnaShooter.Shaders
{
///
/// ShadowMapBlur based on PostScreenBlur to blur the final shadow map
/// output for a more smooth view on the screen.
///
public class ShadowMapBlur : ShaderEffect
{
#region Variables
///
/// The shader xnaEffect filename for this shader.
///
private const string Filename = "PostScreenShadowBlur.fx";
///
/// Effect handles for window size and scene map.
///
private EffectParameter windowSize,
sceneMap;//,
//blurMap;
///
/// Links to the render to texture instances.
///
private RenderToTexture sceneMapTexture;//,
//blurMapTexture;
///
/// Scene map texture
///
/// Render to texture
public RenderToTexture SceneMapTexture
{
get
{
return sceneMapTexture;
} // get
} // SceneMapTexture
/*obs
///
/// Blur map texture
///
/// Render to texture
public RenderToTexture BlurMapTexture
{
get
{
return blurMapTexture;
} // get
} // BlurMapTexture
*/
#endregion
#region Create
///
/// Create shadow map screen blur shader.
/// obs, using full size again: But only use 1/4 of the screen!
///
public ShadowMapBlur()
: base(Filename)
{
Load();
} // ShadowMapBlur()
#endregion
#region Dispose
///
/// Dispose
///
public override void Dispose()
{
base.Dispose();
if (sceneMapTexture != null)
sceneMapTexture.Dispose();
sceneMapTexture = null;
} // Dispose()
#endregion
#region Load
///
/// Load in case the device got lost.
///
public override void Load()
{
base.Load();
// Scene map texture
sceneMapTexture = new RenderToTexture(
RenderToTexture.SizeType.FullScreen);
} // Load()
#endregion
#region Get parameters
///
/// Reload
///
protected override void GetParameters()
{
// Can't get parameters if loading failed!
if (xnaEffect == null)
return;
windowSize = xnaEffect.Parameters["windowSize"];
sceneMap = xnaEffect.Parameters["sceneMap"];
//blurMap = xnaEffect.Parameters["blurMap"];
// We need both windowSize and sceneMap.
if (windowSize == null ||
sceneMap == null)
throw new NotSupportedException("windowSize and sceneMap must be " +
"valid in PostScreenShader=" + Filename);
} // GetParameters()
#endregion
#region RenderShadows
///
/// Render shadows
///
/// Render code
public void RenderShadows(BaseGame.RenderDelegate renderCode)
{
// Render into our scene map texture
sceneMapTexture.SetRenderTarget();
//*TODO
DepthStencilBuffer remBackBufferSurface = null;
if (sceneMapTexture.ZBufferSurface != null)
{
remBackBufferSurface = BaseGame.Device.DepthStencilBuffer;
BaseGame.Device.DepthStencilBuffer =
sceneMapTexture.ZBufferSurface;
} // if (sceneMapTexture.ZBufferSurface)
//*/
// Clear render target
sceneMapTexture.Clear(Color.White);
// Render everything
renderCode();
// Resolve render target
sceneMapTexture.Resolve();
// Restore back buffer as render target
BaseGame.ResetRenderTarget(false);
//*TODO
if (sceneMapTexture.ZBufferSurface != null)
BaseGame.Device.DepthStencilBuffer = remBackBufferSurface;
//*/
} // RenderShadows(renderCode)
#endregion
#region ShowShadows
///
/// Show shadows with help of our blur map shader.
/// We got 2 parts to fix the problem on the Xbox360 that we can't have
/// more than one rendertarget in parallel.
///
public void ShowShadowsPart1()
{
return;
/*obs
// Only apply post screen blur if texture is valid and xnaEffect are valid
if (sceneMapTexture == null ||
Valid == false ||
// If the shadow scene map is not yet filled, there is no point
// continuing here ...
sceneMapTexture.XnaTexture == null)
return;
try
{
// Don't use or write to the z buffer
BaseGame.Device.RenderState.DepthBufferEnable = false;
BaseGame.Device.RenderState.DepthBufferWriteEnable = false;
// Disable alpha for the first pass
BaseGame.Device.RenderState.AlphaBlendEnable = false;
/*obs
// Make sure we use the default add mode for alpha blend operations,
// don't ask me why, but for some reason this is NOT the default
// on the Xbox360 and it cost me a freaking day to figure this out :(
BaseGame.Device.RenderState.AlphaBlendOperation = BlendFunction.Add;
// Make sure we clamp everything to 0-1
BaseGame.Device.SamplerStates[0].AddressU = TextureAddressMode.Clamp;
BaseGame.Device.SamplerStates[0].AddressV = TextureAddressMode.Clamp;
// Restore back buffer as render target
//not required: BaseGame.ResetRenderTarget(false);
*
if (windowSize != null)
windowSize.SetValue(
new float[] { sceneMapTexture.Width, sceneMapTexture.Height });
if (sceneMap != null)
sceneMap.SetValue(sceneMapTexture.XnaTexture);
xnaEffect.CurrentTechnique = xnaEffect.Techniques[
BaseGame.CanUsePS20 ? "ScreenAdvancedBlur20" : "ScreenAdvancedBlur"];
// We must have exactly 2 passes!
if (xnaEffect.CurrentTechnique.Passes.Count != 2)
throw new Exception("This shader should have exactly 2 passes!");
// Just start pass 0
blurMapTexture.SetRenderTarget();
RenderSinglePassShader(VBScreenHelper.Render);
/*obs
effect.Begin(SaveStateMode.None);
EffectPass effectPass = effect.CurrentTechnique.Passes[0];
effectPass.Begin();
VBScreenHelper.Render();
effectPass.End();
*
blurMapTexture.Resolve();
BaseGame.ResetRenderTarget(false);
/*obs
DepthStencilBuffer remBackBufferSurface = null;
xnaEffect.Begin(SaveStateMode.None);
for (int pass = 0; pass < xnaEffect.CurrentTechnique.Passes.Count; pass++)
{
/*#if XBOX360
// Just use 1 pass and render directly!
// Else Xbox360 will render black rectangles on top of our
// background, I really can't kill those (strange bug).
// Use ZeroSourceBlend alpha mode for the final result
BaseGame.Device.RenderState.AlphaBlendEnable = true;
BaseGame.Device.RenderState.AlphaBlendOperation = BlendFunction.Add;
BaseGame.Device.RenderState.SourceBlend = Blend.Zero;
BaseGame.Device.RenderState.DestinationBlend = Blend.SourceColor;
#else
*
if (pass == 0)
{
blurMapTexture.SetRenderTarget();
if (blurMapTexture.ZBufferSurface != null)
{
remBackBufferSurface = BaseGame.Device.DepthStencilBuffer;
BaseGame.Device.DepthStencilBuffer =
blurMapTexture.ZBufferSurface;
} // if (blurMapTexture.ZBufferSurface)
} // if
else
{
BaseGame.ResetRenderTarget(false);
if (blurMapTexture.ZBufferSurface != null)
BaseGame.Device.DepthStencilBuffer = remBackBufferSurface;
// Use ZeroSourceBlend alpha mode for the final result
BaseGame.Device.RenderState.AlphaBlendEnable = true;
BaseGame.Device.RenderState.AlphaBlendOperation = BlendFunction.Add;
BaseGame.Device.RenderState.SourceBlend = Blend.Zero;
BaseGame.Device.RenderState.DestinationBlend = Blend.SourceColor;
} // else
//#endif
EffectPass effectPass = xnaEffect.CurrentTechnique.Passes[pass];
effectPass.Begin();
VBScreenHelper.Render();
effectPass.End();
/*#if XBOX360
break;
#else
*
if (pass == 0)
{
blurMapTexture.Resolve();
if (blurMap != null)
blurMap.SetValue(blurMapTexture.XnaTexture);
xnaEffect.CommitChanges();
} // if
//#endif
} // for (pass, <, ++)
*
} // try
finally
{
//xnaEffect.End();
// Restore z buffer state
BaseGame.Device.RenderState.DepthBufferEnable = true;
BaseGame.Device.RenderState.DepthBufferWriteEnable = true;
// Set u/v addressing back to wrap
BaseGame.Device.SamplerStates[0].AddressU = TextureAddressMode.Wrap;
BaseGame.Device.SamplerStates[0].AddressV = TextureAddressMode.Wrap;
// Restore normal alpha blending
BaseGame.Device.RenderState.BlendFunction = BlendFunction.Add;
//BaseGame.AlphaMode = BaseGame.AlphaModes.Default;
} // finally
*/
} // ShowShadowsPart1()
///
/// Show shadows with help of our blur map shader
///
public void ShowShadowsPart2()
{
// Don't use or write to the z buffer
BaseGame.Device.RenderState.DepthBufferEnable = false;
BaseGame.Device.RenderState.DepthBufferWriteEnable = false;
// Make sure we clamp everything to 0-1
BaseGame.Device.SamplerStates[0].AddressU = TextureAddressMode.Clamp;
BaseGame.Device.SamplerStates[0].AddressV = TextureAddressMode.Clamp;
if (windowSize != null)
windowSize.SetValue(
new float[] { sceneMapTexture.Width, sceneMapTexture.Height });
if (sceneMap != null)
sceneMap.SetValue(sceneMapTexture.XnaTexture);
// Just use the simple blur, the advanced blur will cause too much throuble!
xnaEffect.CurrentTechnique = xnaEffect.Techniques["ScreenBlur"];
// Use ZeroSourceBlend alpha mode for the final result
BaseGame.Device.RenderState.AlphaBlendEnable = true;
BaseGame.Device.RenderState.AlphaBlendOperation = BlendFunction.Add;
BaseGame.Device.RenderState.SourceBlend = Blend.Zero;
BaseGame.Device.RenderState.DestinationBlend = Blend.SourceColor;
RenderSinglePassShader(VBScreenHelper.Render);
// Restore z buffer state
BaseGame.Device.RenderState.DepthBufferEnable = true;
BaseGame.Device.RenderState.DepthBufferWriteEnable = true;
// Set u/v addressing back to wrap
BaseGame.Device.SamplerStates[0].AddressU = TextureAddressMode.Wrap;
BaseGame.Device.SamplerStates[0].AddressV = TextureAddressMode.Wrap;
// Restore normal alpha blending
BaseGame.Device.RenderState.BlendFunction = BlendFunction.Add;
// Done!
return;
/*obs
// Only apply post screen blur if texture is valid and effect are valid
if (blurMapTexture == null ||
Valid == false ||
// If the shadow scene map is not yet filled, there is no point
// continuing here ...
blurMapTexture.XnaTexture == null)
return;
try
{
// Don't use or write to the z buffer
BaseGame.Device.RenderState.DepthBufferEnable = false;
BaseGame.Device.RenderState.DepthBufferWriteEnable = false;
// Make sure we clamp everything to 0-1
BaseGame.Device.SamplerStates[0].AddressU = TextureAddressMode.Clamp;
BaseGame.Device.SamplerStates[0].AddressV = TextureAddressMode.Clamp;
// Restore back buffer as render target
//not required: BaseGame.ResetRenderTarget(false);
if (blurMap != null)
blurMap.SetValue(blurMapTexture.XnaTexture);
xnaEffect.CurrentTechnique = xnaEffect.Techniques[
BaseGame.CanUsePS20 ? "ScreenAdvancedBlur20" : "ScreenAdvancedBlur"];
// We must have exactly 2 passes!
if (xnaEffect.CurrentTechnique.Passes.Count != 2)
throw new Exception("This shader should have exactly 2 passes!");
// Render second pass
xnaEffect.Begin(SaveStateMode.None);
// Use ZeroSourceBlend alpha mode for the final result
BaseGame.Device.RenderState.AlphaBlendEnable = true;
BaseGame.Device.RenderState.AlphaBlendOperation = BlendFunction.Add;
BaseGame.Device.RenderState.SourceBlend = Blend.Zero;
BaseGame.Device.RenderState.DestinationBlend = Blend.SourceColor;
EffectPass effectPass = xnaEffect.CurrentTechnique.Passes[1];
effectPass.Begin();
VBScreenHelper.Render();
effectPass.End();
} // try
finally
{
xnaEffect.End();
// Restore z buffer state
BaseGame.Device.RenderState.DepthBufferEnable = true;
BaseGame.Device.RenderState.DepthBufferWriteEnable = true;
// Set u/v addressing back to wrap
BaseGame.Device.SamplerStates[0].AddressU = TextureAddressMode.Wrap;
BaseGame.Device.SamplerStates[0].AddressV = TextureAddressMode.Wrap;
// Restore normal alpha blending
//BaseGame.Device.RenderState.BlendFunction = BlendFunction.Add;
//BaseGame.AlphaMode = BaseGame.AlphaModes.Default;
} // finally
*/
} // ShowShadows()
#endregion
} // class ShadowMapBlur
} // namespace XnaShooter.Shaders