//--------------------------------------------------------------------------------------------------------------------------------------------------- // // Copyright (C)2007 DarkWynter Studios. All rights reserved. // //--------------------------------------------------------------------------------------------------------------------------------------------------- // {Contact : darkwynter.com for licensing information //--------------------------------------------------------------------------------------------------------------------------------------------------- namespace DarkWynter.Stream.PhysicsGpu { #region Using Statements using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using System.Diagnostics; #endregion /// /// Vertex structure for GPU Physics updates /// public struct VertexPosition { /// /// Vertex position /// public Vector3 position; } /// /// 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 VertexPositionTexture[] 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 VertexPosition[] point_vertices; // Array to store vertex Position, Normal and Texture information private VertexDeclaration point_vertexDeclaration; // Vertex Declaration // Update Shader ================================================================================== public static float gravity = 0.0f; // Stores value modifiable through controller private int UPDATE_TIME_MILLI = 100; private Stopwatch runUpdateTimer = new Stopwatch(); // Tells the GPU how to format the streams private VertexElement[] Elements = new VertexElement[] { new VertexElement(0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0), }; // ================================\ Methods /===================================================== // ================================================================================================ /// /// GpuProcessor constructor sets up Quad and Quad of Points mechanics. /// public GpuProcessor() { //// Get Draw Handles //currentPositionParam = effect_draw.Parameters["CurrentPosition"]; //scaleRange = effect_draw.Parameters["scaleRange"]; //minimumValue = effect_draw.Parameters["minimumValue"]; // Create geometry used in render passes CreateQuad(); CreatePoints(); runUpdateTimer.Reset(); runUpdateTimer.Start(); } private void CreateQuad() { // Set up the Indexed viewport IndexedViewport.X = 0; IndexedViewport.Y = 0; IndexedViewport.Width = Statics_Stream.GPU_ProcessorSettings.INDEXED_TARGET_SIZE; IndexedViewport.Height = Statics_Stream.GPU_ProcessorSettings.INDEXED_TARGET_SIZE; IndexedViewport.MinDepth = Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.MinDepth; IndexedViewport.MaxDepth = Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.MaxDepth; GraphicsDevice gd = Statics_Stream.RenderSettings.graphics.GraphicsDevice; // Create a 4 point vertex buffer quad_vertices = new VertexPositionTexture[4]; quad_vertexDeclaration = new VertexDeclaration(gd, VertexPositionTexture.VertexElements); quad_vertexBuffer = new VertexBuffer(gd, VertexPositionTexture.SizeInBytes * 4, BufferUsage.WriteOnly); // Create quad with width and height = 1 quad_vertices[0] = new VertexPositionTexture(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 VertexPositionTexture(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 VertexPositionTexture(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 VertexPositionTexture(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_Stream.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE; SpatialViewport.Height = Statics_Stream.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE; SpatialViewport.MinDepth = Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.MinDepth; SpatialViewport.MaxDepth = Statics_Stream.RenderSettings.graphics.GraphicsDevice.Viewport.MaxDepth; float spatMap = 1.0f / (float)Statics_Stream.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE; ShaderParameters.UpdateFX.invSpatMapHeight.SetValue(spatMap); ShaderParameters.UpdateFX.invSpatMapWidth.SetValue(spatMap); GraphicsDevice gd = Statics_Stream.RenderSettings.graphics.GraphicsDevice; point_vertices = new VertexPosition[Statics_Stream.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE * Statics_Stream.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE]; point_vertexDeclaration = new VertexDeclaration(gd, Elements); point_vertexBuffer = new VertexBuffer(gd, typeof(VertexPosition), Statics_Stream.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE * Statics_Stream.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_Stream.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].position = new Vector3(((float)i / pixelLength), ((float)j / pixelLength), 0.0f); 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. /// /// location map /// List of gpu variables // CLEAN: REMOVE BOTH PARAMETERS, REPLACE WITH SINGLE GPU OBJECT public void ExecuteRTT(SpatialMap locationMap, List variables) { // Set Gravity //gravity += objectLibrary.humans[0].playerController.gameInput.GetGPUGravityButton; ShaderParameters.UpdateFX.gravity.SetValue(gravity); if (runUpdateTimer.ElapsedMilliseconds >= UPDATE_TIME_MILLI) { runUpdateTimer.Reset(); runUpdateTimer.Start(); // Spatial Updates ShaderParameters.UpdateFX.effect.CurrentTechnique = ShaderParameters.UpdateFX.effect.Techniques[locationMap.technique]; ExecuteSpatialRTT(locationMap._writeRenderTarget, locationMap._depthBuff); locationMap.SwapBuffers(); //locationMap.WriteToFile(); // Indexed Updates for (int i = 0; i < variables.Count; i++) { if (variables[i].isDynamic) { if (variables[i].processorMode == Enums_Stream.GpuProcessorMode.Indexed) { ShaderParameters.UpdateFX.effect.CurrentTechnique = ShaderParameters.UpdateFX.effect.Techniques[variables[i].technique]; ExecuteIndexedRTT(variables[i]._writeRenderTarget); variables[i].SwapBuffers(); //variables[i].WriteToFile(); } if (variables[i].technique == "Velocity") { //variables[i].WriteToFile(); } } } Statics_Stream.RenderSettings.graphics.GraphicsDevice.SetRenderTarget(0, null); } } private void ExecuteIndexedRTT( RenderTarget2D renderTarget) { // Set up Graphics Device GraphicsDevice g = Statics_Stream.RenderSettings.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.UpdateFX.effect.Parameters["ViewProj"].SetValue(view * proj); // Set Quad Vertex Buffer g.Vertices[0].SetSource(quad_vertexBuffer, 0, quad_vertexDeclaration.GetVertexStrideSize(0)); // Set and clear RTT texture g.SetRenderTarget(0, renderTarget); g.Clear(ClearOptions.Target, Color.TransparentWhite, 1.0f, 0); // Draw Quad ShaderParameters.UpdateFX.effect.Begin(); foreach (EffectPass pass in ShaderParameters.UpdateFX.effect.CurrentTechnique.Passes) { pass.Begin(); g.VertexDeclaration = quad_vertexDeclaration; g.DrawPrimitives(PrimitiveType.TriangleFan, 0, 2); pass.End(); } ShaderParameters.UpdateFX.effect.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_Stream.RenderSettings.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.UpdateFX.effect.Parameters["ViewProj"].SetValue(view * proj); // Set Points Vertex Buffer g.Vertices[0].SetSource(point_vertexBuffer, 0, point_vertexDeclaration.GetVertexStrideSize(0)); // 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.UpdateFX.effect.Begin(); foreach (EffectPass pass in ShaderParameters.UpdateFX.effect.CurrentTechnique.Passes) { pass.Begin(); g.VertexDeclaration = point_vertexDeclaration; g.DrawPrimitives(PrimitiveType.PointList, 0, Statics_Stream.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE * Statics_Stream.GPU_ProcessorSettings.SPATIAL_TARGET_SIZE); pass.End(); } ShaderParameters.UpdateFX.effect.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); } } }