//---------------------------------------------------------------------------------------------------------------------------------------------------
//
// 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;
using System.ComponentModel;
using DarkWynter.Stream.UIInterfacing;
#endregion
///
/// Handles all render operations
///
public class Renderer
{
[EditorAttribute(typeof(ObjectPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))]
public Statics_Stream _statics_Stream { get { return statics_Stream; } set { statics_Stream = value; } }
public Statics_Stream statics_Stream;
[EditorAttribute(typeof(ObjectPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))]
public SpriteBatch spriteBatch { get { return _spriteBatch; } set { _spriteBatch = value; } }
public SpriteBatch _spriteBatch;
[EditorAttribute(typeof(ObjectPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))]
public RenderTarget2D renderTarget { get { return _renderTarget; } set { _renderTarget = value; } }
private RenderTarget2D _renderTarget; // Primary Render target
[EditorAttribute(typeof(ObjectPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))]
public GraphicsDevice graphicsDevice { get { return _graphicsDevice; } set { _graphicsDevice = value; } }
private GraphicsDevice _graphicsDevice;
public Color backColor { get { return _backColor; } set { _backColor = value; } }
private Color _backColor = Color.Black;
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;
///
/// Draw Object Library delegate type
///
/// Camera number
public delegate List DrawObjectLibrary(int cameraNumber);
///
/// Draw Sprites delegate type
///
/// 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)
{
// For debugging access; all properties are static accessible
statics_Stream = new Statics_Stream();
// Get the graphics device
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);
this.AutoDetectResolution();
this.AutoDetectWindowAndDefaultViewport(/*Window*/);
// Setup HUD for borders
//viewPortBordersHUD.AddImageDisplay(content.Load("Content/_textures/black"),
// new Vector2(0, Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT / 2.0f - 10),
// Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH,
// 20,
// new Color(255, 255, 255, 150),
// true);
//viewPortBordersHUD.AddImageDisplay(content.Load("Content/_textures/black"),
// new Vector2(Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH / 2.0f - 10, 0),
// 20,
// Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT,
// new Color(255, 255, 255, 150),
// true);
}
public void Update(int totalPlayers)
{
// Update renderer settings if changed
if (Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.Height != Statics_Stream.RenderSettings.GAME_WINDOW_HEIGHT ||
Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.Width != Statics_Stream.RenderSettings.GAME_WINDOW_WIDTH)
{
this.AutoDetectResolution();
this.AutoDetectWindowAndDefaultViewport(/*Window*/);
Renderer.ResetViewports(totalPlayers);
}
}
#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 = Statics_Stream.RenderSettings.graphics.GraphicsDevice;
graphicsDevice.Clear(backColor);
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 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);
}
}
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);
//if (totalPlayers < 3)
//{ viewPortBordersHUD.UpdateImageDraw(1, false); }
//else { viewPortBordersHUD.UpdateImageDraw(1, true); }
//if (totalPlayers > 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_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 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)
{
// Create Initial List
if (Statics_Stream.RenderSettings.cameraList == null)
Statics_Stream.RenderSettings.cameraList = new List();
// Create Initial Camera
if (Statics_Stream.RenderSettings.cameraList.Count == 0)
Statics_Stream.RenderSettings.cameraList.Add(new Camera());
// All viewports needed for the players
Camera blankCamera = Statics_Stream.RenderSettings.cameraList[0];
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[0] = 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
}
}