// INIT. private void InitSystem() { if (mDescriptor == null) { mDescriptor = new GPUParticleDescriptor(); } mDescriptor.Update(); mMaxParticleCount = (int)Mathf.Ceil(mDescriptor.EmittFrequency * mDescriptor.Lifetime); mLastPosition = transform.position; sTotalParticleCount += mMaxParticleCount; // BUFFERS. mPositionBuffer = new SwapBuffer(2, mMaxParticleCount, sizeof(float) * 4); mVelocityBuffer = new SwapBuffer(2, mMaxParticleCount, sizeof(float) * 4); mLifetimeBuffer = new SwapBuffer(2, mMaxParticleCount, sizeof(float) * 4); mColorBuffer = new ComputeBuffer(mMaxParticleCount, sizeof(float) * 4); mHaloBuffer = new ComputeBuffer(mMaxParticleCount, sizeof(float) * 4); mScaleBuffer = new ComputeBuffer(mMaxParticleCount, sizeof(float) * 4); mTransperancyBuffer = new ComputeBuffer(mMaxParticleCount, sizeof(float) * 4); { // Set lifetime default (negative)value. float[] arr = new float[mMaxParticleCount * 4]; for (int i = 0; i < mMaxParticleCount * 4; ++i) { arr[i] = -0.01f; } mLifetimeBuffer.GetInputBuffer().SetData(arr); mLifetimeBuffer.GetOutputBuffer().SetData(arr); } // MESH. UpdateMesh(); //LIFETIME POINT BUFFERS // ------- Color ------ UpdateLifetimeBuffer(out mColorLifetimePointsBuffer, mDescriptor.ColorOverLifetime.Get()); // ------- Halo ------- UpdateLifetimeBuffer(out mHaloLifetimePointsBuffer, mDescriptor.HaloOverLifetime.Get()); // ------ Scale ------- UpdateLifetimeBuffer(out mScaleLifetimePointsBuffer, mDescriptor.ScaleOverLifetime.Get()); // ------ Opacity ----- UpdateLifetimeBuffer(out mTransparencyLifetimePointsBuffer, mDescriptor.OpacityOverLifetime.Get()); // COLLISION. mSphereColliderResultBuffer = new ComputeBuffer(sMaxSphereColliderCount, sizeof(int)); }
// MERGE. private static void Merge() { if (sMergedParticleCount < sTotalParticleCount) { sMergedParticleCount = Mathf.NextPowerOfTwo(sTotalParticleCount); // Resize buffers. sMergedPositionBuffer.Resize(sMergedParticleCount); sMergedVelocityBuffer.Resize(sMergedParticleCount); sMergedLifetimeBuffer.Resize(sMergedParticleCount); sMergedColorBuffer.Resize(sMergedParticleCount); sMergedHaloBuffer.Resize(sMergedParticleCount); sMergedScaleBuffer.Resize(sMergedParticleCount); sMergedTransperancyBuffer.Resize(sMergedParticleCount); sSortElementSwapBuffer.Resize(sMergedParticleCount); } // CLEAR OLD VALUES. // TODO: Might not need to reset all this data!! float[] mergedData = new float[sMergedParticleCount * 4]; for (int i = 0; i < mergedData.GetLength(0); ++i) { mergedData[i] = -100.0f; } sMergedLifetimeBuffer.GetInputBuffer().SetData(mergedData); sMergedLifetimeBuffer.GetOutputBuffer().SetData(mergedData); for (int i = 0; i < mergedData.GetLength(0); ++i) { mergedData[i] = float.MaxValue; } sMergedPositionBuffer.GetInputBuffer().SetData(mergedData); sMergedPositionBuffer.GetOutputBuffer().SetData(mergedData); // SET BUFFERS. sComputeShader.SetBuffer(sKernelMergeInitSort, "mergePositionOUT", sMergedPositionBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelMergeInitSort, "mergeVelocityOUT", sMergedVelocityBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelMergeInitSort, "mergeLifetimeOUT", sMergedLifetimeBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelMergeInitSort, "mergeColorOUT", sMergedColorBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelMergeInitSort, "mergeHaloOUT", sMergedHaloBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelMergeInitSort, "mergeScaleOUT", sMergedScaleBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelMergeInitSort, "mergeTransperancyOUT", sMergedTransperancyBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelMergeInitSort, "gSortElementBufferOUT", sSortElementSwapBuffer.GetOutputBuffer()); Vector3 cForward = Camera.main.transform.forward; sComputeShader.SetFloats("gCameraForward", new float[] { cForward.x, cForward.y, cForward.z }); int offset = 0; foreach (KeyValuePair <GPUParticleSystem, GPUParticleSystem> it in sGPUParticleSystemDictionary) { GPUParticleSystem system = it.Value; if (!system.gameObject.activeInHierarchy) { continue; } sComputeShader.SetInt("gLocalParticleCount", system.mMaxParticleCount); sComputeShader.SetInt("gOffsetIndex", offset); sComputeShader.SetBuffer(sKernelMergeInitSort, "gLocalSystemPositionIN", system.mPositionBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelMergeInitSort, "gLocalSystemVelocityIN", system.mVelocityBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelMergeInitSort, "gLocalSystemLifetimeIN", system.mLifetimeBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelMergeInitSort, "gLocalSystemColorIN", system.mColorBuffer); sComputeShader.SetBuffer(sKernelMergeInitSort, "gLocalSystemHaloIN", system.mHaloBuffer); sComputeShader.SetBuffer(sKernelMergeInitSort, "gLocalSystemScaleIN", system.mScaleBuffer); sComputeShader.SetBuffer(sKernelMergeInitSort, "gLocalSystemTransperancyIN", system.mTransperancyBuffer); sComputeShader.Dispatch(sKernelMergeInitSort, (int)Mathf.Ceil(system.mMaxParticleCount / 64.0f), 1, 1); offset += system.mMaxParticleCount; } }
// EMITT UPDATE. private void EmittUpdate() { // Update timer. mEmittTimer += Time.deltaTime; int emittCount = (int)(mDescriptor.EmittFrequency * mEmittTimer); if (emittCount == 0) { return; } mEmittTimer -= emittCount * 1.0f / mDescriptor.EmittFrequency; Vector3 emitterVelocity = transform.position - mLastPosition; int particlesToEmitt = emittCount; int batchCount = (int)Mathf.Ceil(emittCount / 64.0f); for (int batchID = 0; batchID < batchCount; ++batchID) { int emittCountThisBatch = particlesToEmitt > 64 ? 64 : particlesToEmitt; //Debug.Log(emittCountThisBatch); particlesToEmitt -= 64; sComputeShader.SetInt("gEmittCountThisBatch", emittCountThisBatch); // BIND PARTICLE BUFFERS. sComputeShader.SetBuffer(sKernelEmitt, "gPositionBuffer", mPositionBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelEmitt, "gVelocityBuffer", mVelocityBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelEmitt, "gLifetimeBuffer", mLifetimeBuffer.GetOutputBuffer()); // Inherit velocity from emitter if true. Vector3 velocity = (emitterVelocity / Time.deltaTime) * (mDescriptor.InheritVelocity ? 1 : 0) + mDescriptor.InitialVelocity; // EMITT INFO. sComputeShader.SetInt("gEmittStartIndex", mEmittIndex); sComputeShader.SetInt("gEmittMaxCount", mMaxParticleCount); sComputeShader.SetFloats("gPosition", new float[] { transform.position.x, transform.position.y, transform.position.z }); sComputeShader.SetFloats("gVelocity", new float[] { velocity.x, velocity.y, velocity.z }); sComputeShader.SetFloats("gLifetime", new float[] { mDescriptor.Lifetime }); // EMITT MESH. if (mDescriptor.EmittMesh == null) { // Set count to 0. sComputeShader.SetInt("gEmittMeshVertexCount", 0); sComputeShader.SetInt("gEmittMeshIndexCount", 0); sComputeShader.SetInt("gEmittMeshRandomIndex", 0); } else { Debug.Assert(sEmittMeshInfoDictionary.ContainsKey(mDescriptor.EmittMesh)); EmittMeshInfo emittMeshInfo = sEmittMeshInfoDictionary[mDescriptor.EmittMesh]; // Set index and vertex buffer. sComputeShader.SetBuffer(sKernelEmitt, "gEmittMeshVertexBuffer", emittMeshInfo.mVertexBuffer); sComputeShader.SetBuffer(sKernelEmitt, "gEmittMeshIndexBuffer", emittMeshInfo.mIndexBuffer); sComputeShader.SetInt("gEmittMeshVertexCount", emittMeshInfo.mVertexCount); sComputeShader.SetInt("gEmittMeshIndexCount", emittMeshInfo.mIndexCount); int[] randomIndexArray = new int[64]; for (int j = 0; j < randomIndexArray.GetLength(0); ++j) { randomIndexArray[j] = Random.Range(0, emittMeshInfo.mIndexCount - 1); } sRandomIndexBuffer.SetData(randomIndexArray); sComputeShader.SetBuffer(sKernelEmitt, "gEmittMeshRandomIndexBuffer", sRandomIndexBuffer); sComputeShader.SetFloats("gEmittMeshScale", new float[] { transform.localScale.x, transform.localScale.y, transform.localScale.z }); } // DISPATCH. sComputeShader.Dispatch(sKernelEmitt, 1, 1, 1); // Increment emitt index. mEmittIndex = (mEmittIndex + emittCountThisBatch) % mMaxParticleCount; } }
/// <summary> /// Kills all living particles. /// </summary> public static void KillAllParticles() { Debug.Log("KILLALLPARTILCES1"); if (sGPUParticleSystemDictionary == null) { return; } foreach (KeyValuePair <GPUParticleSystem, GPUParticleSystem> it in sGPUParticleSystemDictionary) { Debug.Log("KILLALLPARTILCES2"); GPUParticleSystem system = it.Value; float[] systemData = new float[system.mMaxParticleCount * 4]; for (int i = 0; i < systemData.GetLength(0); ++i) { systemData[i] = -100.0f; } system.mLifetimeBuffer.GetInputBuffer().SetData(systemData); system.mLifetimeBuffer.GetOutputBuffer().SetData(systemData); for (int i = 0; i < systemData.GetLength(0); ++i) { systemData[i] = float.MaxValue; } system.mPositionBuffer.GetInputBuffer().SetData(systemData); system.mPositionBuffer.GetOutputBuffer().SetData(systemData); int[] r = new int[sMaxGPUColliderCount]; for (int i = 0; i < r.GetLength(0); ++i) { r[i] = 0; } system.mSphereColliderResultBuffer.SetData(r); } // TODO: Might not need to reset all this data!! float[] mergedData = new float[sMergedParticleCount * 4]; for (int i = 0; i < mergedData.GetLength(0); ++i) { mergedData[i] = -100.0f; } sMergedLifetimeBuffer.GetInputBuffer().SetData(mergedData); sMergedLifetimeBuffer.GetOutputBuffer().SetData(mergedData); for (int i = 0; i < mergedData.GetLength(0); ++i) { mergedData[i] = float.MaxValue; } sMergedPositionBuffer.GetInputBuffer().SetData(mergedData); sMergedPositionBuffer.GetOutputBuffer().SetData(mergedData); int[] data = new int[sMaxGPUColliderCount]; for (int i = 0; i < data.GetLength(0); ++i) { data[i] = 0; } sGPUColliderResultSwapBuffer.GetInputBuffer().SetData(data); sGPUColliderResultSwapBuffer.GetOutputBuffer().SetData(data); }