DeferredRendering.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. using System;
  2. using nkast.Aether.Shaders;
  3. using Microsoft.Xna.Framework;
  4. using Microsoft.Xna.Framework.Graphics;
  5. using Microsoft.Xna.Framework.Content;
  6. namespace Samples.Deferred
  7. {
  8. public class DeferredRendering
  9. {
  10. GraphicsDevice _graphicsDevice;
  11. private QuadRenderComponent quadRenderer;
  12. public RenderTarget2D colorRT; // color and specular intensity
  13. public RenderTarget2D normalRT; // normals + specular power
  14. public RenderTarget2D depthRT; // depth
  15. public RenderTarget2D lightRT; // lighting
  16. public DeferredBasicEffect basicEffect;
  17. private DeferredClearGBufferEffect clearBufferEffect;
  18. private DeferredPointLightEffect pointLightEffect;
  19. private DeferredSpotLightEffect spotLightEffect;
  20. private DeferredCombineEffect combineEffect;
  21. private Model sphereModel; //point ligt volume
  22. private Vector2 halfPixel;
  23. public DeferredRendering(GraphicsDevice graphicsDevice, ContentManager content)
  24. {
  25. _graphicsDevice = graphicsDevice;
  26. quadRenderer = new QuadRenderComponent(graphicsDevice);
  27. halfPixel = new Vector2()
  28. {
  29. X = 0.5f / (float)graphicsDevice.PresentationParameters.BackBufferWidth,
  30. Y = 0.5f / (float)graphicsDevice.PresentationParameters.BackBufferHeight
  31. };
  32. int backbufferWidth = graphicsDevice.PresentationParameters.BackBufferWidth;
  33. int backbufferHeight = graphicsDevice.PresentationParameters.BackBufferHeight;
  34. colorRT = new RenderTarget2D(graphicsDevice, backbufferWidth, backbufferHeight, false, SurfaceFormat.Color, DepthFormat.Depth24);
  35. normalRT = new RenderTarget2D(graphicsDevice, backbufferWidth, backbufferHeight, false, SurfaceFormat.Color, DepthFormat.None);
  36. depthRT = new RenderTarget2D(graphicsDevice, backbufferWidth, backbufferHeight, false, SurfaceFormat.Single, DepthFormat.None);
  37. lightRT = new RenderTarget2D(graphicsDevice, backbufferWidth, backbufferHeight, false, SurfaceFormat.Color, DepthFormat.None);
  38. basicEffect = new DeferredBasicEffect(graphicsDevice);
  39. clearBufferEffect = new DeferredClearGBufferEffect(graphicsDevice);
  40. combineEffect = new DeferredCombineEffect(graphicsDevice);
  41. pointLightEffect = new DeferredPointLightEffect(graphicsDevice);
  42. spotLightEffect = new DeferredSpotLightEffect(graphicsDevice);
  43. sphereModel = content.Load<Model>(@"sphere");
  44. }
  45. internal void DrawRTs(SpriteBatch spriteBatch)
  46. {
  47. float height = this._graphicsDevice.Viewport.Height / 8;
  48. float scale = height/colorRT.Height;
  49. Vector2 pos = new Vector2(0, height);
  50. Vector2 off = new Vector2(0, this._graphicsDevice.Viewport.Height - height*4);
  51. spriteBatch.Draw(colorRT, pos * 0 + off, null, Color.White, 0f, Vector2.Zero, scale, SpriteEffects.None, 0);
  52. spriteBatch.Draw(normalRT,pos * 1 + off, null, Color.White, 0f, Vector2.Zero, scale, SpriteEffects.None, 0);
  53. spriteBatch.Draw(depthRT, pos * 2 + off, null, Color.White, 0f, Vector2.Zero, scale, SpriteEffects.None, 0);
  54. spriteBatch.Draw(lightRT, pos * 3 + off, null, Color.White, 0f, Vector2.Zero, scale, SpriteEffects.None, 0);
  55. }
  56. internal void SetGBuffer()
  57. {
  58. _graphicsDevice.SetRenderTargets(colorRT, normalRT, depthRT);
  59. }
  60. internal void ClearGBuffer()
  61. {
  62. _graphicsDevice.Clear(Color.Black);
  63. clearBufferEffect.CurrentTechnique.Passes[0].Apply();
  64. quadRenderer.Render(Vector2.One * -1, Vector2.One);
  65. }
  66. internal void ResolveGBuffer()
  67. {
  68. _graphicsDevice.SetRenderTargets(null);
  69. }
  70. internal void Combine()
  71. {
  72. _graphicsDevice.BlendState = BlendState.Opaque;
  73. _graphicsDevice.DepthStencilState = DepthStencilState.None;
  74. _graphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
  75. _graphicsDevice.SetRenderTarget(null);
  76. _graphicsDevice.Clear(Color.Black);
  77. //Combine everything
  78. combineEffect.ColorMap = colorRT;
  79. combineEffect.LightMap = lightRT;
  80. combineEffect.HalfPixel = halfPixel;
  81. combineEffect.CurrentTechnique.Passes[0].Apply();
  82. quadRenderer.Render(Vector2.One * -1, Vector2.One);
  83. }
  84. public void DrawPointLight(Vector3 lightPosition, Color color, float lightRadius, float lightIntensity, Matrix view, Matrix projection, Vector3 cameraPosition)
  85. {
  86. //set the G-Buffer parameters
  87. pointLightEffect.ColorMap = colorRT;
  88. pointLightEffect.NormalMap = normalRT;
  89. pointLightEffect.DepthMap = depthRT;
  90. //compute the light world matrix
  91. //scale according to light radius, and translate it to light position
  92. Matrix sphereWorldMatrix = Matrix.CreateScale(lightRadius) * Matrix.CreateTranslation(lightPosition);
  93. pointLightEffect.World = sphereWorldMatrix;
  94. pointLightEffect.View = view;
  95. pointLightEffect.Projection = projection;
  96. //light position
  97. pointLightEffect.LightPosition = lightPosition;
  98. //set the color, radius and Intensity
  99. pointLightEffect.Color = color.ToVector3();
  100. pointLightEffect.LightRadius = lightRadius;
  101. pointLightEffect.LightIntensity = lightIntensity;
  102. //parameters for specular computations
  103. pointLightEffect.CameraPosition = cameraPosition;
  104. pointLightEffect.InvertViewProjection = Matrix.Invert(view * projection);
  105. //size of a halfpixel, for texture coordinates alignment
  106. pointLightEffect.HalfPixel = halfPixel;
  107. _graphicsDevice.RasterizerState = RasterizerState.CullNone;
  108. _graphicsDevice.DepthStencilState = DepthStencilState.None;
  109. _graphicsDevice.BlendState = BlendState.AlphaBlend;
  110. pointLightEffect.CurrentTechnique.Passes[0].Apply();
  111. foreach (ModelMesh mesh in sphereModel.Meshes)
  112. {
  113. foreach (ModelMeshPart meshPart in mesh.MeshParts)
  114. {
  115. _graphicsDevice.Indices = meshPart.IndexBuffer;
  116. _graphicsDevice.SetVertexBuffer(meshPart.VertexBuffer);
  117. _graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount);
  118. }
  119. }
  120. _graphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
  121. _graphicsDevice.DepthStencilState = DepthStencilState.Default;
  122. _graphicsDevice.BlendState = BlendState.Opaque;
  123. }
  124. public void DrawSpotLight(Vector3 lightPosition, Color color, float lightRadius, float lightIntensity,
  125. Vector3 lightDirection, float innerAngle, float outerAngle, Matrix view, Matrix projection, Vector3 cameraPosition)
  126. {
  127. //set the G-Buffer parameters
  128. spotLightEffect.ColorMap = colorRT;
  129. spotLightEffect.NormalMap = normalRT;
  130. spotLightEffect.DepthMap = depthRT;
  131. //compute the light world matrix
  132. //scale according to light radius, and translate it to light position
  133. Matrix sphereWorldMatrix = Matrix.CreateScale(lightRadius) * Matrix.CreateTranslation(lightPosition);
  134. spotLightEffect.World = sphereWorldMatrix;
  135. spotLightEffect.View = view;
  136. spotLightEffect.Projection = projection;
  137. //light position
  138. spotLightEffect.LightPosition = lightPosition;
  139. //light direction
  140. spotLightEffect.LightDirection = lightDirection;
  141. //spot light
  142. if (innerAngle == outerAngle) innerAngle -= innerAngle / 360f;
  143. spotLightEffect.InnerAngleCos = (float)Math.Cos(innerAngle);
  144. spotLightEffect.OuterAngleCos = (float)Math.Cos(outerAngle);
  145. //set the color, radius and Intensity
  146. spotLightEffect.Color = color.ToVector3();
  147. spotLightEffect.LightRadius = lightRadius;
  148. spotLightEffect.LightIntensity = lightIntensity;
  149. //parameters for specular computations
  150. spotLightEffect.CameraPosition = cameraPosition;
  151. spotLightEffect.InvertViewProjection = Matrix.Invert(view * projection);
  152. //size of a halfpixel, for texture coordinates alignment
  153. spotLightEffect.HalfPixel = halfPixel;
  154. _graphicsDevice.RasterizerState = RasterizerState.CullNone;
  155. _graphicsDevice.DepthStencilState = DepthStencilState.None;
  156. _graphicsDevice.BlendState = BlendState.AlphaBlend;
  157. spotLightEffect.CurrentTechnique.Passes[0].Apply();
  158. foreach (ModelMesh mesh in sphereModel.Meshes)
  159. {
  160. foreach (ModelMeshPart meshPart in mesh.MeshParts)
  161. {
  162. _graphicsDevice.Indices = meshPart.IndexBuffer;
  163. _graphicsDevice.SetVertexBuffer(meshPart.VertexBuffer);
  164. _graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, meshPart.NumVertices, meshPart.StartIndex, meshPart.PrimitiveCount);
  165. }
  166. }
  167. _graphicsDevice.RasterizerState = RasterizerState.CullCounterClockwise;
  168. _graphicsDevice.DepthStencilState = DepthStencilState.Default;
  169. _graphicsDevice.BlendState = BlendState.Opaque;
  170. }
  171. }
  172. }