Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Runtime.InteropServices;
- using SiliconStudio.Paradox.Effects;
- using SiliconStudio.Paradox.Effects.Modules;
- using SiliconStudio.Paradox.Engine;
- using SiliconStudio.Paradox.Games;
- using SiliconStudio.Paradox.Graphics;
- using SiliconStudio.Core;
- using SiliconStudio.Core.Mathematics;
- using SiliconStudio.Paradox.Particles;
- using SiliconStudio.Paradox.Shaders;
- using SiliconStudio.Paradox.Shaders.Compiler;
- using Buffer = SiliconStudio.Paradox.Graphics.Buffer;
- namespace Particles
- {
- /// <summary>
- /// Particle renderer.
- /// TODO Use SpriteBatch
- /// </summary>
- [EffectKeys]
- public class ParticleRenderer
- {
- public static readonly ParameterKey<ParticleSystem> ParticleSystemKey = ParameterKeys.New<ParticleSystem>();
- private Effect effect;
- private IGame game;
- private Buffer vertexBuffer, indexBuffer;
- private VertexArrayObject vao;
- /// <summary>
- /// The vector which, when multiplied by WorldView, represents UnitX in view space.
- /// Useful to apply transformation such as billboard, that requires view space translation on the world space coordinates.
- /// </summary>
- public static readonly ParameterKey<Vector3> ParticleUnitX = ParameterKeys.NewDynamic(ParameterDynamicValue.New(TransformationKeys.ViewInverse,
- (ref Matrix worldViewInverse, ref Vector3 output) => output = new Vector3(worldViewInverse.M11, worldViewInverse.M12, worldViewInverse.M13)));
- /// <summary>
- /// The vector which, when multiplied by WorldView, represents UnitY in view space.
- /// Useful to apply transformation such as billboard, that requires view space translation on the world space coordinates.
- /// </summary>
- public static readonly ParameterKey<Vector3> ParticleUnitY = ParameterKeys.NewDynamic(ParameterDynamicValue.New(TransformationKeys.ViewInverse,
- (ref Matrix worldViewInverse, ref Vector3 output) => output = new Vector3(worldViewInverse.M21, worldViewInverse.M22, worldViewInverse.M23)));
- private const int BufferParticleCount = 4096;
- public ParticleRenderer(GraphicsDevice graphicsDevice, EffectSystem effectSystem)
- {
- // compile effect
- var compilerParameters = new CompilerParameters();
- compilerParameters.Profile = graphicsDevice.Features.Profile;
- var bytecode = effectSystem.Compiler.Compile(new ShaderClassSource("ParticleBillboard"), compilerParameters);
- // create the effect for rendering
- effect = new Effect(graphicsDevice, bytecode.Bytecodes[0]);
- //effect = new SimpleEffect(GraphicsDevice);
- ////effectMeshPass.Parameters.Set(BlendStateKey, GraphicsDevice.BlendStates.AlphaBlend);
- //effectMesh.Parameters.Set(DepthStencilStateKey, GraphicsDevice.DepthStencilStates.DepthRead);
- //effectMesh.Parameters.Set(RasterizerStateKey, GraphicsDevice.RasterizerStates.CullNone);
- // Initialize default index buffer
- var indices = new ushort[BufferParticleCount * 6];
- for (int i = 0, baseIndex = 0, baseVertex = 0; i < BufferParticleCount; ++i, baseVertex += 4)
- {
- indices[baseIndex++] = (ushort)(baseVertex + 0);
- indices[baseIndex++] = (ushort)(baseVertex + 1);
- indices[baseIndex++] = (ushort)(baseVertex + 3);
- indices[baseIndex++] = (ushort)(baseVertex + 3);
- indices[baseIndex++] = (ushort)(baseVertex + 1);
- indices[baseIndex++] = (ushort)(baseVertex + 2);
- }
- // Create GPU buffers
- vertexBuffer = Buffer.Vertex.New(graphicsDevice, Utilities.SizeOf<ParticleVertex>() * BufferParticleCount * 4, GraphicsResourceUsage.Dynamic);
- indexBuffer = Buffer.Index.New(graphicsDevice, indices);
- //var vertexDeclaration = new VertexDeclaration(
- // VertexElement.Position<Half4>(), // Position contains the Size in w
- // VertexElement.TextureCoordinate<Half2>(),
- // VertexElement.Color(PixelFormat.R8G8B8A8_UNorm));
- var vertexDeclaration = new VertexDeclaration(
- VertexElement.Position<Vector4>(), // Position contains the Size in w
- VertexElement.TextureCoordinate<Vector2>(),
- VertexElement.Color(PixelFormat.R8G8B8A8_UNorm));
- // Create Vertex Array Object
- vao = VertexArrayObject.New(graphicsDevice, effect.InputSignature, new IndexBufferBinding(indexBuffer, false, BufferParticleCount * 6), new VertexBufferBinding(vertexBuffer, vertexDeclaration, BufferParticleCount * 4));
- }
- public Effect Effect
- {
- get { return effect; }
- }
- public unsafe void Render(GraphicsDevice graphicsDevice, ParticleSystem particleSystem)
- {
- // Update vertex buffer
- var dataBox = graphicsDevice.MapSubresource(vertexBuffer, 0, MapMode.WriteDiscard);
- var particleVertices = (ParticleVertex*)dataBox.DataBox.DataPointer;
- var colorField = particleSystem.GetField(ParticleFields.Color);
- var sizeField = particleSystem.GetField(ParticleFields.Size);
- var rotationAccessor = particleSystem.GetField(ParticleFields.Rotation);
- if (rotationAccessor.IsValid())
- {
- foreach (var particle in particleSystem)
- {
- var vertex = new ParticleVertex();
- var centerPos = particle.Get(particleSystem.Position);
- var partSize = particle.Get(sizeField);
- var rotation = particle.Get(rotationAccessor);
- Matrix rotationMatrix;
- TransformationProcessor.CreateMatrixR(ref rotation, out rotationMatrix);
- var unitX = partSize * (Vector3)rotationMatrix.Row1;
- var unitY = partSize * (Vector3)rotationMatrix.Row2;
- // Prepare common vertex data
- vertex.Color = colorField.IsValid() ? (uint)particle.Get(colorField).ToRgba() : 0xFFFFFFFF;
- vertex.Size = (Half)partSize;
- // 0.0f, 0.0f
- var position = centerPos - unitX - unitY;
- vertex.Position = new Half3(position.X, position.Y, position.Z);
- vertex.TexCoord = new Half2();
- *particleVertices++ = vertex;
- // 0.0f, 1.0f
- position = centerPos - unitX + unitY;
- vertex.Position = new Half3(position.X, position.Y, position.Z);
- vertex.TexCoord = new Half2(0, 1);
- *particleVertices++ = vertex;
- // 1.0f, 1.0f
- position = centerPos + unitX + unitY;
- vertex.Position = new Half3(position.X, position.Y, position.Z);
- vertex.TexCoord = new Half2(1, 1);
- *particleVertices++ = vertex;
- // 1.0f, 0.0f
- position = centerPos + unitX - unitY;
- vertex.Position = new Half3(position.X, position.Y, position.Z);
- vertex.TexCoord = new Half2(1, 0);
- *particleVertices++ = vertex;
- }
- }
- else
- {
- foreach (var particle in particleSystem)
- {
- var vertex = new ParticleVertex();
- var position = particle.Get(particleSystem.Position);
- // Prepare common vertex data
- vertex.Position = new Half3(position.X, position.Y, position.Z);
- vertex.Color = colorField.IsValid() ? (uint)particle.Get(colorField).ToRgba() : 0xFFFFFFFF;
- vertex.Size = (Half)particle.Get(sizeField);
- // 0.0f, 0.0f
- vertex.TexCoord = new Half2();
- *particleVertices++ = vertex;
- // 0.0f, 1.0f
- vertex.TexCoord = new Half2(0, 1);
- *particleVertices++ = vertex;
- // 1.0f, 1.0f
- vertex.TexCoord = new Half2(1, 1);
- *particleVertices++ = vertex;
- // 1.0f, 0.0f
- vertex.TexCoord = new Half2(1, 0);
- *particleVertices++ = vertex;
- }
- }
- graphicsDevice.SetDepthStencilState(graphicsDevice.DepthStencilStates.DepthRead);
- graphicsDevice.SetRasterizerState(graphicsDevice.RasterizerStates.CullNone);
- graphicsDevice.UnmapSubresource(dataBox);
- graphicsDevice.SetVertexArrayObject(vao);
- graphicsDevice.DrawIndexed(PrimitiveType.TriangleList, particleSystem.ParticleCount * 6);
- // TODO: Draw the primitive using BasicEffect?
- //var viewProj = Matrix.Multiply(view, projection);
- //var currentViewport = GraphicsDevice.Viewport;
- //spriteBatch.Begin(SpriteSortMode.BackToFront, GraphicsDevice.BlendStates.AlphaBlend, null, null, null, effect);
- //foreach (var particle in particleSystem)
- //{
- // var centerPos = particle.Get(particleSystem.Position);
- // //var centerPos = new Vector3(0.0f, 0.0f, 0.0f);
- // Vector3.TransformCoordinate(ref centerPos, ref viewProj, out centerPos);
- // var position = new Vector2(((centerPos.X + 1.0f) * 0.5f) * currentViewport.Width, ((centerPos.Y + 1.0f) * 0.5f) * currentViewport.Height);
- // var size =
- // spriteBatch.Draw(texture, position, Color.White, 0.0f, new Vector2(texture.Width * 0.5f, texture.Height * 0.5f), 0.1f);
- //}
- //spriteBatch.End();
- }
- //[StructLayout(LayoutKind.Sequential)]
- //public struct ParticleVertex
- //{
- // public Half3 Position;
- // public Half Size;
- // public Half2 TexCoord;
- // public uint Color;
- //}
- [StructLayout(LayoutKind.Sequential)]
- public struct ParticleVertex
- {
- private Vector3 position;
- public Half3 Position
- {
- get { return (Half3)position; }
- set
- {
- position = (Vector3) value;
- }
- }
- public float Size;
- private Vector2 texCoord;
- public Half2 TexCoord
- {
- get
- {
- return (Half2) texCoord;
- }
- set
- {
- texCoord = (Vector2) value;
- }
- }
- public uint Color;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement