Beispiel #1
0
        internal static int Gather(MyGPUEmitterData[] data, out SharpDX.Direct3D11.ShaderResourceView textureArraySRV)
        {
            MyRenderStats.Generic.WriteFormat("GPU particles allocated: {0}", m_totalParticles, VRage.Stats.MyStatTypeEnum.CurrentValue, 300, 0);
            MyRenderStats.Generic.WriteFormat("GPU particles overload: {0}", m_overloaded ? 1.0f : 0, VRage.Stats.MyStatTypeEnum.CurrentValue, 300, 0);

            for (int i = 0; i < MAX_LIVE_EMITTERS; i++)
            {
                data[i].NumParticlesToEmitThisFrame = 0;
            }
            int  maxEmitterIndex = -1;
            uint textureIndex    = 0;

            foreach (var id in m_idIndex.Values)
            {
                if (MyCommon.TimerMs > m_emitters.Data[id.Index].DieAt)
                {
                    m_emitters.Data[id.Index].GPUEmitter.Data.Flags |= GPUEmitterFlags.Dead;
                }

                float toEmit = MyCommon.LastFrameDelta() * m_emitters.Data[id.Index].GPUEmitter.ParticlesPerSecond +
                               m_emitters.Data[id.Index].ParticlesEmittedFraction;
                m_emitters.Data[id.Index].GPUEmitter.Data.NumParticlesToEmitThisFrame = (int)toEmit;
                m_emitters.Data[id.Index].ParticlesEmittedFraction = toEmit - m_emitters.Data[id.Index].GPUEmitter.Data.NumParticlesToEmitThisFrame;

                if (m_emitters.Data[id.Index].TextureId != Resources.TexId.NULL)
                {
                    MyRenderProxy.Assert(m_textureArrayIndices.ContainsKey(m_emitters.Data[id.Index].TextureId));
                    textureIndex = m_textureArrayIndices[m_emitters.Data[id.Index].TextureId].Index;
                }
                else
                {
                    textureIndex = 0;
                }

                int bufferIndex = m_emitters.Data[id.Index].BufferIndex;
                data[bufferIndex]                = m_emitters.Data[id.Index].GPUEmitter.Data;
                data[bufferIndex].Position       = m_emitters.Data[id.Index].GPUEmitter.WorldPosition - MyEnvironment.CameraPosition;
                data[bufferIndex].TextureIndex1 |= textureIndex << (ATLAS_INDEX_BITS + ATLAS_DIMENSION_BITS * 2);

                if (bufferIndex > maxEmitterIndex)
                {
                    maxEmitterIndex = bufferIndex;
                }
            }

            UpdateTextureArray();
            if (m_textureArray != null)
            {
                textureArraySRV = m_textureArray.SRV;
            }
            else
            {
                textureArraySRV = null;
            }

            foreach (var id in m_idIndex.Values.ToArray())
            {
                if ((m_emitters.Data[id.Index].GPUEmitter.Data.Flags & GPUEmitterFlags.Dead) > 0)
                {
                    m_totalParticles -= m_emitters.Data[id.Index].GPUEmitter.MaxParticles();
                    Remove(id);
                }
            }
            return(maxEmitterIndex + 1);
        }
