public VerletDebrisSystem(int maxNumParticles, float timestep, int maxIterations, Material material, Bounds bounds, TerrainSystem terrainSystem)
        {
            this.timestep      = timestep;
            this.maxIterations = maxIterations;
            this.material      = material;
            this.bounds        = bounds;
            this.terrainSystem = terrainSystem;

            positionsBuffer     = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(Vector2)));
            velocitiesBuffer    = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(Vector2)));
            lifetimesBuffer     = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(Vector2)));
            predictedBuffers    = new ComputeBuffer[2];
            predictedBuffers[0] = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(Vector2)));
            predictedBuffers[1] = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(Vector2)));
            deadBuffer          = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(uint)), ComputeBufferType.Append);
            deadBuffer.SetCounterValue(0);
            aliveBuffer = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(uint)), ComputeBufferType.Append);
            aliveBuffer.SetCounterValue(0);
            emitBuffer = new ComputeBuffer(THREADS, Marshal.SizeOf(typeof(Vector4)));
            counter    = new ComputeBuffer(4, Marshal.SizeOf(typeof(uint)), ComputeBufferType.IndirectArguments);
            counter.SetData(new int[] { 0, 1, 0, 0 });
            emitCounter = new ComputeBuffer(4, Marshal.SizeOf(typeof(uint)), ComputeBufferType.IndirectArguments);
            emitCounter.SetData(new int[] { 0, 1, 0, 0 });
            argsBuffer = new ComputeBuffer(5, Marshal.SizeOf(typeof(uint)), ComputeBufferType.IndirectArguments);

            GameObject o = GameObject.CreatePrimitive(PrimitiveType.Quad);

            mesh = o.GetComponent <MeshFilter>().sharedMesh;
            GameObject.DestroyImmediate(o);
            uint[] argsData = new uint[] { mesh.GetIndexCount(0), 0, 0, 0, 0 };
            argsBuffer.SetData(argsData);

            computeShader = (ComputeShader)Resources.Load("VerletDebrisSystem");
            computeShader.SetFloat("DT", timestep);
            computeShader.SetVector("Gravity", new Vector2(0, -98.1f));
            computeShader.SetFloat("Damping", 0.5f);
            computeShader.SetVector("_TerrainDistanceFieldScale", terrainSystem.terrainDistanceFieldScale);
            computeShader.SetFloat("_TerrainDistanceFieldMultiplier", terrainSystem.terrainDistanceFieldMultiplier);

            int initKernel = computeShader.FindKernel("Init");

            computeShader.SetInt("Width", positionsBuffer.count);
            computeShader.SetBuffer(initKernel, "PositionsWRITE", positionsBuffer);
            computeShader.SetBuffer(initKernel, "VelocitiesWRITE", velocitiesBuffer);
            computeShader.SetBuffer(initKernel, "Lifetimes", lifetimesBuffer);
            computeShader.SetBuffer(initKernel, "Dead", deadBuffer);
            computeShader.Dispatch(initKernel, Groups(maxNumParticles), 1, 1);

            hash = new GridHash(bounds, maxNumParticles, 1);
            computeShader.SetFloat("HashScale", hash.InvCellSize);
            computeShader.SetVector("HashSize", hash.Bounds.size);
            computeShader.SetVector("HashTranslate", hash.Bounds.min);
        }
        public LeapfrogDebrisSystem(int maxNumParticles, float timestep, int maxIterations, Material material, Bounds bounds, TerrainSystem terrainSystem)
        {
            this.timestep      = timestep;
            this.maxIterations = maxIterations;
            this.material      = material;
            this.bounds        = bounds;
            this.terrainSystem = terrainSystem;

            explosionsBuffer = new ComputeBuffer(16, Marshal.SizeOf(typeof(Vector4)), ComputeBufferType.Default);

            positionsBuffers     = new ComputeBuffer[2];
            positionsBuffers[0]  = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(Vector2)));
            positionsBuffers[1]  = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(Vector2)));
            velocitiesBuffers    = new ComputeBuffer[2];
            velocitiesBuffers[0] = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(Vector2)));
            velocitiesBuffers[1] = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(Vector2)));
            lifetimesBuffer      = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(Vector2)));
            motionsBuffer        = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(float)));
            colorsBuffer         = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(Vector4)));

            deadBuffer = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(uint)), ComputeBufferType.Append);
            deadBuffer.SetCounterValue(0);
            aliveBuffer = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(uint)), ComputeBufferType.Append);
            aliveBuffer.SetCounterValue(0);
            addTerrainBuffer = new ComputeBuffer(maxNumParticles, Marshal.SizeOf(typeof(Vector2)), ComputeBufferType.Append);
            addTerrainBuffer.SetCounterValue(0);

            counter = new ComputeBuffer(4, Marshal.SizeOf(typeof(uint)), ComputeBufferType.IndirectArguments);
            counter.SetData(new int[] { 0, 1, 0, 0 });
            counterIndex = new ComputeBuffer(1, Marshal.SizeOf(typeof(uint)), ComputeBufferType.Raw);
            emitCounter  = new ComputeBuffer(4, Marshal.SizeOf(typeof(uint)), ComputeBufferType.IndirectArguments);
            emitCounter.SetData(new uint[] { 0, 1, 0, 0 });
            argsBuffer = new ComputeBuffer(5, Marshal.SizeOf(typeof(uint)), ComputeBufferType.IndirectArguments);

            GameObject o = GameObject.CreatePrimitive(PrimitiveType.Quad);

            mesh = o.GetComponent <MeshFilter>().sharedMesh;
            GameObject.DestroyImmediate(o);
            uint[] argsData = new uint[] { mesh.GetIndexCount(0), 0, 0, 0, 0 };
            argsBuffer.SetData(argsData);

            computeShader = (ComputeShader)Resources.Load("LeapfrogDebrisSystem");
            computeShader.SetFloat("DT", timestep);
            computeShader.SetVector("Gravity", new Vector2(0, -98.1f));
            computeShader.SetFloat("Damping", 0.99f);
            computeShader.SetVector("_TerrainDistanceFieldScale", terrainSystem.terrainDistanceFieldScale);
            computeShader.SetFloat("_TerrainDistanceFieldMultiplier", terrainSystem.terrainDistanceFieldMultiplier);
            computeShader.SetVector("_TerrainSize", new Vector2(terrainSystem.width, terrainSystem.height));

            Vector2 boundsMin    = bounds.min;
            Vector2 boundsMax    = bounds.max;
            Vector4 boundsVector = new Vector4(boundsMin.x, boundsMin.y, boundsMax.x, boundsMax.y);

            computeShader.SetVector("Bounds", boundsVector);

            int initKernel = computeShader.FindKernel("Init");

            computeShader.SetInt("Width", maxNumParticles);
            computeShader.SetBuffer(initKernel, "Lifetimes", lifetimesBuffer);
            computeShader.SetBuffer(initKernel, "Dead", deadBuffer);
            computeShader.Dispatch(initKernel, Groups(maxNumParticles), 1, 1);

            hash = new GridHash(bounds, maxNumParticles, 1.1283791671f);
            computeShader.SetFloat("HashScale", hash.InvCellSize);
            computeShader.SetVector("HashSize", hash.Bounds.size);
            computeShader.SetVector("HashTranslate", hash.Bounds.min);
        }