//---------------------------------------------------------------------------------------------------------------------------------------------------
//
// Copyright (C)2007 DarkWynter Studios. All rights reserved.
//
//---------------------------------------------------------------------------------------------------------------------------------------------------
// {License Information: Creative Commons}
//---------------------------------------------------------------------------------------------------------------------------------------------------
namespace ElementalGame
{
#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
public class Renderer
{
public static Matrix matrixModelView; // View Matrix
public static Matrix matrixProjection; // Projection Matrix
RenderTarget2D renderTarget; // Primary Render target
RenderTarget2D shadowMapTarget; // Primary Render target
Effect AAEffect; // Effect to render the Render Target to a quad on-screen
HeadsUpDisplay viewPortBorders = new HeadsUpDisplay();
//Texture2D shadowMap;
private VertexBuffer vertexBuffer; // Buffer to store vertices
public VertexPositionNormalTexture[] vertices; // Array to store vertex Position, Normal and Texture information
private VertexDeclaration vertexDeclaration; // Vertex Declaration
public static Matrix lightView1;
public static Matrix lightView2;
public static Matrix lightProj;
public static bool zoomEnabled = false;
public static bool HIJACK_VIEWPORT = false;
public static bool currentPlayerDead = false;
public Renderer()
{
GraphicsDevice graphicsDevice = ElementalGame.graphics.GraphicsDevice;
// Primary render targets. Everything drawn in the player viewport's will be rendered to these targets
shadowMapTarget = new RenderTarget2D(graphicsDevice,
graphicsDevice.Viewport.Width,
graphicsDevice.Viewport.Height,
1,
SurfaceFormat.Color);
renderTarget = new RenderTarget2D(graphicsDevice,
ElementalGame.graphics.GraphicsDevice.Viewport.Width,//ElementalGame.caps.MaxTextureWidth,
ElementalGame.graphics.GraphicsDevice.Viewport.Height,//ElementalGame.caps.MaxTextureHeight,
1,
SurfaceFormat.Color);
// Anti-Aliasing shader effect for rendering the quad to the screen
AAEffect = ElementalGame.content.Load("Shaders/ElementalGPU");
// Create Vertex Declaration, Buffer, and Array
vertexDeclaration = new VertexDeclaration(graphicsDevice, VertexPositionNormalTexture.VertexElements);
vertexBuffer = new VertexBuffer(graphicsDevice,
VertexPositionNormalTexture.SizeInBytes * 4,
ResourceUsage.Dynamic,
ResourceManagementMode.Manual);
vertices = new VertexPositionNormalTexture[4];
// Create quad with width and height = 1
vertices[0] = new VertexPositionNormalTexture(new Vector3(0.0f, 0.0f, 0),
new Vector3(0.0f, 0.0f, 1),
new Vector2(0, 1.0f));
vertices[1] = new VertexPositionNormalTexture(new Vector3(1.0f, 0.0f, 0),
new Vector3(1.0f, 0.0f, 1),
new Vector2(1.0f, 1.0f));
vertices[2] = new VertexPositionNormalTexture(new Vector3(1.0f, 1.0f, 0),
new Vector3(1.0f, 1.0f, 1),
new Vector2(1.0f, 0));
vertices[3] = new VertexPositionNormalTexture(new Vector3(0.0f, 1.0f, 0),
new Vector3(0.0f, 1.0f, 1),
new Vector2(0, 0));
// Set the data
vertexBuffer.SetData(vertices);
// Setup HUD for borders
viewPortBorders.AddImageDisplay(ElementalGame.content.Load("_textures/black"),
new Vector2(0, XML.SystemSettings.GAME_WINDOW_HEIGHT / 2.0f - 10),
XML.SystemSettings.GAME_WINDOW_WIDTH,
20,
new Color(255, 255, 255, 150),
true);
viewPortBorders.AddImageDisplay(ElementalGame.content.Load("_textures/black"),
new Vector2(XML.SystemSettings.GAME_WINDOW_WIDTH / 2.0f - 10, 0),
20,
XML.SystemSettings.GAME_WINDOW_HEIGHT,
new Color(255, 255, 255, 150),
true);
}
// 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
public void Draw(ObjectLibrary objectLibrary, List viewportList)
{
GraphicsDevice graphicsDevice = ElementalGame.graphics.GraphicsDevice;
objectLibrary.GetDrawObjects();
if (XML.SystemSettings.enableShadowMap1)
{
graphicsDevice.SetRenderTarget(0, shadowMapTarget); // Turn on Render To Texture
graphicsDevice.RenderState.DepthBufferEnable = true; // Enable depth buffering
// Clear both the render target and the depth buffer
graphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);
// Do shadow mapping only if the graphics card can handle it
graphicsDevice.Viewport = ElementalGame.defaultViewport; // Set the View port
Vector3 lightPosition1 = new Vector3(XML.LevelSettings.lightInfo1.M11,
XML.LevelSettings.lightInfo1.M12,
XML.LevelSettings.lightInfo1.M13);
Vector3 targetLocation1 = new Vector3(Terrain.collisionMapSize / 4.0f,
0.0f,
Terrain.collisionMapSize / 4.0f);
Vector3 lightPosition2 = new Vector3(XML.LevelSettings.lightInfo2.M11,
XML.LevelSettings.lightInfo2.M12,
XML.LevelSettings.lightInfo2.M13);
Vector3 targetLocation2 = new Vector3(Terrain.collisionMapSize * 3.0f / 4.0f,
0.0f,
Terrain.collisionMapSize * 3.0f / 4.0f);
// Calculate the player's ModelView Matrix
lightView1 = Matrix.CreateLookAt(lightPosition1,
targetLocation1,
objectLibrary.humans[0].mass.upVector);
lightView2 = Matrix.CreateLookAt(lightPosition2,
targetLocation2,
objectLibrary.humans[0].mass.upVector);
// Calculate the player's Projection Matrix
lightProj = Matrix.CreatePerspectiveFieldOfView((float)Math.PI / 2.0f,
graphicsDevice.Viewport.Width / graphicsDevice.Viewport.Height,
0.3f,
100000f);
ShaderParameters.LightViewProj1.SetValue(lightView1 * lightProj);
ShaderParameters.LightViewProj2.SetValue(lightView2 * lightProj);
ShaderParameters.zMaxDepth.SetValue(XML.LevelSettings.zMaxDepth);
// Switch to each player's viewport and draw the scene from their perspective
objectLibrary.DrawShadow();
graphicsDevice.ResolveRenderTarget(0); // Gets the Rendered Texture and store it in the RenderTarget variable
//shadowMap = shadowMapTarget.GetTexture(); // Retrieve the Shadow map from our Render Target
ShaderParameters.shadowTexture1.SetValue(shadowMapTarget.GetTexture());
}
if (XML.SystemSettings.enableShadowMap2)
{
graphicsDevice.SetRenderTarget(0, shadowMapTarget); // Turn on Render To Texture
graphicsDevice.Clear(ClearOptions.Target | ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);
ShaderParameters.LightViewProj1.SetValue(lightView2 * lightProj);
// Switch to each players viewport and draw the scene from their perspective
objectLibrary.DrawShadow();
graphicsDevice.ResolveRenderTarget(0);
//shadowMap2 = shadowMapTarget2.GetTexture();
//shadowMap1.Save("shadow1.png", ImageFileFormat.Png);
//shadowMap2.Save("shadow2.png", ImageFileFormat.Png);
ShaderParameters.shadowTexture2.SetValue(shadowMapTarget.GetTexture());
ShaderParameters.LightViewProj1.SetValue(lightView1 * lightProj);
}
graphicsDevice.SetRenderTarget(0, renderTarget); // Turn on Render To Texture
graphicsDevice.Clear(Color.TransparentBlack);
// Draw all objects for each player's viewport
for (int i = 0; i < viewportList.Count; i++)
{
graphicsDevice.Viewport = viewportList[i]; // Set the View port
graphicsDevice.Clear(Color.TransparentBlack); // Clear it
//hijack code.. just take it out
#region NOT_IN_USE
//if (HIJACK_VIEWPORT && i == 0 && objectLibrary.bots.Count > 0 && objectLibrary.bots[0].IsAlive())
//{
// // Calculate the Light's ModelView Matrix
// matrixModelView = Matrix.CreateLookAt(objectLibrary.bots[0].mass.currentPosition + objectLibrary.bots[0].mass.normalVector * 2,
// objectLibrary.bots[0].mass.currentPosition + objectLibrary.bots[0].mass.normalVector * 3,
// objectLibrary.bots[0].mass.upVector);
//}
//else
#endregion
{
// Calculate the player's ModelView Matrix
matrixModelView = Matrix.CreateLookAt(objectLibrary.humans[i].mass.currentPosition,
objectLibrary.humans[i].mass.currentPosition + objectLibrary.humans[i].mass.normalVector,
objectLibrary.humans[i].mass.upVector);
}
// Calculate the player's Projection Matrix
matrixProjection = Matrix.CreatePerspectiveFieldOfView((float)Math.PI / 4,
viewportList[i].Width / viewportList[i].Height,
0.3f,
100000f);
ShaderParameters.ViewProj.SetValue(matrixModelView * matrixProjection);
ShaderParameters.EyePostion.SetValue(Matrix.Invert(matrixModelView));
ShaderParameters.playerIsDead.SetValue(!objectLibrary.humans[i].IsAlive());
currentPlayerDead = !objectLibrary.humans[i].IsAlive();
// Switch to each players viewport and draw the scene from their perspective
objectLibrary.Draw(i);
}
graphicsDevice.ResolveRenderTarget(0); // Gets the Rendered Texture and store it in the RenderTarget variable
ShaderParameters.modelTexture1.SetValue(renderTarget.GetTexture()); // Set the primary render target to modelTexture1
graphicsDevice.SetRenderTarget(0, null); // Reset the Render Target
Matrix proj, pos;
if (zoomEnabled)
{
proj = Matrix.CreateOrthographic(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height, 1, 10000);
// Setup world matrix
pos = Matrix.CreateScale(graphicsDevice.Viewport.Width * 2, graphicsDevice.Viewport.Height * 2, 1)
*
Matrix.CreateTranslation(-graphicsDevice.Viewport.Width, -graphicsDevice.Viewport.Height, 0.0f);
}
else
{
proj = Matrix.CreateOrthographic(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height, 1, 10000);
// Setup world matrix
pos = Matrix.CreateScale(graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height, 1)
*
Matrix.CreateTranslation(-graphicsDevice.Viewport.Width / 2.0f, -graphicsDevice.Viewport.Height / 2.0f, 0.0f);
}
graphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionNormalTexture.SizeInBytes);
// Clear the screen
graphicsDevice.Clear(ClearOptions.Target, Color.Black, 1.0f, 0);
// Setup view and projection matrixes
Matrix view = Matrix.CreateLookAt(Vector3.Backward, Vector3.Zero, Vector3.Up);
// Set all the different shader parameter for Anti-Aliasing
ShaderParameters.ViewProj.SetValue(view * proj); // Pass the calculated world * view * proj matrix
ShaderParameters.World.SetValue(pos);
AAEffect.CurrentTechnique = AAEffect.Techniques["FullScreenAntiAliasing"]; // Set the technique to use in the shader to AA
// Render our quad
AAEffect.Begin();
foreach (EffectPass pass in AAEffect.CurrentTechnique.Passes)
{
pass.Begin();
graphicsDevice.VertexDeclaration = vertexDeclaration;
graphicsDevice.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2);
pass.End();
}
AAEffect.End();
//end the global sprite batch
ElementalGame.spriteBatch.End();
// Once this is done, draw each player's HUD on top of everything
for (int i = 0; i < XML.SystemSettings.TOTAL_PLAYERS; i++)
{
ElementalGame.spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
graphicsDevice.Viewport = viewportList[i]; // Set the View port
// Calculate the player's ModelView Matrix
matrixModelView = Matrix.CreateLookAt(objectLibrary.humans[i].mass.currentPosition,
objectLibrary.humans[i].mass.currentPosition + objectLibrary.humans[i].mass.normalVector,
objectLibrary.humans[i].mass.upVector);
// Calculate the player's Projection Matrix
matrixProjection = Matrix.CreatePerspectiveFieldOfView((float)Math.PI / 4,
viewportList[i].Width / viewportList[i].Height,
0.3f,
100000f);
if (objectLibrary.humans[i].IsAlive())
{
//Draw the HUD for this human player
objectLibrary.humans[i].HUD.Draw();
objectLibrary.DrawTargets(i);
}
else
{
//Draw the dead HUD for dead player
objectLibrary.humans[i].deadHUD.Draw();
}
ElementalGame.spriteBatch.End();
}
graphicsDevice.Viewport = ElementalGame.defaultViewport;
//start again
ElementalGame.spriteBatch.Begin(SpriteBlendMode.AlphaBlend);
//draw the borders
if (XML.SystemSettings.TOTAL_PLAYERS < 3)
{
viewPortBorders.UpdateImageDraw(1, false);
}
else
{
viewPortBorders.UpdateImageDraw(1, true);
}
if (XML.SystemSettings.TOTAL_PLAYERS > 1)
{
viewPortBorders.Draw();
}
}
}
}