Advertisement
Guest User

Paradox ParticleRenderer

a guest
Feb 2nd, 2015
214
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.94 KB | None | 0 0
  1. using System;
  2. using System.Runtime.InteropServices;
  3. using SiliconStudio.Paradox.Effects;
  4. using SiliconStudio.Paradox.Effects.Modules;
  5. using SiliconStudio.Paradox.Engine;
  6. using SiliconStudio.Paradox.Games;
  7. using SiliconStudio.Paradox.Graphics;
  8. using SiliconStudio.Core;
  9. using SiliconStudio.Core.Mathematics;
  10. using SiliconStudio.Paradox.Particles;
  11. using SiliconStudio.Paradox.Shaders;
  12. using SiliconStudio.Paradox.Shaders.Compiler;
  13. using Buffer = SiliconStudio.Paradox.Graphics.Buffer;
  14.  
  15. namespace Particles
  16. {
  17.     /// <summary>
  18.     /// Particle renderer.
  19.     /// TODO Use SpriteBatch
  20.     /// </summary>
  21.     [EffectKeys]
  22.     public class ParticleRenderer
  23.     {
  24.         public static readonly ParameterKey<ParticleSystem> ParticleSystemKey = ParameterKeys.New<ParticleSystem>();
  25.  
  26.         private Effect effect;
  27.         private IGame game;
  28.         private Buffer vertexBuffer, indexBuffer;
  29.         private VertexArrayObject vao;
  30.  
  31.         /// <summary>
  32.         /// The vector which, when multiplied by WorldView, represents UnitX in view space.
  33.         /// Useful to apply transformation such as billboard, that requires view space translation on the world space coordinates.
  34.         /// </summary>
  35.         public static readonly ParameterKey<Vector3> ParticleUnitX = ParameterKeys.NewDynamic(ParameterDynamicValue.New(TransformationKeys.ViewInverse,
  36.             (ref Matrix worldViewInverse, ref Vector3 output) => output = new Vector3(worldViewInverse.M11, worldViewInverse.M12, worldViewInverse.M13)));
  37.  
  38.         /// <summary>
  39.         /// The vector which, when multiplied by WorldView, represents UnitY in view space.
  40.         /// Useful to apply transformation such as billboard, that requires view space translation on the world space coordinates.
  41.         /// </summary>
  42.         public static readonly ParameterKey<Vector3> ParticleUnitY = ParameterKeys.NewDynamic(ParameterDynamicValue.New(TransformationKeys.ViewInverse,
  43.             (ref Matrix worldViewInverse, ref Vector3 output) => output = new Vector3(worldViewInverse.M21, worldViewInverse.M22, worldViewInverse.M23)));
  44.  
  45.         private const int BufferParticleCount = 4096;
  46.  
  47.         public ParticleRenderer(GraphicsDevice graphicsDevice, EffectSystem effectSystem)
  48.         {
  49.             // compile effect
  50.             var compilerParameters = new CompilerParameters();
  51.             compilerParameters.Profile = graphicsDevice.Features.Profile;
  52.             var bytecode = effectSystem.Compiler.Compile(new ShaderClassSource("ParticleBillboard"), compilerParameters);
  53.  
  54.             // create the effect for rendering
  55.             effect = new Effect(graphicsDevice, bytecode.Bytecodes[0]);
  56.             //effect = new SimpleEffect(GraphicsDevice);
  57.  
  58.             ////effectMeshPass.Parameters.Set(BlendStateKey, GraphicsDevice.BlendStates.AlphaBlend);
  59.             //effectMesh.Parameters.Set(DepthStencilStateKey, GraphicsDevice.DepthStencilStates.DepthRead);
  60.             //effectMesh.Parameters.Set(RasterizerStateKey, GraphicsDevice.RasterizerStates.CullNone);
  61.  
  62.             // Initialize default index buffer
  63.             var indices = new ushort[BufferParticleCount * 6];
  64.             for (int i = 0, baseIndex = 0, baseVertex = 0; i < BufferParticleCount; ++i, baseVertex += 4)
  65.             {
  66.                 indices[baseIndex++] = (ushort)(baseVertex + 0);
  67.                 indices[baseIndex++] = (ushort)(baseVertex + 1);
  68.                 indices[baseIndex++] = (ushort)(baseVertex + 3);
  69.                 indices[baseIndex++] = (ushort)(baseVertex + 3);
  70.                 indices[baseIndex++] = (ushort)(baseVertex + 1);
  71.                 indices[baseIndex++] = (ushort)(baseVertex + 2);
  72.             }
  73.  
  74.             // Create GPU buffers
  75.             vertexBuffer = Buffer.Vertex.New(graphicsDevice, Utilities.SizeOf<ParticleVertex>() * BufferParticleCount * 4, GraphicsResourceUsage.Dynamic);
  76.             indexBuffer = Buffer.Index.New(graphicsDevice, indices);
  77.  
  78.             //var vertexDeclaration = new VertexDeclaration(
  79.             //    VertexElement.Position<Half4>(), // Position contains the Size in w
  80.             //    VertexElement.TextureCoordinate<Half2>(),
  81.             //    VertexElement.Color(PixelFormat.R8G8B8A8_UNorm));
  82.  
  83.             var vertexDeclaration = new VertexDeclaration(
  84.                 VertexElement.Position<Vector4>(), // Position contains the Size in w
  85.                 VertexElement.TextureCoordinate<Vector2>(),
  86.                 VertexElement.Color(PixelFormat.R8G8B8A8_UNorm));
  87.  
  88.             // Create Vertex Array Object
  89.             vao = VertexArrayObject.New(graphicsDevice, effect.InputSignature, new IndexBufferBinding(indexBuffer, false, BufferParticleCount * 6), new VertexBufferBinding(vertexBuffer, vertexDeclaration, BufferParticleCount * 4));
  90.         }
  91.  
  92.         public Effect Effect
  93.         {
  94.             get { return effect; }
  95.         }
  96.  
  97.         public unsafe void Render(GraphicsDevice graphicsDevice, ParticleSystem particleSystem)
  98.         {
  99.             // Update vertex buffer
  100.             var dataBox = graphicsDevice.MapSubresource(vertexBuffer, 0, MapMode.WriteDiscard);
  101.             var particleVertices = (ParticleVertex*)dataBox.DataBox.DataPointer;
  102.  
  103.             var colorField = particleSystem.GetField(ParticleFields.Color);
  104.             var sizeField = particleSystem.GetField(ParticleFields.Size);
  105.  
  106.             var rotationAccessor = particleSystem.GetField(ParticleFields.Rotation);
  107.  
  108.             if (rotationAccessor.IsValid())
  109.             {
  110.                 foreach (var particle in particleSystem)
  111.                 {
  112.                     var vertex = new ParticleVertex();
  113.                     var centerPos = particle.Get(particleSystem.Position);
  114.                     var partSize = particle.Get(sizeField);
  115.                     var rotation = particle.Get(rotationAccessor);
  116.  
  117.                     Matrix rotationMatrix;
  118.                     TransformationProcessor.CreateMatrixR(ref rotation, out rotationMatrix);
  119.                     var unitX = partSize * (Vector3)rotationMatrix.Row1;
  120.                     var unitY = partSize * (Vector3)rotationMatrix.Row2;
  121.  
  122.                     // Prepare common vertex data
  123.                     vertex.Color = colorField.IsValid() ? (uint)particle.Get(colorField).ToRgba() : 0xFFFFFFFF;
  124.                     vertex.Size = (Half)partSize;
  125.  
  126.                     // 0.0f, 0.0f
  127.                     var position = centerPos - unitX - unitY;
  128.                     vertex.Position = new Half3(position.X, position.Y, position.Z);
  129.                     vertex.TexCoord = new Half2();
  130.                     *particleVertices++ = vertex;
  131.  
  132.                     // 0.0f, 1.0f
  133.                     position = centerPos - unitX + unitY;
  134.                     vertex.Position = new Half3(position.X, position.Y, position.Z);
  135.                     vertex.TexCoord = new Half2(0, 1);
  136.                     *particleVertices++ = vertex;
  137.  
  138.                     // 1.0f, 1.0f
  139.                     position = centerPos + unitX + unitY;
  140.                     vertex.Position = new Half3(position.X, position.Y, position.Z);
  141.                     vertex.TexCoord = new Half2(1, 1);
  142.                     *particleVertices++ = vertex;
  143.  
  144.                     // 1.0f, 0.0f
  145.                     position = centerPos + unitX - unitY;
  146.                     vertex.Position = new Half3(position.X, position.Y, position.Z);
  147.                     vertex.TexCoord = new Half2(1, 0);
  148.                     *particleVertices++ = vertex;
  149.                 }
  150.             }
  151.             else
  152.             {
  153.                 foreach (var particle in particleSystem)
  154.                 {
  155.                     var vertex = new ParticleVertex();
  156.                     var position = particle.Get(particleSystem.Position);
  157.  
  158.                     // Prepare common vertex data
  159.                     vertex.Position = new Half3(position.X, position.Y, position.Z);
  160.                     vertex.Color = colorField.IsValid() ? (uint)particle.Get(colorField).ToRgba() : 0xFFFFFFFF;
  161.                     vertex.Size = (Half)particle.Get(sizeField);
  162.  
  163.                     // 0.0f, 0.0f
  164.                     vertex.TexCoord = new Half2();
  165.                     *particleVertices++ = vertex;
  166.  
  167.                     // 0.0f, 1.0f
  168.                     vertex.TexCoord = new Half2(0, 1);
  169.                     *particleVertices++ = vertex;
  170.  
  171.                     // 1.0f, 1.0f
  172.                     vertex.TexCoord = new Half2(1, 1);
  173.                     *particleVertices++ = vertex;
  174.  
  175.                     // 1.0f, 0.0f
  176.                     vertex.TexCoord = new Half2(1, 0);
  177.                     *particleVertices++ = vertex;
  178.                 }
  179.             }
  180.  
  181.             graphicsDevice.SetDepthStencilState(graphicsDevice.DepthStencilStates.DepthRead);
  182.             graphicsDevice.SetRasterizerState(graphicsDevice.RasterizerStates.CullNone);
  183.  
  184.             graphicsDevice.UnmapSubresource(dataBox);
  185.  
  186.             graphicsDevice.SetVertexArrayObject(vao);
  187.             graphicsDevice.DrawIndexed(PrimitiveType.TriangleList, particleSystem.ParticleCount * 6);
  188.  
  189.             // TODO: Draw the primitive using BasicEffect?
  190.             //var viewProj = Matrix.Multiply(view, projection);
  191.             //var currentViewport = GraphicsDevice.Viewport;
  192.             //spriteBatch.Begin(SpriteSortMode.BackToFront, GraphicsDevice.BlendStates.AlphaBlend, null, null, null, effect);
  193.             //foreach (var particle in particleSystem)
  194.             //{
  195.             //    var centerPos = particle.Get(particleSystem.Position);
  196.             //    //var centerPos = new Vector3(0.0f, 0.0f, 0.0f);
  197.             //    Vector3.TransformCoordinate(ref centerPos, ref viewProj, out centerPos);
  198.             //    var position = new Vector2(((centerPos.X + 1.0f) * 0.5f) * currentViewport.Width, ((centerPos.Y + 1.0f) * 0.5f) * currentViewport.Height);
  199.             //    var size =
  200.             //    spriteBatch.Draw(texture, position, Color.White, 0.0f, new Vector2(texture.Width * 0.5f, texture.Height * 0.5f), 0.1f);
  201.             //}
  202.             //spriteBatch.End();
  203.         }
  204.  
  205.         //[StructLayout(LayoutKind.Sequential)]
  206.         //public struct ParticleVertex
  207.         //{
  208.         //    public Half3 Position;
  209.         //    public Half Size;
  210.         //    public Half2 TexCoord;
  211.         //    public uint Color;
  212.         //}
  213.  
  214.         [StructLayout(LayoutKind.Sequential)]
  215.         public struct ParticleVertex
  216.         {
  217.             private Vector3 position;
  218.  
  219.             public Half3 Position
  220.             {
  221.                 get { return (Half3)position; }
  222.                 set
  223.                 {
  224.                     position = (Vector3) value;
  225.                 }
  226.             }
  227.  
  228.  
  229.             public float Size;
  230.            
  231.             private Vector2 texCoord;
  232.             public Half2 TexCoord
  233.             {
  234.                 get
  235.                 {
  236.                     return (Half2) texCoord;
  237.                 }
  238.                 set
  239.                 {
  240.                     texCoord = (Vector2) value;
  241.                 }
  242.             }
  243.  
  244.             public uint Color;
  245.         }
  246.     }
  247. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement