PostScreenGlow.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. //-----------------------------------------------------------------------------
  2. // PostScreenGlow.cs
  3. //
  4. // Microsoft XNA Community Game Platform
  5. // Copyright (C) Microsoft Corporation. All rights reserved.
  6. //-----------------------------------------------------------------------------
  7. using System;
  8. using System.Collections;
  9. using System.Text;
  10. using System.IO;
  11. using RacingGame.GameLogic;
  12. using RacingGame.Graphics;
  13. using RacingGame.Helpers;
  14. using Microsoft.Xna.Framework.Graphics;
  15. using Texture = RacingGame.Graphics.Texture;
  16. using Microsoft.Xna.Framework.Input;
  17. using Microsoft.Xna.Framework;
  18. namespace RacingGame.Shaders
  19. {
  20. /// <summary>
  21. /// Post screen glow shader based on PostScreenGlow.fx.
  22. /// Derive from PostScreenMenu, this way we can save duplicating
  23. /// the effect parameters and use the same RenderToTextures.
  24. /// </summary>
  25. public class PostScreenGlow : PostScreenMenu
  26. {
  27. static readonly BlendState BlendStateAlphaWrite = new BlendState() {
  28. ColorSourceBlend = Blend.One,
  29. AlphaSourceBlend = Blend.Zero,
  30. ColorDestinationBlend = Blend.Zero,
  31. AlphaDestinationBlend = Blend.One
  32. };
  33. /// <summary>
  34. /// The shader effect filename for this shader.
  35. /// </summary>
  36. private const string Filename = "PostScreenGlow.fx";
  37. /// <summary>
  38. /// Effect handles for window size and scene map.
  39. /// </summary>
  40. private EffectParameter radialSceneMap,
  41. radialBlurScaleFactor,
  42. screenBorderFadeoutMap;
  43. /// <summary>
  44. /// Links to the passTextures, easier to write code this way.
  45. /// This are just reference copies.
  46. /// </summary>
  47. private RenderToTexture radialSceneMapTexture;
  48. /// <summary>
  49. /// Helper texture for the screen border (darken the borders).
  50. /// </summary>
  51. private Texture screenBorderFadeoutMapTexture = null;
  52. /// <summary>
  53. /// Last used radial blur scale factor
  54. /// </summary>
  55. private float lastUsedRadialBlurScaleFactor = 0;
  56. /// <summary>
  57. /// Radial blur scale factor
  58. /// </summary>
  59. public float RadialBlurScaleFactor
  60. {
  61. get
  62. {
  63. return lastUsedRadialBlurScaleFactor;
  64. }
  65. set
  66. {
  67. if (radialBlurScaleFactor != null &&
  68. lastUsedRadialBlurScaleFactor != value)
  69. {
  70. lastUsedRadialBlurScaleFactor = value;
  71. radialBlurScaleFactor.SetValue(value);
  72. }
  73. }
  74. }
  75. /// <summary>
  76. /// Create post screen glow
  77. /// </summary>
  78. public PostScreenGlow()
  79. : base(Filename)
  80. {
  81. // Final map for glow, used to perform radial blur next step
  82. radialSceneMapTexture = new RenderToTexture(
  83. RenderToTexture.SizeType.FullScreen);
  84. }
  85. /// <summary>
  86. /// Reload
  87. /// </summary>
  88. protected override void GetParameters()
  89. {
  90. // Can't get parameters if loading failed!
  91. if (effect == null)
  92. return;
  93. windowSize = effect.Parameters["windowSize"];
  94. sceneMap = effect.Parameters["sceneMap"];
  95. // We need both windowSize and sceneMap.
  96. if (windowSize == null ||
  97. sceneMap == null)
  98. throw new NotSupportedException("windowSize and sceneMap must be " +
  99. "valid in PostScreenShader=" + Filename);
  100. // Init additional stuff
  101. downsampleMap = effect.Parameters["downsampleMap"];
  102. blurMap1 = effect.Parameters["blurMap1"];
  103. blurMap2 = effect.Parameters["blurMap2"];
  104. radialSceneMap = effect.Parameters["radialSceneMap"];
  105. // Load screen border texture
  106. screenBorderFadeoutMap = effect.Parameters["screenBorderFadeoutMap"];
  107. screenBorderFadeoutMapTexture = new Texture("ScreenBorderFadeout");
  108. // Set texture
  109. screenBorderFadeoutMap.SetValue(
  110. screenBorderFadeoutMapTexture.XnaTexture);
  111. radialBlurScaleFactor = effect.Parameters["radialBlurScaleFactor"];
  112. }
  113. /// <summary>
  114. /// Execute shaders and show result on screen, Start(..) must have been
  115. /// called before and the scene should be rendered to sceneMapTexture.
  116. /// </summary>
  117. public override void Show()
  118. {
  119. // Only apply post screen glow if texture is valid and effect is valid
  120. if (sceneMapTexture == null ||
  121. effect == null ||
  122. started == false)
  123. return;
  124. started = false;
  125. // Resolve sceneMapTexture render target for Xbox360 support
  126. sceneMapTexture.Resolve();
  127. // Don't use or write to the z buffer
  128. BaseGame.Device.DepthStencilState = DepthStencilState.None;
  129. // Also don't use any kind of blending.
  130. //Update: allow writing to alpha!
  131. BaseGame.Device.BlendState = BlendStateAlphaWrite;
  132. if (windowSize != null)
  133. windowSize.SetValue(
  134. new Vector2(sceneMapTexture.Width, sceneMapTexture.Height));
  135. if (sceneMap != null)
  136. sceneMap.SetValue(sceneMapTexture.XnaTexture);
  137. RadialBlurScaleFactor =
  138. // Warning: To big values will make the motion blur look to
  139. // stepy (we see each step and thats not good). -0.02 should be max.
  140. -(0.0025f + RacingGameManager.Player.Speed * 0.005f /
  141. Player.DefaultMaxSpeed);
  142. effect.CurrentTechnique = effect.Techniques["ScreenGlow20"];
  143. // We must have exactly 5 passes!
  144. if (effect.CurrentTechnique.Passes.Count != 5)
  145. throw new InvalidOperationException(
  146. "This shader should have exactly 5 passes!");
  147. try
  148. {
  149. for (int pass = 0; pass < effect.CurrentTechnique.Passes.Count;
  150. pass++)
  151. {
  152. if (pass == 0)
  153. radialSceneMapTexture.SetRenderTarget();
  154. else if (pass == 1)
  155. downsampleMapTexture.SetRenderTarget();
  156. else if (pass == 2)
  157. blurMap1Texture.SetRenderTarget();
  158. else if (pass == 3)
  159. blurMap2Texture.SetRenderTarget();
  160. else
  161. {
  162. BaseGame.ResetRenderTarget(true);
  163. }
  164. EffectPass effectPass = effect.CurrentTechnique.Passes[pass];
  165. effectPass.Apply();
  166. // For first effect we use radial blur, draw it with a grid
  167. // to get cooler results (more blur at borders than in middle).
  168. if (pass == 0)
  169. VBScreenHelper.Render10x10Grid();
  170. else
  171. VBScreenHelper.Render();
  172. if (pass == 0)
  173. {
  174. radialSceneMapTexture.Resolve();
  175. if (radialSceneMap != null)
  176. radialSceneMap.SetValue(radialSceneMapTexture.XnaTexture);
  177. effectPass.Apply();
  178. }
  179. else if (pass == 1)
  180. {
  181. downsampleMapTexture.Resolve();
  182. if (downsampleMap != null)
  183. downsampleMap.SetValue(downsampleMapTexture.XnaTexture);
  184. effectPass.Apply();
  185. }
  186. else if (pass == 2)
  187. {
  188. blurMap1Texture.Resolve();
  189. if (blurMap1 != null)
  190. blurMap1.SetValue(blurMap1Texture.XnaTexture);
  191. effectPass.Apply();
  192. }
  193. else if (pass == 3)
  194. {
  195. blurMap2Texture.Resolve();
  196. if (blurMap2 != null)
  197. blurMap2.SetValue(blurMap2Texture.XnaTexture);
  198. effectPass.Apply();
  199. }
  200. }
  201. }
  202. finally
  203. {
  204. // Restore z buffer state
  205. BaseGame.Device.DepthStencilState = DepthStencilState.Default;
  206. }
  207. }
  208. }
  209. }