/ShevaEngine2/Modules/Graphics/ShadowMaps/DualParaboloidShadowMaps.cs

http://shevaengine.codeplex.com · C# · 157 lines · 95 code · 33 blank · 29 comment · 4 complexity · 074dbec9e506c8b47d54c5458dc542b1 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using Microsoft.Xna.Framework;
  4. using Microsoft.Xna.Framework.Graphics;
  5. using ShevaEngine.Core.Modules.Graphics.Lights;
  6. using ShevaEngine.Core.Modules.Materials;
  7. using ShevaEngine.Core.Modules.Scenes;
  8. namespace ShevaEngine.Core.Modules.Graphics.ShadowMaps
  9. {
  10. /// <summary>
  11. /// Dual paraboloid shadow maps.
  12. /// </summary>
  13. public class DualParaboloidShadowMaps : ShadowMap
  14. {
  15. /// <summary>Shadow map.</summary>
  16. public RenderTarget2D ShadowMapTop;
  17. /// <summary>Shadow map.</summary>
  18. public RenderTarget2D ShadowMapBottom;
  19. /// <summary>Shadow map size.</summary>
  20. public Int32 ShadowMapSize;
  21. /// <summary>Light.</summary>
  22. public Light Light;
  23. /// <summary>Scene.</summary>
  24. public Scene Scene;
  25. /// <summary>Light camera.</summary>
  26. private Matrix LightViewCamera;
  27. /// <summary>Shadow map effect.</summary>
  28. private Effect ShadowMapEffect;
  29. /// <summary>Last draw call.</summary>
  30. private DrawCallKey LastDrawCallKey;
  31. /// <summary>Initial draw call.</summary>
  32. private DrawCallKey InitialDrawCallKey;
  33. /// <summary>
  34. /// Constructor.
  35. /// </summary>
  36. public DualParaboloidShadowMaps(Light light, Scene scene)
  37. {
  38. this.ShadowMapSize = 512;
  39. this.ShadowMapTop = new RenderTarget2D(ShevaEngine.Instance.GraphicsDevice,
  40. ShadowMapSize, ShadowMapSize, false, SurfaceFormat.Single, DepthFormat.Depth24Stencil8);
  41. this.ShadowMapBottom = new RenderTarget2D(ShevaEngine.Instance.GraphicsDevice,
  42. ShadowMapSize, ShadowMapSize, false, SurfaceFormat.Single, DepthFormat.Depth24Stencil8);
  43. this.Light = light;
  44. this.Scene = scene;
  45. this.ShadowMapEffect = MaterialManager.Instance.GetEffect("DualParaboloidSM");
  46. this.InitialDrawCallKey = new DrawCallKey(
  47. UInt16.MaxValue, UInt16.MaxValue, UInt16.MaxValue, UInt16.MaxValue);
  48. }
  49. /// <summary>
  50. /// Method creates shadow map.
  51. /// </summary>
  52. public override void CreateShadowMap()
  53. {
  54. ShevaEngine.Instance.GraphicsDevice.SetRenderTarget(this.ShadowMapTop);
  55. ShevaEngine.Instance.GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Target, Color.White, 1.0f, 1);
  56. ShevaEngine.Instance.GraphicsDevice.BlendState = BlendState.Opaque;
  57. //GraphicsEngine.Instance.GraphicsDevice.RenderState.AlphaBlendEnable = false;
  58. DepthStencilState depthStencilState = new DepthStencilState();
  59. depthStencilState.DepthBufferEnable = true;
  60. depthStencilState.DepthBufferWriteEnable = true;
  61. depthStencilState.DepthBufferFunction = CompareFunction.Less;
  62. ShevaEngine.Instance.GraphicsDevice.DepthStencilState = depthStencilState;
  63. {
  64. RasterizerState rasterizerState = new RasterizerState();
  65. rasterizerState.CullMode = CullMode.CullCounterClockwiseFace;
  66. ShevaEngine.Instance.GraphicsDevice.RasterizerState = rasterizerState;
  67. }
  68. RenderingPipeline pipeline = this.Scene.GetRenderingPipeline(this.LightViewCamera);
  69. this.LightViewCamera = Matrix.CreateLookAt(
  70. this.Light.World.Translation, this.Light.World.Translation - new Vector3(0, 1, 0), Vector3.UnitZ);
  71. this.ShadowMapEffect.Parameters["ShadowMapFarPlane"].SetValue(this.Light.Radius);
  72. this.ShadowMapEffect.Parameters["View"].SetValue(this.LightViewCamera);
  73. this.ShadowMapEffect.Parameters["ShadowMapDirection"].SetValue(1.0f);
  74. this.ShadowMapEffect.CurrentTechnique.Passes[0].Apply();
  75. this.RenderPipeline(pipeline);
  76. ShevaEngine.Instance.GraphicsDevice.SetRenderTarget(this.ShadowMapBottom);
  77. ShevaEngine.Instance.GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Target, Color.White, 1.0f, 1);
  78. {
  79. RasterizerState rasterizerState = new RasterizerState();
  80. rasterizerState.CullMode = CullMode.CullClockwiseFace;
  81. ShevaEngine.Instance.GraphicsDevice.RasterizerState = rasterizerState;
  82. }
  83. this.ShadowMapEffect.Parameters["ShadowMapDirection"].SetValue(-1.0f);
  84. this.RenderPipeline(pipeline);
  85. ShevaEngine.Instance.GraphicsDevice.SetRenderTarget(null);
  86. }
  87. /// <summary>
  88. /// Render pipeline method.
  89. /// </summary>
  90. private void RenderPipeline(RenderingPipeline pipeline)
  91. {
  92. this.LastDrawCallKey = this.InitialDrawCallKey;
  93. foreach (KeyValuePair<DrawCallKey, List<DrawCallPipeline>> item in pipeline.OpaqueObjects)
  94. {
  95. if (item.Key.TextureState != this.LastDrawCallKey.TextureState)
  96. {
  97. TextureState textureState = TextureManager.Instance[item.Key.TextureState];
  98. //if (textureState.ContainsKey("Diffuse"))
  99. // this.ShadowMapEffect.Parameters["Diffuse"].SetValue(textureState["Diffuse"]);
  100. }
  101. this.Scene.GraphicsBuffersManager.SetBuffers(item.Key.BuffersID);
  102. this.RenderDrawCalls(item.Value);
  103. }
  104. }
  105. /// <summary>
  106. /// Method renders draw call.
  107. /// </summary>
  108. /// <param name="drawCall"></param>
  109. /// <param name="worldMatrices"></param>
  110. private void RenderDrawCalls(List<DrawCallPipeline> pipeline)
  111. {
  112. for (int drawCallIndex = 0; drawCallIndex < pipeline.Count; drawCallIndex++)
  113. {
  114. int matricesCount = pipeline[drawCallIndex].WorldMatrices.Count;
  115. for (int i = 0; i < matricesCount; i++)
  116. {
  117. this.ShadowMapEffect.Parameters["World"].SetValue(pipeline[drawCallIndex].WorldMatrices[i]);
  118. this.ShadowMapEffect.CurrentTechnique.Passes[0].Apply();
  119. pipeline[drawCallIndex].DrawCall.Render();
  120. }
  121. }
  122. }
  123. }
  124. }