//---------------------------------------------------------------------------------------------------------------------------------------------------
//
// Copyright (C)2007 DarkWynter Studios. All rights reserved.
//
//---------------------------------------------------------------------------------------------------------------------------------------------------
// {Contact : darkwynter.com for licensing information
//---------------------------------------------------------------------------------------------------------------------------------------------------
namespace DarkWynterEngine.Draw
{
#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
using UserInterface;
using ObjectLib;
using Globals;
///
/// Handles all render operations
///
public class Renderer
{
///
/// Used in Menu System
///
public SpriteBatch spriteBatch;
private HeadsUpDisplay viewPortBordersHUD = new HeadsUpDisplay();
private RenderTarget2D renderTarget; // Primary Render target
private RenderTarget2D shadowMapTarget1; // Primary Render target
private RenderTarget2D shadowMapTarget2; // Primary Render target
private VertexBuffer vertexBuffer; // Buffer to store vertices
private VertexPositionNormalTexture[] vertices; // Array to store vertex Position, Normal and Texture information
private VertexDeclaration vertexDeclaration; // Vertex Declaration
///
/// Constructor
///
public Renderer()
{
GraphicsDevice graphicsDevice = Statics.SystemSettings.graphics.GraphicsDevice;
// Primary render target. Everything drawn in the player viewport's will be rendered to this target
shadowMapTarget1 = new RenderTarget2D(graphicsDevice,
Statics.SystemSettings.graphics.GraphicsDevice.Viewport.Width,
Statics.SystemSettings.graphics.GraphicsDevice.Viewport.Height,
1,
SurfaceFormat.Color);
shadowMapTarget2 = new RenderTarget2D(graphicsDevice,
Statics.SystemSettings.graphics.GraphicsDevice.Viewport.Width,
Statics.SystemSettings.graphics.GraphicsDevice.Viewport.Height,
1,
SurfaceFormat.Color);
renderTarget = new RenderTarget2D(graphicsDevice,
Statics.SystemSettings.graphics.GraphicsDevice.Viewport.Width,//Statics.caps.MaxTextureWidth,
Statics.SystemSettings.graphics.GraphicsDevice.Viewport.Height,//Statics.caps.MaxTextureHeight,
1,
SurfaceFormat.Color);
// Secondary render target. This is being used to access the depth buffer from the graphics device
//depthBuffer = new RenderTarget2D(graphicsDevice,
// Statics.caps.MaxTextureWidth,
// Statics.caps.MaxTextureHeight,
// 1,
// SurfaceFormat.Color);
// Set up the menu system components
spriteBatch = new SpriteBatch(Statics.SystemSettings.graphics.GraphicsDevice);
// Create Vertex Declaration, Buffer, and Array
vertexDeclaration = new VertexDeclaration(graphicsDevice, VertexPositionNormalTexture.VertexElements);
vertexBuffer = new VertexBuffer(graphicsDevice,
VertexPositionNormalTexture.SizeInBytes * 4,
BufferUsage.WriteOnly);
vertices = new VertexPositionNormalTexture[4];
// Create quad with width and height = 1
vertices[0] = new VertexPositionNormalTexture(new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, 0.0f, 1.0f), new Vector2(0.0f, 1.0f));
vertices[1] = new VertexPositionNormalTexture(new Vector3(1.0f, 0.0f, 0.0f), new Vector3(1.0f, 0.0f, 1.0f), new Vector2(1.0f, 1.0f));
vertices[2] = new VertexPositionNormalTexture(new Vector3(1.0f, 1.0f, 0.0f), new Vector3(1.0f, 1.0f, 1.0f), new Vector2(1.0f, 0.0f));
vertices[3] = new VertexPositionNormalTexture(new Vector3(0.0f, 1.0f, 0.0f), new Vector3(0.0f, 1.0f, 1.0f), new Vector2(0.0f, 0.0f));
// Set the data
vertexBuffer.SetData(vertices);
// Setup HUD for borders
viewPortBordersHUD.AddImageDisplay(Statics.SystemSettings.content.Load("Content/_textures/black"),
new Vector2(0, Statics.RenderSettings.GAME_WINDOW_HEIGHT / 2.0f - 10),
Statics.RenderSettings.GAME_WINDOW_WIDTH,
20,
new Color(255, 255, 255, 150),
true);
viewPortBordersHUD.AddImageDisplay(Statics.SystemSettings.content.Load("Content/_textures/black"),
new Vector2(Statics.RenderSettings.GAME_WINDOW_WIDTH / 2.0f - 10, 0),
20,
Statics.RenderSettings.GAME_WINDOW_HEIGHT,
new Color(255, 255, 255, 150),
true);
}
#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
///
/// ObjectLibrary
public void Draw(ObjectLibrary objectLibrary)
{
// Set up state
GraphicsDevice graphicsDevice = Statics.SystemSettings.graphics.GraphicsDevice;
graphicsDevice.Clear(Color.Black);
graphicsDevice.RenderState.DepthBufferEnable = true;
// Enable Render To Texture
graphicsDevice.SetRenderTarget(0, renderTarget);
// Draw GameObjects to the framebuffer
Draw_ObjectLibrary(graphicsDevice, objectLibrary);
// Draw Post Process Sprites and HUD
Draw_Sprites(graphicsDevice, objectLibrary);
// Disable Render To Texture
graphicsDevice.SetRenderTarget(0, null);
// Store rendered image in modelTexture1
ShaderParameters.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, objectLibrary);
// Draw Boarders around the screen
Draw_Borders(graphicsDevice, spriteBatch);
}
private void Draw_ObjectLibrary(GraphicsDevice graphicsDevice, ObjectLibrary objectLibrary)
{
// Draw all objects for each player's viewport
for (int cameraNumber = 0; cameraNumber < Statics.RenderSettings.cameraList.Count; cameraNumber++)
{
graphicsDevice.Viewport = Statics.RenderSettings.cameraList[cameraNumber].viewport;
graphicsDevice.Clear(new Color(15, 25, 20));
// Calculate the player's ModelView Matrix
Statics.RenderSettings.matrixView =
Statics.RenderSettings.cameraList[cameraNumber].GetViewMatrix(objectLibrary.humans[cameraNumber].mass);
// Calculate the player's Projection Matrix
Statics.RenderSettings.matrixProjection = Statics.RenderSettings.cameraList[cameraNumber].GetProjectionMatrix();
// Pass Matricies to Shader
ShaderParameters.ViewProj.SetValue(Statics.RenderSettings.matrixView * Statics.RenderSettings.matrixProjection);
ShaderParameters.EyePostion.SetValue(Matrix.Invert(Statics.RenderSettings.matrixView));
//===\ Game Object Draw / ===
objectLibrary.Draw(cameraNumber);
}
}
private void Draw_Sprites(GraphicsDevice graphicsDevice, ObjectLibrary objectLibrary)
{
// Draw all objects for each player's viewport
for (int playerIndex = 0; playerIndex < Statics.RenderSettings.cameraList.Count; playerIndex++)
{
Statics.SystemSettings.graphics.GraphicsDevice.Viewport = Statics.RenderSettings.cameraList[playerIndex].viewport;
// Calculate the player's ModelView Matrix
Statics.RenderSettings.matrixView =
Matrix.CreateLookAt(objectLibrary.humans[playerIndex].mass.currentPosition,
objectLibrary.humans[playerIndex].mass.currentPosition + objectLibrary.humans[playerIndex].mass.normalVector,
objectLibrary.humans[playerIndex].mass.upVector);
// Calculate the player's Projection Matrix
Statics.RenderSettings.matrixProjection =
Matrix.CreatePerspectiveFieldOfView((float)Math.PI / 4,
Statics.RenderSettings.cameraList[playerIndex].viewport.Width / Statics.RenderSettings.cameraList[playerIndex].viewport.Height,
0.3f, 100000f);
// ObjectLibrary PostDraw_Sprites
objectLibrary.Draw_Billboards(playerIndex);
}
}
private void SetZoomLevel(GraphicsDevice graphicsDevice)
{
// If Zoom enables - HACKED !
if (Statics.RenderSettings.zoomEnabled)
{
Statics.RenderSettings.matrixProjection = Matrix.CreateOrthographic(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height, 1, 10000);
Statics.RenderSettings.matrixPosition = Matrix.CreateScale(graphicsDevice.Viewport.Width * Statics.RenderSettings.zoomFactor,
graphicsDevice.Viewport.Height * Statics.RenderSettings.zoomFactor,
1) *
Matrix.CreateTranslation(-graphicsDevice.Viewport.Width, -graphicsDevice.Viewport.Height, 0.0f);
}
else
{
Statics.RenderSettings.matrixProjection = Matrix.CreateOrthographic(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height, 1, 10000);
Statics.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);
}
}
private void Draw_HUD(GraphicsDevice graphicsDevice, SpriteBatch spriteBatch, ObjectLibrary objectLibrary)
{
// Draw each player's HUD on top of everything
for (int i = 0; i < Statics.SystemSettings.TOTAL_PLAYERS; i++)
{
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
graphicsDevice.Viewport = Statics.RenderSettings.cameraList[i].viewport;
// Post Draw for Humans
objectLibrary.PostDraw_HUD(i, spriteBatch);
spriteBatch.End();
}
}
private void Draw_PostProcessEffects(GraphicsDevice graphicsDevice)
{
graphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionNormalTexture.SizeInBytes);
graphicsDevice.Clear(ClearOptions.Target, Color.Black, 1.0f, 0);
// Setup view and projection matrixes
Statics.RenderSettings.matrixView = Matrix.CreateLookAt(Vector3.Backward, Vector3.Zero, Vector3.Up);
// Set all the different shader parameter for Anti-Aliasing
ShaderParameters.ViewProj.SetValue(Statics.RenderSettings.matrixView * Statics.RenderSettings.matrixProjection);
ShaderParameters.World.SetValue(Statics.RenderSettings.matrixPosition);
ShaderParameters.effect_draw.CurrentTechnique = ShaderParameters.effect_draw.Techniques["DrawQuad"];
// Render our quad
ShaderParameters.effect_draw.Begin();
foreach (EffectPass pass in ShaderParameters.effect_draw.CurrentTechnique.Passes)
{
pass.Begin();
graphicsDevice.VertexDeclaration = vertexDeclaration;
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2);
pass.End();
}
ShaderParameters.effect_draw.End();
}
private void Draw_Borders(GraphicsDevice graphicsDevice, SpriteBatch spriteBatch)
{
// Draw the borders on the screen
graphicsDevice.Viewport = Statics.RenderSettings.defaultViewport;
spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
if (Statics.SystemSettings.TOTAL_PLAYERS < 3)
{ viewPortBordersHUD.UpdateImageDraw(1, false); }
else { viewPortBordersHUD.UpdateImageDraw(1, true); }
if (Statics.SystemSettings.TOTAL_PLAYERS > 1)
{ viewPortBordersHUD.Draw(spriteBatch); }
spriteBatch.End();
}
#endregion
#region Utilities
///
/// Set up for 1280 or 1024 Resolution.
/// Supports both 4:3 and Widescreen format
///
public void AutoDetectResolution()
{
// Check the display mode to see how big the resolution
int displayWidth = Statics.SystemSettings.graphics.GraphicsDevice.DisplayMode.Width;
int displayHeight = Statics.SystemSettings.graphics.GraphicsDevice.DisplayMode.Height;
#if XBOX360
Statics.RenderSettings.GAME_WINDOW_WIDTH = displayWidth;
Statics.RenderSettings.GAME_WINDOW_HEIGHT = displayHeight;
#else
//Auto detect best resolution
if (displayWidth >= 1280)
{
// 720p
Statics.RenderSettings.GAME_WINDOW_WIDTH = 1280;
if (displayHeight >= 1024)
{
// 4:3 resolution
Statics.RenderSettings.GAME_WINDOW_HEIGHT = 1024;
}
else
{
// Widescreen
Statics.RenderSettings.GAME_WINDOW_HEIGHT = 720;
}
}
else if (displayWidth >= 1024)
{
// something in between
Statics.RenderSettings.GAME_WINDOW_WIDTH = 1024;
Statics.RenderSettings.GAME_WINDOW_HEIGHT = 768;
}
else
{
// Default to 480p
if (displayWidth > 700)
{
Statics.RenderSettings.GAME_WINDOW_WIDTH = 800;
}
else
{
Statics.RenderSettings.GAME_WINDOW_WIDTH = 640;
}
if (displayHeight >= 600)
{
Statics.RenderSettings.GAME_WINDOW_HEIGHT = 600;
}
else
{
Statics.RenderSettings.GAME_WINDOW_HEIGHT = 480;
}
}
#endif
Statics.SystemSettings.graphics.PreferredBackBufferWidth = Statics.RenderSettings.GAME_WINDOW_WIDTH;
Statics.SystemSettings.graphics.PreferredBackBufferHeight = Statics.RenderSettings.GAME_WINDOW_HEIGHT;
Statics.SystemSettings.graphics.ApplyChanges();
}
///
/// Set up the best settings for Window and ViewPort
///
public void AutoDetectWindowAndDefaultViewport(GameWindow Window)
{
// Set up window
Statics.RenderSettings.clientWidth = Window.ClientBounds.Width;
Statics.RenderSettings.clientHeight = Window.ClientBounds.Height;
Statics.RenderSettings.clientMinDepth = Statics.SystemSettings.graphics.GraphicsDevice.Viewport.MinDepth;
Statics.RenderSettings.clientMaxDepth = Statics.SystemSettings.graphics.GraphicsDevice.Viewport.MaxDepth;
// Set the default viewport
Statics.RenderSettings.defaultViewport.X = 0;
Statics.RenderSettings.defaultViewport.Y = 0;
Statics.RenderSettings.defaultViewport.Width = Statics.RenderSettings.clientWidth;
Statics.RenderSettings.defaultViewport.Height = Statics.RenderSettings.clientHeight;
Statics.RenderSettings.defaultViewport.MinDepth = Statics.RenderSettings.clientMinDepth;
Statics.RenderSettings.defaultViewport.MaxDepth = Statics.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)
{
Statics.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.RenderSettings.clientWidth / 2;
}
else
{
viewportWidth = Statics.RenderSettings.clientWidth;
}
if (numPlayers > 1)
{
// Divide height
viewportHeight = Statics.RenderSettings.clientHeight / 2;
}
else
{
viewportHeight = Statics.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.RenderSettings.clientMinDepth;
blankCamera.viewport.MaxDepth = Statics.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.RenderSettings.cameraList.Add(blankCamera);
}
}
///
/// Reset rendering options to support 3D drawing.
///
public void DisableSpriteBatches()
{
// Make sure culling is off
Statics.SystemSettings.graphics.GraphicsDevice.RenderState.CullMode = CullMode.None;
// Fix the render state post drawing sprite batch
Statics.SystemSettings.graphics.GraphicsDevice.RenderState.DepthBufferEnable = true;
Statics.SystemSettings.graphics.GraphicsDevice.RenderState.AlphaBlendEnable = false;
Statics.SystemSettings.graphics.GraphicsDevice.RenderState.AlphaTestEnable = false;
// Set the Texture addressing mode
Statics.SystemSettings.graphics.GraphicsDevice.SamplerStates[0].AddressU =
Statics.SystemSettings.graphics.GraphicsDevice.SamplerStates[0].AddressV =
Statics.SystemSettings.graphics.GraphicsDevice.SamplerStates[0].AddressW =
TextureAddressMode.Wrap;
Statics.SystemSettings.graphics.GraphicsDevice.SamplerStates[0].MagFilter = TextureFilter.Anisotropic;
Statics.SystemSettings.graphics.GraphicsDevice.SamplerStates[0].MinFilter = TextureFilter.Anisotropic;
Statics.SystemSettings.graphics.GraphicsDevice.SamplerStates[0].MipFilter = TextureFilter.Anisotropic;
Statics.SystemSettings.graphics.GraphicsDevice.Textures[0] = null;
}
#endregion
}
}