RenderContext.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. #region File Description
  2. //-----------------------------------------------------------------------------
  3. // RenderContext.cs
  4. //
  5. // Microsoft XNA Community Game Platform
  6. // Copyright (C) Microsoft Corporation. All rights reserved.
  7. //-----------------------------------------------------------------------------
  8. #endregion
  9. #region Using Statements
  10. using System;
  11. using System.Collections;
  12. using System.Collections.Generic;
  13. using Microsoft.Xna.Framework;
  14. using Microsoft.Xna.Framework.Graphics;
  15. using RobotGameData.Camera;
  16. #endregion
  17. namespace RobotGameData.Render
  18. {
  19. #region Render Tracer
  20. /// <summary>
  21. /// rendering information.
  22. /// </summary>
  23. public class RenderTracer
  24. {
  25. public GraphicsDevice Device = null;
  26. public GameTime GameTime = null;
  27. public BoundingFrustum Frustum = null;
  28. public Matrix View = Matrix.Identity;
  29. public Matrix ViewInvert = Matrix.Identity;
  30. public Matrix Projection = Matrix.Identity;
  31. public SpriteBatch SpriteBatch = null;
  32. public RenderFog Fog = null;
  33. public RenderLighting Lighting = null;
  34. }
  35. #endregion
  36. #region Render Fog
  37. /// <summary>
  38. /// fog information.
  39. /// </summary>
  40. public class RenderFog
  41. {
  42. public bool enabled = false;
  43. public float start = 1.0f;
  44. public float end = 10000.0f;
  45. public Color color = Color.White;
  46. }
  47. #endregion
  48. #region Render Lighting
  49. /// <summary>
  50. /// lighting information.
  51. /// </summary>
  52. public class RenderLighting
  53. {
  54. public bool enabled = false;
  55. public Vector3 direction = Vector3.Zero;
  56. public Color ambientColor = Color.White;
  57. public Color diffuseColor = Color.White;
  58. public Color specularColor = Color.White;
  59. }
  60. #endregion
  61. #region Render Material
  62. /// <summary>
  63. /// material information
  64. /// </summary>
  65. public class RenderMaterial
  66. {
  67. public float alpha = 1.0f;
  68. public Color diffuseColor = Color.White;
  69. public Color specularColor = Color.White;
  70. public Color emissiveColor = Color.Black;
  71. public float specularPower = 24;
  72. public bool vertexColorEnabled = false;
  73. public bool preferPerPixelLighting = false;
  74. }
  75. #endregion
  76. /// <summary>
  77. /// It has an important role of managing all of the scene objects
  78. /// and drawing on screen. scene3DRoot node manages and allows the drawing
  79. /// of all of the object nodes on 3D screen.
  80. /// There is only one scene3DRoot node in framework.
  81. /// For scene2DLayer, depending on the game content, there may be
  82. /// several scene 2D root nodes and it allows the registered
  83. /// 2D sprite nodes to be drawn. Depending on the creation,
  84. /// there may be zero or n numbers.
  85. /// The internal draw function classifies the nature of the dimension, 3D or 2D,
  86. /// and draws on screen by level.
  87. /// Also, it has Viewport and view frustum.
  88. /// </summary>
  89. public class RenderContext : DrawableGameComponent
  90. {
  91. #region Fields
  92. /// <summary>
  93. /// The scene renrder information
  94. /// </summary>
  95. RenderTracer renderTracer = new RenderTracer();
  96. SpriteBatch spriteBatch = null;
  97. /// <summary>
  98. /// The root scene node
  99. /// </summary>
  100. GameSceneNode scene3DRoot = null;
  101. /// <summary>
  102. /// The 2D scene node layer
  103. /// </summary>
  104. List<GameSceneNode> scene2DLayer = null;
  105. /// <summary>
  106. /// The 2D overlay scene layer
  107. /// </summary>
  108. List<GameSceneNode> scene2DOverlay = null;
  109. /// <summary>
  110. /// Frustum culling for render mesh
  111. /// </summary>
  112. BoundingFrustum frustum = null;
  113. /// <summary>
  114. /// color of the back buffer.
  115. /// </summary>
  116. Color clearColor = Color.Black;
  117. public event EventHandler RenderingPreDrawScene;
  118. public event EventHandler RenderingPostDrawScene;
  119. public event EventHandler RenderingPreDraw3D;
  120. public event EventHandler RenderingPostDraw3D;
  121. public event EventHandler RenderingPreDraw2D;
  122. public event EventHandler RenderingPostDraw2D;
  123. #endregion
  124. #region Properties
  125. public GameSceneNode Scene3DRoot { get { return scene3DRoot; } }
  126. public GameSceneNode[] Scene2DLayers { get { return scene2DLayer.ToArray(); } }
  127. public GameSceneNode Scene2DFadeLayer { get { return scene2DOverlay[0]; } }
  128. public GameSceneNode Scene2DTopLayer { get { return scene2DOverlay[1]; } }
  129. public SpriteBatch SpriteBatch { get { return spriteBatch; } }
  130. public BoundingFrustum Frustum { get { return frustum; } }
  131. public Color ClearColor
  132. {
  133. get { return this.clearColor; }
  134. set { this.clearColor = value; }
  135. }
  136. #endregion
  137. /// <summary>
  138. /// Constructor.
  139. /// </summary>
  140. /// <param name="game">game</param>
  141. public RenderContext(Game game)
  142. : base(game)
  143. {
  144. // Create scene root nodes
  145. scene2DLayer = new List<GameSceneNode>();
  146. scene2DOverlay = new List<GameSceneNode>();
  147. GameSceneNode SceneFade = new GameSceneNode();
  148. SceneFade.Name = "Scene2DFadeRoot";
  149. GameSceneNode SceneTop = new GameSceneNode();
  150. SceneTop.Name = "Scene2DTopRoot";
  151. scene2DOverlay.Add(SceneFade);
  152. scene2DOverlay.Add(SceneTop);
  153. scene3DRoot = new GameSceneNode();
  154. scene3DRoot.Name = "Scene3DRoot";
  155. }
  156. /// <summary>
  157. /// Allows the game component to perform any initialization
  158. /// it needs to before starting to run. This is where it can query
  159. /// for any required services and load content.
  160. /// </summary>
  161. public override void Initialize()
  162. {
  163. spriteBatch = new SpriteBatch(FrameworkCore.Game.GraphicsDevice);
  164. DefaultRenderState();
  165. base.Initialize();
  166. }
  167. /// <summary>
  168. /// Allows the game component to update itself.
  169. /// </summary>
  170. /// <param name="gameTime">Provides a snapshot of timing values.</param>
  171. public override void Update(GameTime gameTime)
  172. {
  173. // 3D Scene update
  174. scene3DRoot.Update(gameTime);
  175. // 2D Layers update
  176. for (int i = 0; i < scene2DLayer.Count; i++)
  177. scene2DLayer[i].Update(gameTime);
  178. // Overlay Layer update
  179. for (int i = 0; i < scene2DOverlay.Count; i++)
  180. scene2DOverlay[i].Update(gameTime);
  181. base.Update(gameTime);
  182. }
  183. /// <summary>
  184. /// draws every scene node which is attached to the scene node.
  185. /// Draws in order of 3D scene node, 2D scene node, and overlay text.
  186. /// When there are more than one view cameras that have registered
  187. /// to the 3D scene, Viewport is applied to the 3D scene node,
  188. /// which is drawn as many as the number of the view camera.
  189. /// When render event handler has been registered, it is called
  190. /// before or after drawing.
  191. /// </summary>
  192. public override void Draw(GameTime gameTime)
  193. {
  194. // Set to render information
  195. renderTracer.Device = FrameworkCore.Game.GraphicsDevice;
  196. renderTracer.GameTime = gameTime;
  197. renderTracer.SpriteBatch = SpriteBatch;
  198. renderTracer.Fog = FrameworkCore.Viewer.BasicFog;
  199. renderTracer.Lighting = FrameworkCore.Viewer.BasicLighting;
  200. ClearBackBuffer();
  201. if (RenderingPreDrawScene != null)
  202. {
  203. RenderingPreDrawScene(this, EventArgs.Empty);
  204. }
  205. // 3D Render
  206. {
  207. if (RenderingPreDraw3D != null)
  208. {
  209. RenderingPreDraw3D(this, EventArgs.Empty);
  210. }
  211. // process multiple camera
  212. for (int i = 0; i < FrameworkCore.CurrentCamera.Count; i++)
  213. {
  214. ViewCamera viewCamera = FrameworkCore.Viewer.CurrentCamera;
  215. CameraBase camera = viewCamera.GetCamera(i);
  216. renderTracer.View = camera.ViewMatrix;
  217. renderTracer.ViewInvert = Matrix.Invert(camera.ViewMatrix);
  218. renderTracer.Projection = camera.ProjectionMatrix;
  219. // Update frustum
  220. UpdateFrustum(camera.ViewMatrix, camera.ProjectionMatrix);
  221. renderTracer.Frustum = this.Frustum;
  222. // Set to each viewport
  223. ApplyViewport(viewCamera.GetViewport(i));
  224. // Render the 3D scene
  225. Draw3D(renderTracer);
  226. }
  227. // restore to default viewport
  228. ApplyViewport(FrameworkCore.DefaultViewport);
  229. if (RenderingPostDraw3D != null)
  230. {
  231. RenderingPostDraw3D(this, EventArgs.Empty);
  232. }
  233. }
  234. // 2D Render
  235. {
  236. if (RenderingPreDraw2D != null)
  237. {
  238. RenderingPreDraw2D(this, EventArgs.Empty);
  239. }
  240. // Render the 2D scene
  241. Draw2D(renderTracer);
  242. if (RenderingPostDraw2D != null)
  243. {
  244. RenderingPostDraw2D(this, EventArgs.Empty);
  245. }
  246. }
  247. if (RenderingPostDrawScene != null)
  248. {
  249. RenderingPostDrawScene(this, EventArgs.Empty);
  250. }
  251. // Display overlaped texts or others
  252. DrawOverlayText(gameTime);
  253. // Draw other components
  254. base.Draw(gameTime);
  255. }
  256. /// <summary>
  257. /// removes every scene node and scene layer that have been attached to
  258. /// the scene root node.
  259. /// </summary>
  260. /// <param name="disposing"></param>
  261. protected override void Dispose(bool disposing)
  262. {
  263. if (disposing)
  264. {
  265. if (spriteBatch != null)
  266. {
  267. spriteBatch.Dispose();
  268. spriteBatch = null;
  269. }
  270. }
  271. ClearScene3DRoot(disposing);
  272. ClearScene2DLayer(disposing);
  273. ClearScene2DOverlay(disposing);
  274. scene3DRoot = null;
  275. base.Dispose(disposing);
  276. }
  277. /// <summary>
  278. /// applies the specified Viewport to GraphicsDevice.
  279. /// </summary>
  280. /// <param name="viewport">a new Viewport</param>
  281. public static void ApplyViewport(Viewport viewport)
  282. {
  283. FrameworkCore.Game.GraphicsDevice.Viewport = viewport;
  284. }
  285. /// <summary>
  286. /// updates the bounding frustum.
  287. /// </summary>
  288. /// <param name="view"></param>
  289. /// <param name="proj"></param>
  290. public void UpdateFrustum(Matrix view, Matrix proj)
  291. {
  292. // Computes the bounding frustum.
  293. this.frustum = new BoundingFrustum(view * proj);
  294. }
  295. /// <summary>
  296. /// returns the 2D scene layer of the specified index.
  297. /// </summary>
  298. /// <param name="index">an index of 2D scene layer</param>
  299. public GameSceneNode GetScene2DLayer(int index)
  300. {
  301. if (scene2DLayer.Count - 1 < index)
  302. {
  303. throw new ArgumentException(
  304. "Cannot return a 2D layer. Invalid index (" +
  305. index.ToString() + ")");
  306. }
  307. return scene2DLayer[index];
  308. }
  309. /// <summary>
  310. /// creates new 2D scene layers.
  311. /// </summary>
  312. /// <param name="count">count of layers</param>
  313. public void CreateScene2DLayer(int count)
  314. {
  315. for (int i = 0; i < count; i++)
  316. {
  317. scene2DLayer.Add(new GameSceneNode());
  318. }
  319. }
  320. /// <summary>
  321. /// clears all 2D scene layers.
  322. /// </summary>
  323. public void ClearScene2DLayer(bool disposing)
  324. {
  325. if (disposing )
  326. {
  327. for (int i = 0; i < scene2DLayer.Count; i++)
  328. scene2DLayer[i].Dispose();
  329. }
  330. scene2DLayer.Clear();
  331. }
  332. /// <summary>
  333. /// clears 2D overlay layer.
  334. /// </summary>
  335. /// <param name="disposing"></param>
  336. public void ClearScene2DOverlay(bool disposing)
  337. {
  338. if (disposing )
  339. {
  340. for (int i = 0; i < scene2DOverlay.Count; i++)
  341. scene2DOverlay[i].Dispose();
  342. }
  343. scene2DOverlay.Clear();
  344. }
  345. /// <summary>
  346. /// clears 3D scene layer.
  347. /// </summary>
  348. public void ClearScene3DRoot(bool disposing)
  349. {
  350. if (scene3DRoot != null)
  351. {
  352. if( disposing)
  353. scene3DRoot.Dispose();
  354. scene3DRoot.RemoveAllChild(true);
  355. }
  356. }
  357. /// <summary>
  358. /// sets render target.
  359. /// </summary>
  360. /// <param name="index">an index of render target</param>
  361. /// <param name="renderTarget"></param>
  362. public void SetRenderTarget(int index, RenderTarget2D renderTarget)
  363. {
  364. GraphicsDevice.SetRenderTarget(index, renderTarget);
  365. }
  366. /// <summary>
  367. /// clears the back buffer of viewport.
  368. /// </summary>
  369. public void ClearBackBuffer()
  370. {
  371. // Screen clear
  372. FrameworkCore.Game.GraphicsDevice.Clear(ClearOptions.Target |
  373. ClearOptions.DepthBuffer,
  374. ClearColor, 1.0f, 0);
  375. }
  376. /// <summary>
  377. /// sets the default render target.
  378. /// </summary>
  379. public void RestoreDefaultRenderTarget()
  380. {
  381. GraphicsDevice.SetRenderTarget(0, null);
  382. }
  383. /// <summary>
  384. /// draws the 3D scene.
  385. /// </summary>
  386. protected void Draw3D(RenderTracer renderTracer)
  387. {
  388. DefaultRenderState();
  389. // Draw all 3D objects
  390. scene3DRoot.Draw(renderTracer);
  391. }
  392. /// <summary>
  393. /// draws the 2D scene.
  394. /// </summary>
  395. protected void Draw2D(RenderTracer renderTracer)
  396. {
  397. spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
  398. // Draw all 2D objects
  399. for (int i = 0; i < scene2DLayer.Count; i++)
  400. scene2DLayer[i].Draw(renderTracer);
  401. // Draw all 2D overlay
  402. for (int i = 0; i < scene2DOverlay.Count; i++)
  403. scene2DOverlay[i].Draw(renderTracer);
  404. spriteBatch.End();
  405. }
  406. /// <summary>
  407. /// draws the overlay text.
  408. /// </summary>
  409. protected static void DrawOverlayText(GameTime gameTime)
  410. {
  411. // Overlay text on screen
  412. FrameworkCore.TextManager.Draw(gameTime);
  413. }
  414. /// <summary>
  415. /// sets default render state.
  416. /// </summary>
  417. protected static void DefaultRenderState()
  418. {
  419. GraphicsDevice device = FrameworkCore.Game.GraphicsDevice;
  420. device.RenderState.DepthBufferEnable = true;
  421. device.RenderState.DepthBufferWriteEnable = true;
  422. device.SamplerStates[0].AddressU = TextureAddressMode.Wrap;
  423. device.SamplerStates[0].AddressV = TextureAddressMode.Wrap;
  424. // Set to alpha blending
  425. device.RenderState.AlphaTestEnable = true;
  426. device.RenderState.AlphaBlendEnable = true;
  427. device.RenderState.SourceBlend = Blend.SourceAlpha;
  428. device.RenderState.DestinationBlend = Blend.InverseSourceAlpha;
  429. device.RenderState.BlendFunction = BlendFunction.Add;
  430. device.RenderState.CullMode = CullMode.CullCounterClockwiseFace;
  431. device.RenderState.StencilEnable = false;
  432. // Set 0 and greater alpha compare
  433. device.RenderState.ReferenceAlpha = 0;
  434. device.RenderState.AlphaFunction = CompareFunction.Greater;
  435. }
  436. }
  437. }