ShadowMapBlur.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. //-----------------------------------------------------------------------------
  2. // ShadowMapBlur.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using Microsoft.Xna.Framework;
  8. using Microsoft.Xna.Framework.Graphics;
  9. using System;
  10. using RacingGame.Graphics;
  11. using RacingGame.Helpers;
  12. namespace RacingGame.Shaders
  13. {
  14. /// <summary>
  15. /// ShadowMapBlur based on PostScreenBlur to blur the final shadow map
  16. /// output for a more smooth view on the screen.
  17. /// </summary>
  18. public class ShadowMapBlur : ShaderEffect
  19. {
  20. static readonly BlendState ZeroSourceBlend = new BlendState()
  21. {
  22. AlphaBlendFunction = BlendFunction.Add,
  23. AlphaSourceBlend = Blend.Zero,
  24. ColorSourceBlend = Blend.Zero,
  25. AlphaDestinationBlend = Blend.SourceAlpha,
  26. ColorDestinationBlend = Blend.SourceColor
  27. };
  28. /// <summary>
  29. /// The shader effect filename for this shader.
  30. /// </summary>
  31. private const string Filename = "PostScreenShadowBlur.fx";
  32. /// <summary>
  33. /// Effect handles for window size and scene map.
  34. /// </summary>
  35. private EffectParameter windowSize,
  36. sceneMap,
  37. blurMap;
  38. /// <summary>
  39. /// Links to the render to texture instances.
  40. /// </summary>
  41. private RenderToTexture sceneMapTexture,
  42. blurMapTexture;
  43. /// <summary>
  44. /// Scene map texture
  45. /// </summary>
  46. /// <returns>Render to texture</returns>
  47. public RenderToTexture SceneMapTexture
  48. {
  49. get
  50. {
  51. return sceneMapTexture;
  52. }
  53. }
  54. /// <summary>
  55. /// Blur map texture
  56. /// </summary>
  57. /// <returns>Render to texture</returns>
  58. public RenderToTexture BlurMapTexture
  59. {
  60. get
  61. {
  62. return blurMapTexture;
  63. }
  64. }
  65. /// <summary>
  66. /// Create shadow map screen blur shader.
  67. /// obs, using full size again: But only use 1/4 of the screen!
  68. /// </summary>
  69. public ShadowMapBlur()
  70. : base(Filename)
  71. {
  72. // Scene map texture
  73. sceneMapTexture = new RenderToTexture(
  74. //RenderToTexture.SizeType.FullScreen);
  75. //improve performance:
  76. RenderToTexture.SizeType.HalfScreen);
  77. blurMapTexture = new RenderToTexture(
  78. //RenderToTexture.SizeType.FullScreen);
  79. //improve performance:
  80. RenderToTexture.SizeType.HalfScreen);
  81. }
  82. protected override void SetParameterDefaultValues()
  83. {
  84. base.SetParameterDefaultValues();
  85. // Weights8 is now hardcoded in the shader to avoid GLSL std140
  86. // float-array padding mismatch on DesktopGL (each float element
  87. // would be padded to 16 bytes, causing a BlockCopy overrun).
  88. }
  89. /// <summary>
  90. /// Reload
  91. /// </summary>
  92. protected override void GetParameters()
  93. {
  94. // Can't get parameters if loading failed!
  95. if (effect == null)
  96. return;
  97. windowSize = effect.Parameters["windowSize"];
  98. sceneMap = effect.Parameters["sceneMap"];
  99. blurMap = effect.Parameters["blurMap"];
  100. // We need both windowSize and sceneMap.
  101. if (windowSize == null ||
  102. sceneMap == null)
  103. throw new NotSupportedException("windowSize and sceneMap must be " +
  104. "valid in PostScreenShader=" + Filename);
  105. }
  106. /// <summary>
  107. /// Render shadows
  108. /// </summary>
  109. /// <param name="renderCode">Render code</param>
  110. public void RenderShadows(BaseGame.RenderHandler renderCode)
  111. {
  112. if (renderCode == null)
  113. throw new ArgumentNullException("renderCode");
  114. // Render into our scene map texture
  115. sceneMapTexture.SetRenderTarget();
  116. // Clear render target
  117. sceneMapTexture.Clear(Color.White);
  118. // Render everything
  119. renderCode();
  120. // Resolve render target
  121. sceneMapTexture.Resolve();
  122. // Restore back buffer as render target
  123. BaseGame.ResetRenderTarget(true);
  124. }
  125. /// <summary>
  126. /// Show shadows with help of our blur map shader
  127. /// </summary>
  128. public void RenderShadows()
  129. {
  130. // Only apply post screen blur if texture is valid and effect are valid
  131. if (sceneMapTexture == null ||
  132. Valid == false ||
  133. // If the shadow scene map is not yet filled, there is no point
  134. // continuing here ...
  135. sceneMapTexture.XnaTexture == null)
  136. return;
  137. // Don't use or write to the z buffer
  138. BaseGame.Device.DepthStencilState = DepthStencilState.None;
  139. // Disable alpha for the first pass
  140. BaseGame.Device.BlendState = BlendState.Opaque;
  141. if (windowSize != null)
  142. windowSize.SetValue(
  143. new Vector2(sceneMapTexture.Width, sceneMapTexture.Height));
  144. if (sceneMap != null)
  145. sceneMap.SetValue(sceneMapTexture.XnaTexture);
  146. effect.CurrentTechnique = effect.Techniques["ScreenAdvancedBlur20"];
  147. // We must have exactly 2 passes!
  148. if (effect.CurrentTechnique.Passes.Count != 2)
  149. throw new InvalidOperationException(
  150. "This shader should have exactly 2 passes!");
  151. // Just start pass 0
  152. blurMapTexture.SetRenderTarget();
  153. EffectPass effectPass = effect.CurrentTechnique.Passes[0];
  154. effectPass.Apply();
  155. VBScreenHelper.Render();
  156. blurMapTexture.Resolve();
  157. BaseGame.ResetRenderTarget(false);
  158. // Restore z buffer state
  159. BaseGame.Device.DepthStencilState = DepthStencilState.Default;
  160. // Set u/v addressing back to wrap
  161. BaseGame.Device.SamplerStates[0] = SamplerState.LinearWrap;
  162. // Restore normal alpha blending
  163. //BaseGame.Device.RenderState.BlendFunction = BlendFunction.Add;
  164. BaseGame.SetCurrentAlphaMode(BaseGame.AlphaMode.Default);
  165. }
  166. /// <summary>
  167. /// Show shadows with help of our blur map shader
  168. /// </summary>
  169. public void ShowShadows()
  170. {
  171. // Only apply post screen blur if texture is valid and effect are valid
  172. if (blurMapTexture == null ||
  173. Valid == false ||
  174. // If the shadow scene map is not yet filled, there is no point
  175. // continuing here ...
  176. blurMapTexture.XnaTexture == null)
  177. return;
  178. // Don't use or write to the z buffer
  179. BaseGame.Device.DepthStencilState = DepthStencilState.None;
  180. // Make sure we clamp everything to 0-1
  181. BaseGame.Device.SamplerStates[0] = SamplerState.LinearClamp;
  182. // Restore back buffer as render target
  183. //not required: BaseGame.ResetRenderTarget(false);
  184. if (blurMap != null)
  185. blurMap.SetValue(blurMapTexture.XnaTexture);
  186. effect.CurrentTechnique = effect.Techniques["ScreenAdvancedBlur20"];
  187. // We must have exactly 2 passes!
  188. if (effect.CurrentTechnique.Passes.Count != 2)
  189. throw new InvalidOperationException(
  190. "This shader should have exactly 2 passes!");
  191. // Render second pass
  192. // Use ZeroSourceBlend alpha mode for the final result
  193. BaseGame.Device.BlendState = ZeroSourceBlend;
  194. /*BaseGame.Device.RenderState.AlphaBlendEnable = true;
  195. BaseGame.Device.RenderState.AlphaBlendOperation = BlendFunction.Add;
  196. BaseGame.Device.RenderState.SourceBlend = Blend.Zero;
  197. BaseGame.Device.RenderState.DestinationBlend = Blend.SourceColor;*/
  198. EffectPass effectPass = effect.CurrentTechnique.Passes[1];
  199. effectPass.Apply();
  200. VBScreenHelper.Render();
  201. // Restore z buffer state
  202. BaseGame.Device.DepthStencilState = DepthStencilState.Default;
  203. // Set u/v addressing back to wrap
  204. BaseGame.Device.SamplerStates[0] = SamplerState.LinearWrap;
  205. // Restore normal alpha blending
  206. //BaseGame.Device.RenderState.BlendFunction = BlendFunction.Add;
  207. BaseGame.SetCurrentAlphaMode(BaseGame.AlphaMode.Default);
  208. }
  209. }
  210. }