Beispiel #2
0
        internal static int Gather(MyGPUEmitterData[] data, out ISrvBindable textureArraySrv)
        {
            for (int i = 0; i < MAX_LIVE_EMITTERS; i++)
            {
                data[i].NumParticlesToEmitThisFrame = 0;
            }

            // sort emitters!
            List <MyLiveData> emitters = m_emitters.Values.ToList();

            //if (emitters.Count > MAX_LIVE_EMITTERS)
            emitters.Sort();

            int  maxEmitterIndex        = -1;
            uint textureIndex           = 0;
            int  unassociatedCount      = 0;
            int  skipCount              = 0;
            int  unsortedCount          = 0;
            int  firstUnassociatedIndex = -1;
            int  lastAssociatedIndex    = -1;

            for (int i = 0; i < emitters.Count; i++)
            {
                var emitter = emitters[i];
                // assiociate buffer index to new emitters & track overload to free space for unassociated near emitters later
                if (emitter.BufferIndex == -1)
                {
                    if (m_freeBufferIndices.Count > 0)
                    {
                        emitter.BufferIndex = m_freeBufferIndices.Pop();
                    }
                    else
                    {
                        unassociatedCount++;
                        if (firstUnassociatedIndex == -1)
                        {
                            firstUnassociatedIndex = i;
                        }
                    }
                }
                else
                {
                    skipCount           = unassociatedCount;
                    lastAssociatedIndex = i;
                    if (unassociatedCount > 0)
                    {
                        unsortedCount++;
                    }
                }

                if (MyCommon.TimerMs > emitter.DieAt)
                {
                    emitter.GPUEmitter.Data.Flags |= GPUEmitterFlags.Dead;
                }

                if (emitter.BufferIndex != -1)
                {
                    if ((emitter.GPUEmitter.Data.Flags & GPUEmitterFlags.FreezeEmit) == 0)
                    {
                        float toEmit = MyCommon.LastFrameDelta() * emitter.GPUEmitter.ParticlesPerSecond +
                                       emitter.ParticlesEmittedFraction;
                        emitter.GPUEmitter.Data.NumParticlesToEmitThisFrame = (int)toEmit;
                        emitter.ParticlesEmittedFraction = toEmit - emitter.GPUEmitter.Data.NumParticlesToEmitThisFrame;
                    }

                    if (string.IsNullOrEmpty(emitter.GPUEmitter.AtlasTexture))
                    {
                        MyRenderProxy.Assert(m_textureArrayIndices.ContainsKey(emitter.GPUEmitter.AtlasTexture));
                        textureIndex = m_textureArrayIndices[emitter.GPUEmitter.AtlasTexture].Index;
                    }
                    else
                    {
                        textureIndex = 0;
                    }

                    int bufferIndex = emitter.BufferIndex;
                    data[bufferIndex] = emitter.GPUEmitter.Data;
                    Vector3 pos = emitter.GPUEmitter.WorldPosition - MyRender11.Environment.Matrices.CameraPosition;
                    data[bufferIndex].RotationMatrix.M14 = pos.X;
                    data[bufferIndex].RotationMatrix.M24 = pos.Y;
                    data[bufferIndex].RotationMatrix.M34 = pos.Z;
                    data[bufferIndex].PositionDelta      = emitter.LastWorldPosition - emitter.GPUEmitter.WorldPosition;
                    data[bufferIndex].TextureIndex1     |= textureIndex << (ATLAS_INDEX_BITS + ATLAS_DIMENSION_BITS * 2);

                    if (bufferIndex > maxEmitterIndex)
                    {
                        maxEmitterIndex = bufferIndex;
                    }
                }
                emitter.LastWorldPosition = emitter.GPUEmitter.WorldPosition;
            }

            /*MyRenderStats.Generic.WriteFormat("GPU particles allocated: {0}", totalParticles, VRage.Stats.MyStatTypeEnum.CurrentValue, 300, 0);
             * MyRenderStats.Generic.WriteFormat("GPU particles overload: {0}", overloadedParticles ? 1.0f : 0, VRage.Stats.MyStatTypeEnum.CurrentValue, 300, 0);
             * MyRenderStats.Generic.WriteFormat("GPU emitters overload: {0}", overloadedEmitters ? 1.0f : 0, VRage.Stats.MyStatTypeEnum.CurrentValue, 300, 0);*/

            UpdateTextureArray();
            textureArraySrv = m_textureArray;

            // stop emitters far away to make room for emitters nearby
            if (skipCount > 0 && unsortedCount > 0)
            {
                // iterate until buffer-unassociated index is larger then unassocited one
                for (int i = firstUnassociatedIndex, j = lastAssociatedIndex; i < j;)
                {
                    var emitter = emitters[j];
                    // free last buffer-associated emitter
                    data[emitter.BufferIndex].Flags |= GPUEmitterFlags.Dead;
                    data[emitter.BufferIndex].NumParticlesToEmitThisFrame = 0;
                    m_freeBufferIndices.Push(emitter.BufferIndex);
                    emitter.BufferIndex = -1;

                    // find new last buffer-associated emitter
                    do
                    {
                        j--;
                    }while (j > 0 && emitters[j].BufferIndex == -1);

                    // find next buffer-unassociated emitter
                    do
                    {
                        i++;
                    } while (i < emitters.Count && emitters[i].BufferIndex != -1);
                }
            }

            foreach (var emitter in emitters)
            {
                if ((emitter.GPUEmitter.Data.Flags & GPUEmitterFlags.Dead) > 0)
                {
                    Remove(emitter);
                }
            }

            return(maxEmitterIndex + 1);
        }