//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- namespace DarkWynterEngine.PhysicsGpu { #region Using Statements using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; #endregion using Globals; using ObjectLib; /// /// GpuProcessor handles the rendering of GpuVariables. /// Supports standard gpgpu "quad" technique to handle gather algorithms. /// Also supports what we call a "quad of points" technique to handle scatter algorithms. /// public class GpuProcessor { // Spatial and Indexed Viewports private Viewport IndexedViewport; private 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 // 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 // Update Shader ================================================================================== private EffectParameter gpu_dt; // Time difference between frames private EffectParameter gpu_Pass; // Keeps track of which physics-instruction pass we are on private EffectParameter invSpatMapHeight; private EffectParameter invSpatMapWidth; private EffectParameter gpu_Gravity; // Manipulate gpu gravity remotely private float gravity = 0.0f; // Stores value modifiable through controller private EffectParameter gpu_HeightMap; // GPU version of terrain heightmap; shared with draw shader private EffectParameter gpu_NormalMap; // GPU version of terrain normalmap; shared with draw shader // ================================\ Methods /===================================================== // ================================================================================================ /// /// GpuProcessor constructor sets up Quad and Quad of Points mechanics. /// public GpuProcessor() { // Get Update Handles gpu_Pass = ShaderParameters.effect_update.Parameters["IndexedPass"]; gpu_dt = ShaderParameters.effect_update.Parameters["dt"]; gpu_Gravity = ShaderParameters.effect_update.Parameters["gravity"]; invSpatMapHeight = ShaderParameters.effect_update.Parameters["invSpatMapHeight"]; invSpatMapWidth = ShaderParameters.effect_update.Parameters["invSpatMapWidth"]; //// Get Draw Handles //currentPositionParam = effect_draw.Parameters["CurrentPosition"]; //scaleRange = effect_draw.Parameters["scaleRange"]; //minimumValue = effect_draw.Parameters["minimumValue"]; // Set up Terrain Maps gpu_HeightMap = ShaderParameters.effect_update.Parameters["TerrainHeightMap"]; gpu_NormalMap = ShaderParameters.effect_update.Parameters["TerrainNormalMap"]; // Create geometry used in render passes CreateQuad(); CreatePoints(); } private void CreateQuad() { // Set up the Indexed viewport IndexedViewport.X = 0; IndexedViewport.Y = 0; IndexedViewport.Width = Statics.GPU_ProcessorSettings.INDEXED_TARGET_SIZE; IndexedViewport.Height = Statics.GPU_ProcessorSettings.INDEXED_TARGET_SIZE; IndexedViewport.MinDepth = Statics.SystemSettings.graphics.GraphicsDevice.Viewport.MinDepth; IndexedViewport.MaxDepth = Statics.SystemSettings.graphics.GraphicsDevice.Viewport.MaxDepth; GraphicsDevice gd = Statics.SystemSettings.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, BufferUsage.WriteOnly); // 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 = Statics.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE; SpatialViewport.Height = Statics.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE; SpatialViewport.MinDepth = Statics.SystemSettings.graphics.GraphicsDevice.Viewport.MinDepth; SpatialViewport.MaxDepth = Statics.SystemSettings.graphics.GraphicsDevice.Viewport.MaxDepth; invSpatMapHeight.SetValue(1.0f / (float)Statics.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE); invSpatMapWidth.SetValue(1.0f / (float)Statics.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE); GraphicsDevice gd = Statics.SystemSettings.graphics.GraphicsDevice; point_vertices = new VertexPositionNormalTexture[Statics.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE * Statics.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE]; point_vertexDeclaration = new VertexDeclaration(gd, VertexPositionNormalTexture.VertexElements); point_vertexBuffer = new VertexBuffer(gd, VertexPositionNormalTexture.SizeInBytes * Statics.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE * Statics.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE, BufferUsage.WriteOnly); // Row by row, create a point for each pixel between 0-1 int index = 0; float pixelLength = Statics.GPU_ProcessorSettings.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); } /// /// Executes a shader pass on a List of GpuVariables. /// Each GpuVariable has enough information to tell the processor how to execute it. /// Variables are processed in the order in which they occur in the list. /// /// A list of variables to process. /// ObjectLibrary containing terrain used in collision. /// // CLEAN: REMOVE BOTH PARAMETERS, REPLACE WITH SINGLE GPU OBJECT public void ExecuteRTT(GpuObjectList gpuObjectList, ObjectLibrary objectLibrary) { // Set Gravity //gravity += objectLibrary.humans[0].playerController.gameInput.GetGPUGravityButton; gpu_Gravity.SetValue(gravity); // Set Change in Time gpu_dt.SetValue(Statics.SystemSettings.dt); // Set HeightMap, NormalMap, ForceMap, and Scale Values gpu_HeightMap.SetValue(objectLibrary.terrain.heightMapTexture); gpu_NormalMap.SetValue(objectLibrary.terrain.normalMapTexture); // Spatial Updates ShaderParameters.effect_update.CurrentTechnique = ShaderParameters.effect_update.Techniques[gpuObjectList.locationMap.technique]; ExecuteSpatialRTT(gpuObjectList.locationMap._writeRenderTarget, gpuObjectList.locationMap._depthBuff); gpuObjectList.locationMap.SwapBuffers(); //gpuObjectList.locationMap.WriteToFile(); //// Indexed Updates for (int i = 0; i < gpuObjectList.variables.Count; i++) { if (gpuObjectList.variables[i].isDynamic) { if (gpuObjectList.variables[i].processorMode == Enums.GpuProcessorMode.Indexed) { ShaderParameters.effect_update.CurrentTechnique = ShaderParameters.effect_update.Techniques[gpuObjectList.variables[i].technique]; ExecuteIndexedRTT(gpuObjectList.variables[i]._writeRenderTarget); gpuObjectList.variables[i].SwapBuffers(); //gpuObjectList.variables[i].WriteToFile(); } if (gpuObjectList.variables[i].processorMode == Enums.GpuProcessorMode.Spatial) { } } } Statics.SystemSettings.graphics.GraphicsDevice.SetRenderTarget(0, null); } private void ExecuteIndexedRTT( RenderTarget2D renderTarget) { // Set up Graphics Device GraphicsDevice g = Statics.SystemSettings.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)); ShaderParameters.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 ShaderParameters.effect_update.Begin(); foreach (EffectPass pass in ShaderParameters.effect_update.CurrentTechnique.Passes) { pass.Begin(); g.VertexDeclaration = quad_vertexDeclaration; g.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2); pass.End(); } ShaderParameters.effect_update.End(); // Gets the Rendered Texture and store it in the RenderTarget variable //g.ResolveRenderTarget(0); g.SetRenderTarget(0, null); //g.RenderState.DepthBufferEnable = true; // Retrieve the Shadow map from our Render Target //renderTargetTexture = renderTarget.GetTexture(); //renderTargetTexture.Save("indexedTexture.png", ImageFileFormat.Png); } private void ExecuteSpatialRTT(RenderTarget2D renderTarget, DepthStencilBuffer depthBuff) { // Set up Graphics Device GraphicsDevice g = Statics.SystemSettings.graphics.GraphicsDevice; g.Viewport = SpatialViewport; g.RenderState.DepthBufferEnable = false; // Setup view and projection matrixes Matrix proj = Matrix.CreateOrthographic(1.0f, 1.0f, 0, 5); Matrix view = Matrix.CreateLookAt(new Vector3(0.5f, 0.5f, -1.0f), new Vector3(0.5f, 0.5f, 0.0f), new Vector3(0.0f, 1.0f, 0.0f)); ShaderParameters.effect_update.Parameters["ViewProj"].SetValue(view * proj); ShaderParameters.effect_update.Parameters["gpuObjectScale"].SetValue(Statics.TerrainSettings.collisionMapSize); // Set Points Vertex Buffer g.Vertices[0].SetSource(point_vertexBuffer, 0, VertexPositionNormalTexture.SizeInBytes); // Set and clear RTT texture g.SetRenderTarget(0, renderTarget); DepthStencilBuffer old = g.DepthStencilBuffer; g.DepthStencilBuffer = depthBuff; g.Clear(ClearOptions.Target, Color.TransparentWhite, 1.0f, 0); // Draw Quad ShaderParameters.effect_update.Begin(); foreach (EffectPass pass in ShaderParameters.effect_update.CurrentTechnique.Passes) { pass.Begin(); g.VertexDeclaration = point_vertexDeclaration; g.DrawPrimitives(PrimitiveType.PointList, 0, Statics.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE * Statics.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE); pass.End(); } ShaderParameters.effect_update.End(); // Gets the Rendered Texture and store it in the RenderTarget variable //g.ResolveRenderTarget(0); g.SetRenderTarget(0, null); g.DepthStencilBuffer = old; //g.RenderState.DepthBufferEnable = true; //renderTarget.GetTexture().Save("gpuPhysicsTex.png", ImageFileFormat.Png); } } }