Пример #1
0
        //prepare to perform the particle logic
        void IParticleProcessor.BeginDrawPass(int pass, float deltaTime, int step)
        {
            float maxTimeStep = ((float)this.maxParticleTimeStep) * this.systemStepDeltaTime;
            float time        = ((float)(step & (this.maxParticleTimeStep - 1))) * this.systemStepDeltaTime;

            deltaTime = systemStepDeltaTime;

            activeRenderPass  = this.renderPasses[pass];
            frameBufferToggle = !frameBufferToggle;

            if (activeRenderPass == null)
            {
                return;                 // this can happen when a particle system is disposed
            }
            if (this.processorData.FrameShader != null)
            {
                (this.processorData.FrameShader as GpuParticleShader).SetConstants(activeRenderPass.globals, deltaTime, time, maxTimeStep);
            }
            if (this.processorData.FrameMoveShader != null)
            {
                (this.processorData.FrameMoveShader as GpuParticleShader).SetConstants(activeRenderPass.globals, deltaTime, time, maxTimeStep);
            }
            if (this.processorData.OnceShader != null)
            {
                (this.processorData.OnceShader as GpuParticleShader).SetConstants(activeRenderPass.globals, deltaTime, time, maxTimeStep);
            }
            if (this.processorData.OnceCloneShader != null)
            {
                (this.processorData.OnceCloneShader as GpuParticleShader).SetConstants(activeRenderPass.globals, deltaTime, time, maxTimeStep);
            }
        }
Пример #2
0
        /// <summary></summary>
        public void Dispose()
        {
            DisposeMember(ref positionSizeBufferA);
            DisposeMember(ref velocityRotationBufferA);
            DisposeMember(ref userBufferA);
            DisposeMember(ref colourBufferA);

            DisposeMember(ref positionSizeBufferB);
            DisposeMember(ref velocityRotationBufferB);
            DisposeMember(ref userBufferB);
            DisposeMember(ref colourBufferB);

            DisposeMember(ref lifeStoreBufferA);
            DisposeMember(ref lifeStoreBufferB);

            DisposeMember(ref mrtGroupA);
            DisposeMember(ref mrtGroupB);

            lifeStepParticleData = null;
            allProcessors        = null;
            activeRenderPass     = null;
            verticesRenderIndex  = null;
            scissorTest          = null;
            backgroundFillPass   = null;
            randomTexture        = null;

            shaderRandomValues = null;
        }
