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); }
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); }