//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- namespace DarkWynter.Stream { #region Using Statements using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Audio; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Microsoft.Xna.Framework.Input; using Microsoft.Xna.Framework.Storage; #endregion /// /// Handles all render operations /// public class Renderer { /// /// Used in Menu System /// public SpriteBatch spriteBatch; private static RenderTarget2D renderTarget; // Primary Render target private VertexBuffer vertexBuffer; // Buffer to store vertices private VertexPositionTexture[] vertices; // Array to store vertex Position, Normal and Texture information private VertexDeclaration vertexDeclaration; // Vertex Declaration private int totalPlayers; /// /// Delegate function to draw all world objects. /// /// Camera number public delegate List DrawObjectLibrary(int cameraNumber); /// /// Delegate function to draw all screen objects. /// /// Player index public delegate List DrawSprites(int playerIndex); /// /// Draw HUD delegate type /// /// /// public delegate void DrawHUD(int playerIndex, SpriteBatch spriteBatch); /// /// Draw Object Library delegate /// public DrawObjectLibrary drawObjectLibrary; /// /// Draw Sprites delegate /// public DrawSprites drawSprites; /// /// Draw HUD delegate /// public DrawHUD drawHUD; /// /// Constructor /// public Renderer(ContentManager content) { GraphicsDevice graphicsDevice = Statics_Stream.RenderSettings.graphics.GraphicsDevice; // Set up the menu system components spriteBatch = new SpriteBatch(Statics_Stream.RenderSettings.graphics.GraphicsDevice); // Create Vertex Declaration, Buffer, and Array vertexDeclaration = new VertexDeclaration(graphicsDevice, VertexPositionTexture.VertexElements); vertexBuffer = new VertexBuffer(graphicsDevice, VertexPositionTexture.SizeInBytes * 4, BufferUsage.WriteOnly); vertices = new VertexPositionTexture[4]; // Create quad with width and height = 1 vertices[0] = new VertexPositionTexture(new Vector3(0.0f, 0.0f, 0.0f), new Vector2(0.0f, 1.0f)); vertices[1] = new VertexPositionTexture(new Vector3(1.0f, 0.0f, 0.0f), new Vector2(1.0f, 1.0f)); vertices[2] = new VertexPositionTexture(new Vector3(1.0f, 1.0f, 0.0f), new Vector2(1.0f, 0.0f)); vertices[3] = new VertexPositionTexture(new Vector3(0.0f, 1.0f, 0.0f), new Vector2(0.0f, 0.0f)); // Set the data vertexBuffer.SetData(vertices); } #region Draw Pipeline Functions /// /// Render to the render target once for each user's viewport calling ObjectLibrary's draw functions and /// at the same time render the depth buffer to another render target /// /// Total number of humans in the game public void Draw(int totplayers) { totalPlayers = totplayers; // Set up state GraphicsDevice graphicsDevice = Statics_Stream.RenderSettings.graphics.GraphicsDevice; graphicsDevice.Clear(Color.Black); graphicsDevice.RenderState.DepthBufferEnable = true; try { // Enable Render To Texture graphicsDevice.SetRenderTarget(0, renderTarget); } catch { AutoDetectResolution(); } // Draw GameObjects to the framebuffer Draw_ObjectLibrary(graphicsDevice); // Draw Post Process Sprites and HUD Draw_Sprites(graphicsDevice); // Disable Render To Texture graphicsDevice.SetRenderTarget(0, null); // Store rendered image in modelTexture1 ShaderParameters.DrawFX.modelTexture1.SetValue(renderTarget.GetTexture()); // Set viewport matrices based on Zoom level SetZoomLevel(graphicsDevice); // Draw Post Process Shader Effects on modelTexture1 Draw_PostProcessEffects(graphicsDevice); // Draw Heads Up Display Draw_HUD(graphicsDevice, spriteBatch); // Draw Borders around the screen Draw_Borders(graphicsDevice, spriteBatch); } private void Draw_ObjectLibrary(GraphicsDevice graphicsDevice) { // Draw all objects for each player's viewport for (int cameraNumber = 0; cameraNumber < Statics_Stream.RenderSettings.cameraList.Count; cameraNumber++) { Statics_Stream.RenderSettings.cameraList[cameraNumber].viewport.Width = Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH; Statics_Stream.RenderSettings.cameraList[cameraNumber].viewport.Height = Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT; graphicsDevice.Viewport = Statics_Stream.RenderSettings.cameraList[cameraNumber].viewport; graphicsDevice.Clear(new Color(15, 25, 20)); //===\ Game Object Draw / === //objectLibrary.Draw(cameraNumber); List drawList = drawObjectLibrary(cameraNumber); foreach (Draw drawObject in drawList) { if (drawObject != null) { drawObject.DoDraw(); } } } } private void Draw_Sprites(GraphicsDevice graphicsDevice) { // Draw all objects for each player's viewport for (int playerIndex = 0; playerIndex < Statics_Stream.RenderSettings.cameraList.Count; playerIndex++) { Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport = Statics_Stream.RenderSettings.cameraList[playerIndex].viewport; // ObjectLibrary PostDraw_Sprites //objectLibrary.Draw_Billboards(playerIndex); List drawList = drawSprites(playerIndex); foreach (Draw drawObject in drawList) { if (drawObject != null) { drawObject.DoDraw(); } } } } private void Draw_HUD(GraphicsDevice graphicsDevice, SpriteBatch spriteBatch) { // Draw each player's HUD on top of everything for (int playerIndex = 0; playerIndex < totalPlayers; playerIndex++) { spriteBatch.Begin(SpriteBlendMode.AlphaBlend); graphicsDevice.Viewport = Statics_Stream.RenderSettings.cameraList[playerIndex].viewport; // Post Draw for Humans //objectLibrary.PostDraw_HUD(i, spriteBatch); drawHUD(playerIndex, spriteBatch); spriteBatch.End(); } } private void Draw_PostProcessEffects(GraphicsDevice graphicsDevice) { graphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionTexture.SizeInBytes); graphicsDevice.Clear(ClearOptions.Target, Color.Black, 1.0f, 0); // Setup view and projection matrixes Statics_Stream.RenderSettings.matrixView = Matrix.CreateLookAt(Vector3.Backward, Vector3.Zero, Vector3.Up); // Set all the different shader parameter for Anti-Aliasing ShaderParameters.DrawFX.ViewProj.SetValue(Statics_Stream.RenderSettings.matrixView * Statics_Stream.RenderSettings.matrixProjection); ShaderParameters.DrawFX.World.SetValue(Statics_Stream.RenderSettings.matrixPosition); ShaderParameters.DrawFX.effect.CurrentTechnique = ShaderParameters.DrawFX.effect.Techniques["DrawQuad"]; // Render our quad ShaderParameters.DrawFX.effect.Begin(); foreach (EffectPass pass in ShaderParameters.DrawFX.effect.CurrentTechnique.Passes) { pass.Begin(); graphicsDevice.VertexDeclaration = vertexDeclaration; graphicsDevice.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2); pass.End(); } ShaderParameters.DrawFX.effect.End(); } private void Draw_Borders(GraphicsDevice graphicsDevice, SpriteBatch spriteBatch) { // Draw the borders on the screen graphicsDevice.Viewport = Statics_Stream.RenderSettings.defaultViewport; spriteBatch.Begin(SpriteBlendMode.AlphaBlend); spriteBatch.End(); } #endregion #region Utilities private void SetZoomLevel(GraphicsDevice graphicsDevice) { // If Zoom enables - HACKED ! if (Statics_Stream.RenderSettings.zoomEnabled) { Statics_Stream.RenderSettings.matrixProjection = Matrix.CreateOrthographic(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height, 1, 10000); Statics_Stream.RenderSettings.matrixPosition = Matrix.CreateScale(graphicsDevice.Viewport.Width * Statics_Stream.RenderSettings.zoomFactor, graphicsDevice.Viewport.Height * Statics_Stream.RenderSettings.zoomFactor, 1) * Matrix.CreateTranslation(-graphicsDevice.Viewport.Width, -graphicsDevice.Viewport.Height, 0.0f); } else { Statics_Stream.RenderSettings.matrixProjection = Matrix.CreateOrthographic(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height, 1, 10000); Statics_Stream.RenderSettings.matrixPosition = Matrix.CreateScale(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height, 1) * Matrix.CreateTranslation(-graphicsDevice.Viewport.Width / 2.0f, -graphicsDevice.Viewport.Height / 2.0f, 0.0f); } } /// /// Set up for 1280 or 1024 Resolution. /// Supports both 4:3 and Widescreen format /// public static void AutoDetectResolution() { // Check the display mode to see how big the resolution int displayWidth = Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.Width; int displayHeight = Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.Height; // Primary render target. Everything drawn in the player viewport's will be rendered to this target renderTarget = new RenderTarget2D(Statics_Stream.RenderSettings.graphics.GraphicsDevice, Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.Width, Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.Height, 1, SurfaceFormat.Color); /* #if XBOX360 Statics.RenderSettings.GAME_WINDOW_WIDTH = displayWidth; Statics.RenderSettings.GAME_WINDOW_HEIGHT = displayHeight; #else //Auto detect best resolution if (displayWidth >= 1280) { // 720p Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH = 1280; if (displayHeight >= 1024) { // 4:3 resolution Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT = 1024; } else { // Widescreen Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT = 720; } } else if (displayWidth >= 1024) { // something in between Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH = 1024; Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT = 768; } else { // Default to 480p if (displayWidth > 700) { Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH = 800; } else { Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH = 640; } if (displayHeight >= 600) { Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT = 600; } else { Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT = 480; } } #endif */ Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH = displayWidth; Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT = displayHeight; Statics_Stream.RenderSettings.graphics.PreferredBackBufferWidth = Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH; Statics_Stream.RenderSettings.graphics.PreferredBackBufferHeight = Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT; Statics_Stream.RenderSettings.graphics.ApplyChanges(); } /// /// Set up the best settings for Window and ViewPort /// public static void AutoDetectWindowAndDefaultViewport(/*GameWindow Window*/) { // Set up window Statics_Stream.RenderSettings.clientWidth = Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH; Statics_Stream.RenderSettings.clientHeight = Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT; // Window.ClientBounds.Height; Statics_Stream.RenderSettings.clientMinDepth = Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.MinDepth; Statics_Stream.RenderSettings.clientMaxDepth = Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.MaxDepth; // Set the default viewport Statics_Stream.RenderSettings.defaultViewport.X = 0; Statics_Stream.RenderSettings.defaultViewport.Y = 0; Statics_Stream.RenderSettings.defaultViewport.Width = Statics_Stream.RenderSettings.clientWidth; Statics_Stream.RenderSettings.defaultViewport.Height = Statics_Stream.RenderSettings.clientHeight; Statics_Stream.RenderSettings.defaultViewport.MinDepth = Statics_Stream.RenderSettings.clientMinDepth; Statics_Stream.RenderSettings.defaultViewport.MaxDepth = Statics_Stream.RenderSettings.clientMaxDepth; } /// /// Resets all the player viewports based on the number of players currently in-game /// /// Number of players public static void ResetViewports(int numPlayers) { Renderer.AutoDetectResolution(); Renderer.AutoDetectWindowAndDefaultViewport(/*Window*/); Statics_Stream.RenderSettings.cameraList.Clear(); // All viewports needed for the players Camera blankCamera = new Camera(); int viewportWidth, viewportHeight; // Divide the viewport based on number of players if (numPlayers > 2) { // Divide width viewportWidth = Statics_Stream.RenderSettings.clientWidth / 2; } else { viewportWidth = Statics_Stream.RenderSettings.clientWidth; } if (numPlayers > 1) { // Divide height viewportHeight = Statics_Stream.RenderSettings.clientHeight / 2; } else { viewportHeight = Statics_Stream.RenderSettings.clientHeight; } // Assign each viewport its screen space for (int i = 0; i < numPlayers; i++) { if (numPlayers > 2) { blankCamera.viewport.X = (i % 2) * viewportWidth; blankCamera.viewport.Y = (i / 2) * viewportHeight; } else { blankCamera.viewport.X = 0; blankCamera.viewport.Y = (i % 2) * viewportHeight; } blankCamera.viewport.Width = viewportWidth; blankCamera.viewport.Height = viewportHeight; blankCamera.viewport.MinDepth = Statics_Stream.RenderSettings.clientMinDepth; blankCamera.viewport.MaxDepth = Statics_Stream.RenderSettings.clientMaxDepth; // Set the targeting reticle for the player based on this viewport //gameFlow.objectLibrary.humans[i].CreateHUD(newViewport, content); // Add to the global viewport list Statics_Stream.RenderSettings.cameraList.Add(blankCamera); } } /// /// Reset rendering options to support 3D drawing. /// public void DisableSpriteBatches() { // Make sure culling is off Statics_Stream.RenderSettings.graphics.GraphicsDevice.RenderState.CullMode = CullMode.None; // Fix the render state post drawing sprite batch Statics_Stream.RenderSettings.graphics.GraphicsDevice.RenderState.DepthBufferEnable = true; Statics_Stream.RenderSettings.graphics.GraphicsDevice.RenderState.AlphaBlendEnable = false; Statics_Stream.RenderSettings.graphics.GraphicsDevice.RenderState.AlphaTestEnable = false; // Set the Texture addressing mode Statics_Stream.RenderSettings.graphics.GraphicsDevice.SamplerStates[0].AddressU = Statics_Stream.RenderSettings.graphics.GraphicsDevice.SamplerStates[0].AddressV = Statics_Stream.RenderSettings.graphics.GraphicsDevice.SamplerStates[0].AddressW = TextureAddressMode.Wrap; Statics_Stream.RenderSettings.graphics.GraphicsDevice.SamplerStates[0].MagFilter = TextureFilter.Anisotropic; Statics_Stream.RenderSettings.graphics.GraphicsDevice.SamplerStates[0].MinFilter = TextureFilter.Anisotropic; Statics_Stream.RenderSettings.graphics.GraphicsDevice.SamplerStates[0].MipFilter = TextureFilter.Anisotropic; // Release resources locked by XNA for (int n = 0; n < 16; n++) { Statics_Stream.RenderSettings.graphics.GraphicsDevice.Textures[n] = null; } } #endregion } }