//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- namespace ElementalGame { #region Using Statements using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; #endregion public class GpuProcessor { // Spacial Data Structure Vec4 locationMap; // Spatial and Indexed Viewports Viewport IndexedViewport; Viewport SpatialViewport; // Quad Vertex Buffer ============================================================================= private VertexBuffer quad_vertexBuffer; // Buffer to store vertices private VertexPositionNormalTexture[] quad_vertices; // Array to store vertex Position, Normal and Texture information private VertexDeclaration quad_vertexDeclaration; // Vertex Declaration public static int INDEXED_TARGET_SIZE = 256; // Point Vertex Buffer ============================================================================ private VertexBuffer point_vertexBuffer; // Buffer to store vertices private VertexPositionNormalTexture[] point_vertices; // Array to store vertex Position, Normal and Texture information private VertexDeclaration point_vertexDeclaration; // Vertex Declaration public static int SPATIAL_TARGET_SIZE = 512; // Update Shader ================================================================================== Effect effect_update; // The program handle EffectParameter gpu_dt; // Time difference between frames EffectParameter gpu_Pass; // Keeps track of which physics-instruction pass we are on EffectParameter gpu_Gravity; // Manipulate gpu gravity remotely float gravity = 0.0f; // Stores value modifiable through controller EffectParameter gpu_HeightMap; // GPU version of terrain heightmap; shared with draw shader EffectParameter gpu_NormalMap; // GPU version of terrain normalmap; shared with draw shader Texture2D ForceMap; // Texture holding "wind" currents EffectParameter ForceMapPointer; // Pointer for gpu // Draw Shader ==================================================================================== Effect effect_draw; // The handle to ElementalGPU.fx EffectParameter currentPositionParam; // To save the CurrentPosition texture to ElementalGPU EffectParameter scaleRange; // To save the Scale Range to ElementalGPU EffectParameter minimumValue; // To save the Minimum Value to ElementalGPU bool initializeConstants = true; // ================================\ Methods /===================================================== // ================================================================================================ public GpuProcessor() { // Set up Uniform shader connections effect_update = ElementalGame.content.Load("PhysicsGPU/GpuCollisionPhysics"); effect_draw = ElementalGame.content.Load("Shaders/ElementalGPU"); // Get Update Handles gpu_Pass = effect_update.Parameters["IndexedPass"]; gpu_dt = effect_update.Parameters["dt"]; gpu_Gravity = effect_update.Parameters["gravity"]; // Get Draw Handles currentPositionParam = effect_draw.Parameters["CurrentPosition"]; scaleRange = effect_draw.Parameters["scaleRange"]; minimumValue = effect_draw.Parameters["minimumValue"]; // Set up Terrain Maps gpu_HeightMap = effect_update.Parameters["TerrainHeightMap"]; gpu_NormalMap = effect_update.Parameters["TerrainNormalMap"]; // Create Location Map locationMap = new Vec4(effect_update, "LocationMap", "locationMap"); // Load the ForceMap ForceMap = ElementalGame.content.Load("_textures/ForceMap"); ForceMapPointer = effect_update.Parameters["ForceMap"]; // Create geometry used in render passes CreateQuad(); CreatePoints(); } private void CreateQuad() { // Set up the Indexed viewport IndexedViewport.X = 0; IndexedViewport.Y = 0; IndexedViewport.Width = INDEXED_TARGET_SIZE; IndexedViewport.Height = INDEXED_TARGET_SIZE; IndexedViewport.MinDepth = ElementalGame.graphics.GraphicsDevice.Viewport.MinDepth; IndexedViewport.MaxDepth = ElementalGame.graphics.GraphicsDevice.Viewport.MaxDepth; GraphicsDevice gd = ElementalGame.graphics.GraphicsDevice; // Create a 4 point vertex buffer quad_vertices = new VertexPositionNormalTexture[4]; quad_vertexDeclaration = new VertexDeclaration(gd, VertexPositionNormalTexture.VertexElements); quad_vertexBuffer = new VertexBuffer(gd, VertexPositionNormalTexture.SizeInBytes * 4, ResourceUsage.None, ResourceManagementMode.Automatic); // Create quad with width and height = 1 quad_vertices[0] = new VertexPositionNormalTexture(new Vector3(-0.5f, -0.5f, 0), new Vector3(-0.5f, -0.5f, 1), new Vector2(0, 1.0f)); // 3rd quadrent quad_vertices[1] = new VertexPositionNormalTexture(new Vector3(0.5f, -0.5f, 0), new Vector3(0.5f, -0.5f, 1), new Vector2(1.0f, 1.0f)); // 4th quadrent quad_vertices[2] = new VertexPositionNormalTexture(new Vector3(0.5f, 0.5f, 0), new Vector3(0.5f, 0.5f, 1), new Vector2(1.0f, 0)); // 1st quadrent quad_vertices[3] = new VertexPositionNormalTexture(new Vector3(-0.5f, 0.5f, 0), new Vector3(-0.0f, 1.0f, 1), new Vector2(0, 0)); // 2nd quadrent // Set the data quad_vertexBuffer.SetData(quad_vertices); } private void CreatePoints() { // Set up the Spatial viewport SpatialViewport.X = 0; SpatialViewport.Y = 0; SpatialViewport.Width = SPATIAL_TARGET_SIZE; SpatialViewport.Height = SPATIAL_TARGET_SIZE; SpatialViewport.MinDepth = ElementalGame.graphics.GraphicsDevice.Viewport.MinDepth; SpatialViewport.MaxDepth = ElementalGame.graphics.GraphicsDevice.Viewport.MaxDepth; GraphicsDevice gd = ElementalGame.graphics.GraphicsDevice; point_vertices = new VertexPositionNormalTexture[SPATIAL_TARGET_SIZE * SPATIAL_TARGET_SIZE]; point_vertexDeclaration = new VertexDeclaration(gd, VertexPositionNormalTexture.VertexElements); point_vertexBuffer = new VertexBuffer(gd, VertexPositionNormalTexture.SizeInBytes * SPATIAL_TARGET_SIZE * SPATIAL_TARGET_SIZE, ResourceUsage.None, ResourceManagementMode.Automatic); // Row by row, create a point for each pixel between 0-1 int index = 0; float pixelLength = SPATIAL_TARGET_SIZE - 1.0f; for (int j = 0; j <= pixelLength; j++) { for (int i = 0; i <= pixelLength; i++) { Vector3 pPos = new Vector3(((float)i / pixelLength), ((float)j / pixelLength), 0.0f); Vector3 nPos = new Vector3(((float)i / pixelLength), ((float)j / pixelLength), 1.0f); Vector2 tPos = new Vector2(((float)i / pixelLength), ((float)j / pixelLength)); point_vertices[index] = new VertexPositionNormalTexture(pPos, nPos, tPos); index++; } } // Set the data point_vertexBuffer.SetData(point_vertices); } // Main public void ExecuteRTT(float dt, GpuObject gpuObject, ObjectLibrary objectLibrary) { // Spatial Updates effect_update.CurrentTechnique = effect_update.Techniques["SpatialMain"]; ExecuteSpatialRTT(ref locationMap.writeRenderTarget, ref locationMap.write); locationMap.SwapBuffers(); //gpuObject.WriteToFile(); // Set Gravity gravity += objectLibrary.humans[0].playerController.GetGPUGravityButton(); gpu_Gravity.SetValue(gravity); // Set shader dt gpu_dt.SetValue(dt); // Set HeightMap and NormalMap gpu_HeightMap.SetValue(objectLibrary.terrain.heightMapTexture); gpu_NormalMap.SetValue(objectLibrary.terrain.normalMapTexture); // Set ForceMap ForceMapPointer.SetValue(ForceMap); // Indexed Updates effect_update.CurrentTechnique = effect_update.Techniques["IndexedMain"]; for (int i = 0; i <= 6; i++) { gpu_Pass.SetValue(i); ExecuteIndexedRTT(ref gpuObject.variables[i].writeRenderTarget, ref gpuObject.variables[i].write); gpuObject.variables[i].SwapBuffers(); //gpuObject.variables[i].WriteToFile(); } // ================== MOVE OR REMOVE ======================== // Save texture to other fx file // variables[5] = current position currentPositionParam.SetValue(gpuObject.variables[5].write); if (initializeConstants) { initializeConstants = false; // Store the constants scaleRange.SetValue(gpuObject.variables[5].scaleRange); minimumValue.SetValue(gpuObject.variables[5].minimumValue); } ElementalGame.graphics.GraphicsDevice.SetRenderTarget(0, null); } private void ExecuteIndexedRTT(ref RenderTarget2D renderTarget, ref Texture2D renderTargetTexture) { // Set up Graphics Device GraphicsDevice g = ElementalGame.graphics.GraphicsDevice; g.Viewport = IndexedViewport; g.RenderState.DepthBufferEnable = false; // Setup view and projection matrixes Matrix proj = Matrix.CreateOrthographic(1.0f, 1.0f, 1, 5); Matrix view = Matrix.CreateLookAt(Vector3.Backward, Vector3.Zero, new Vector3(0, 1, 1)); effect_update.Parameters["ViewProj"].SetValue(view * proj); // Set Quad Vertex Buffer g.Vertices[0].SetSource(quad_vertexBuffer, 0, VertexPositionNormalTexture.SizeInBytes); // Set and clear RTT texture g.SetRenderTarget(0, renderTarget); g.Clear(ClearOptions.Target, Color.TransparentWhite, 1.0f, 0); // Draw Quad effect_update.Begin(); foreach (EffectPass pass in effect_update.CurrentTechnique.Passes) { pass.Begin(); g.VertexDeclaration = quad_vertexDeclaration; g.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2); pass.End(); } effect_update.End(); // Gets the Rendered Texture and store it in the RenderTarget variable g.ResolveRenderTarget(0); //renderTarget.GetTexture().Save("indexedTexture.png", ImageFileFormat.Png); // Retrieve the Shadow map from our Render Target //renderTargetTexture = renderTarget.GetTexture(); //renderTargetTexture.Save("indexedTexture.png", ImageFileFormat.Png); } private void ExecuteSpatialRTT(ref RenderTarget2D renderTarget, ref Texture2D renderTargetTexture) { // Set up Graphics Device GraphicsDevice g = ElementalGame.graphics.GraphicsDevice; g.Viewport = SpatialViewport; g.RenderState.DepthBufferEnable = false; // Setup view and projection matrixes Matrix proj = Matrix.CreateOrthographic(0.5f, 0.5f, 0, 5); //Matrix view = Matrix.CreateLookAt(Vector3.Backward, Vector3.Zero, new Vector3(0, 1, 1)); Matrix view = Matrix.CreateLookAt(new Vector3(0.75f, 0.75f, 1.0f), new Vector3(0.75f, 0.75f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); effect_update.Parameters["ViewProj"].SetValue(view * proj); effect_update.Parameters["gpuObjectScale"].SetValue(Terrain.collisionMapSize); // Set Points Vertex Buffer g.Vertices[0].SetSource(point_vertexBuffer, 0, VertexPositionNormalTexture.SizeInBytes); // Set and clear RTT texture g.SetRenderTarget(0, renderTarget); g.Clear(ClearOptions.Target, Color.TransparentWhite, 1.0f, 0); // Draw Quad effect_update.Begin(); foreach (EffectPass pass in effect_update.CurrentTechnique.Passes) { pass.Begin(); g.VertexDeclaration = point_vertexDeclaration; g.DrawPrimitives(PrimitiveType.PointList, 0, SPATIAL_TARGET_SIZE * SPATIAL_TARGET_SIZE); pass.End(); } effect_update.End(); // Gets the Rendered Texture and store it in the RenderTarget variable g.ResolveRenderTarget(0); //renderTarget.GetTexture().Save("gpuPhysicsTex.png", ImageFileFormat.Png); } } }