Пример #3
0
        void IParticleProcessor.Update(int particleCount, float particleCountF, float delatTime, float[] globals, CopyAction[] copyActions, int copyActionCount, AddAction[] addActions, int addActionCount, int step)
        {
            //update may be called multiple times for a single frame
            //so store the update data in GpuParticleRenderPass instances

            //instances are reused

            //get a free pass to copy in action data
            if (renderPassCount == renderPasses.Length)
            {
                Array.Resize(ref renderPasses, renderPasses.Length * 2);
            }

            GpuParticleRenderPass pass = renderPasses[renderPassCount];

            if (pass == null)
            {
                //allocate a pass
                pass = new GpuParticleRenderPass(this.allProcessors);
                renderPasses[renderPassCount] = pass;
            }

            //copy in the action data...
            pass.ParticleCount  = particleCount;
            pass.ParticleCountF = particleCountF;

            for (int i = 0; i < globals.Length; i++)
            {
                pass.globals[i] = globals[i];
            }

            if (copyActionCount > 0)
            {
                //allocate
                int count = 2;
                while (copyActionCount > count)
                {
                    count *= 2;                     // keep allocations as powers of two
                }
                if (pass.CopyData == null ||
                    pass.CopyData.Length < copyActionCount)
                {
                    Array.Resize(ref pass.CopyData, count);
                }

                //reset the count
                pass.CopyCount = copyActionCount;

                //write the data
                int i = 0;
                while (i != copyActionCount)
                {
                    pass.CopyData[i].X = copyActions[i].indexToF;
                    pass.CopyData[i].Y = copyActions[i].indexFromF;

                    i++;
                    //ZW store the life / age data
                }
            }


            if (addActionCount > 0)
            {
                //count the number of actions for each type
                for (int i = 0; i < addActionCount; i++)
                {
                    pass.AddLists[addActions[i].cloneTypeIndex + 1].AddCount++;
                }

                //allocate the storage for each action by type
                for (int i = 0; i < pass.AddLists.Length; i++)
                {
                    int listCount = pass.AddLists[i].AddCount;
                    pass.AddLists[i].AddCount = 0;

                    if (listCount == 0)
                    {
                        continue;
                    }

                    Vector4[] list = pass.AddLists[i].AddData;

                    if (list != null &&
                        list.Length >= listCount)
                    {
                        continue;
                    }

                    int count = 4;
                    while (listCount > count)
                    {
                        count *= 2;                         // keep allocations as powers of two
                    }
                    if (list == null || list.Length < listCount)
                    {
                        Array.Resize(ref pass.AddLists[i].AddData, count);

                        if (pass.AddLists[i].processor == null)
                        {
                            //this processor also sets positions
                            Array.Resize(ref pass.AddLists[i].AddDetails, count);
                        }
                    }
                }

                //fill up the data
                for (int i = 0; i < addActionCount; i++)
                {
                    ProcessorAddList list = pass.AddLists[addActions[i].cloneTypeIndex + 1];
                    int index             = list.AddCount;

                    list.AddData[index].X = addActions[i].indexF;

                    //when cloneFromIndex is -1, cloneFromIndexF stores the starting x coord
                    list.AddData[index].Y = addActions[i].cloneFromIndexF;

                    //ZW store the life / age data (set in next block, if needed)

                    if (addActions[i].cloneFromIndex == -1)
                    {
                        //store the position of the particle (it's not being cloned)
                        list.AddDetails[index] = addActions[i].spawnDetails;
                    }

                    list.AddCount++;
                }
            }
            //done...

            //except...

            //copy in the data to the 'Life storage' list.
            //this is a separate texture that stores life and age of each particle
            //this is rather inefficient unfortunately

            if (usesLifeStorage && (copyActionCount > 0 || addActionCount > 0))
            {
                //unfortunately, there is a lot of int-to-float conversion here

                //stored step is wrapped to help precision
                float startStep = ((float)(step & (this.maxParticleTimeStep - 1))) * this.systemStepDeltaTime;

                //allocate
                int count = 2;
                while (copyActionCount + addActionCount > count)
                {
                    count *= 2;                     // keep allocations as powers of two
                }
                if (pass.LifeData == null ||
                    pass.LifeData.Length < copyActionCount + addActionCount)
                {
                    Array.Resize(ref pass.LifeData, count);
                }

                count = 2;
                while (pass.ParticleCount > count)
                {
                    count *= 2;
                }
                if (lifeStepParticleData == null ||
                    lifeStepParticleData.Length < pass.ParticleCount)
                {
                    Array.Resize(ref lifeStepParticleData, count);
                }

                count = 0;
                Vector3[] data  = pass.LifeData;
                Vector3   v     = new Vector3();
                Vector2   store = new Vector2();

                for (int i = 0; i < pass.AddLists.Length; i++)
                {
                    pass.AddLists[i].AddCount = 0;
                }


                //move a particle
                for (int i = 0; i < copyActionCount; i++)
                {
                    v.X = copyActions[i].indexToF;

                    //get it's life data
                    store = lifeStepParticleData[copyActions[i].indexFrom];
                    //store in case it moves again
                    lifeStepParticleData[copyActions[i].indexTo] = store;

                    v.Y = store.X;
                    v.Z = store.Y;
#if DEBUG
                    if (v.Y == 0 &&
                        v.Z == 0)
                    {
                        throw new ArgumentException();
                    }
#endif

                    //a copy will read the life / age from the texture

                    //update the CopyData data too
                    //as the ZW values need to store this data
                    pass.CopyData[count].Z = store.X;
                    pass.CopyData[count].W = store.Y;

                    data[count++] = v;
                }

                //data is stored as 'index, age, start time'
                for (int i = 0; i < addActionCount; i++)
                {
                    v.X = addActions[i].indexF;
                    v.Y = ((float)addActions[i].lifeSteps) * this.systemStepDeltaTime;
                    v.Z = startStep;

                    //update the AddList data too
                    //as the ZW values need to store this data

                    ProcessorAddList list = pass.AddLists[addActions[i].cloneTypeIndex + 1];

                    list.AddData[list.AddCount].Z = v.Y;
                    list.AddData[list.AddCount].W = v.Z;
                    list.AddCount++;



                    store.X = v.Y;
                    store.Y = v.Z;

                    //need to store this data for particles that are moved (see above)
                    lifeStepParticleData[addActions[i].index] = store;

                    data[count++] = v;
                }

                pass.LifeCount = count;
            }

            renderPassCount++;
        }