// 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)); }
// SORT. private static void Sort() { Debug.Assert(sTotalParticleCount <= sMergedParticleCount); Debug.Assert(Mathf.IsPowerOfTwo(sMergedParticleCount)); // DISPATCH SORT BUFFER. for (int k = 2; k <= sMergedParticleCount; k <<= 1) // Major steps. { for (int j = k >> 1; j > 0; j = j >> 1) // Minor steps. { // SWAP AND BIND BUFFERS. sSortElementSwapBuffer.Swap(); sComputeShader.SetBuffer(sKernelSort, "gSortElementBufferIN", sSortElementSwapBuffer.GetInputBuffer()); sComputeShader.SetBuffer(sKernelSort, "gSortElementBufferOUT", sSortElementSwapBuffer.GetOutputBuffer()); sComputeShader.SetInt("gK", k); sComputeShader.SetInt("gJ", j); sComputeShader.SetInt("gMaxParticleCount", sMergedParticleCount); // DISPATCH. sComputeShader.Dispatch(sKernelSort, (int)Mathf.Ceil(sMergedParticleCount / 64.0f), 1, 1); } } }
// UPDATE. private void UpdateSystem() { // SWAP INPUT/OUTPUT. mPositionBuffer.Swap(); mVelocityBuffer.Swap(); mLifetimeBuffer.Swap(); // BIND INPUT BUFFERS. sComputeShader.SetBuffer(sKernelUpdate, "gPositionIN", mPositionBuffer.GetInputBuffer()); sComputeShader.SetBuffer(sKernelUpdate, "gVelocityIN", mVelocityBuffer.GetInputBuffer()); sComputeShader.SetBuffer(sKernelUpdate, "gLifetimeIN", mLifetimeBuffer.GetInputBuffer()); // BIND OUTPUT BUFFERS. sComputeShader.SetBuffer(sKernelUpdate, "gPositionOUT", mPositionBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelUpdate, "gVelocityOUT", mVelocityBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelUpdate, "gLifetimeOUT", mLifetimeBuffer.GetOutputBuffer()); sComputeShader.SetBuffer(sKernelUpdate, "gColorOUT", mColorBuffer); sComputeShader.SetBuffer(sKernelUpdate, "gHaloOUT", mHaloBuffer); sComputeShader.SetBuffer(sKernelUpdate, "gScaleOUT", mScaleBuffer); sComputeShader.SetBuffer(sKernelUpdate, "gTransparencyOUT", mTransperancyBuffer); // BIND VALUE OF LIFETIME BUFFERS. sComputeShader.SetInt("gColorLifetimeCount", mDescriptor.ColorOverLifetime.Length()); sComputeShader.SetBuffer(sKernelUpdate, "gColorLifetimeBuffer", mColorLifetimePointsBuffer); sComputeShader.SetInt("gHaloLifetimeCount", mDescriptor.HaloOverLifetime.Length()); sComputeShader.SetBuffer(sKernelUpdate, "gHaloLifetimeBuffer", mHaloLifetimePointsBuffer); sComputeShader.SetInt("gScaleLifetimeCount", mDescriptor.ScaleOverLifetime.Length()); sComputeShader.SetBuffer(sKernelUpdate, "gScaleLifetimeBuffer", mScaleLifetimePointsBuffer); sComputeShader.SetInt("gTransparencyLifetimeCount", mDescriptor.OpacityOverLifetime.Length()); sComputeShader.SetBuffer(sKernelUpdate, "gTransparencyLifetimeBuffer", mTransparencyLifetimePointsBuffer); // SET META DATA. sComputeShader.SetInt("gMaxParticleCount", mMaxParticleCount); sComputeShader.SetFloat("gDeltaTime", Time.deltaTime); sComputeShader.SetFloats("gConstantAcceleration", new float[] { mDescriptor.ConstantAcceleration.x, mDescriptor.ConstantAcceleration.y, mDescriptor.ConstantAcceleration.z }); sComputeShader.SetFloat("gConstantDrag", mDescriptor.ConstantDrag); // ACCELERATOR. Dictionary <GPUParticleAttractor, GPUParticleAttractor> attractorDictionary = GPUParticleAttractor.GetGPUParticleAttractorDictionary(); if (attractorDictionary == null) { sComputeShader.SetInt("gAttractorCount", 0); } else { Debug.Assert(attractorDictionary.Count < sMaxAttractorCount); float[] attractorArray = new float[attractorDictionary.Count * 8]; int i = 0; int count = 0; foreach (KeyValuePair <GPUParticleAttractor, GPUParticleAttractor> it in attractorDictionary) { GPUParticleAttractor attractor = it.Value; //Skip if inactive. if (!attractor.gameObject.activeInHierarchy) { continue; } float scale = Mathf.Max(Mathf.Max(attractor.transform.localScale.x, attractor.transform.localScale.y), attractor.transform.localScale.z); attractorArray[i++] = attractor.transform.position.x; attractorArray[i++] = attractor.transform.position.y; attractorArray[i++] = attractor.transform.position.z; attractorArray[i++] = attractor.Power; attractorArray[i++] = scale * attractor.Min; attractorArray[i++] = scale * attractor.Max; attractorArray[i++] = 0.0f; //Padding attractorArray[i++] = 0.0f; //Padding count++; } sGPUParticleAttractorBuffer.SetData(attractorArray); sComputeShader.SetInt("gAttractorCount", count); sComputeShader.SetBuffer(sKernelUpdate, "gAttractorBuffer", sGPUParticleAttractorBuffer); } // Vector Fields. Dictionary <GPUParticleVectorField, GPUParticleVectorField> vectorFieldDictionary = GPUParticleVectorField.GetGPUParticleAttractorDictionary(); if (vectorFieldDictionary == null) { sComputeShader.SetInt("gVectorFieldCount", 0); } else { Debug.Assert(vectorFieldDictionary.Count < sMaxVectorFieldCount); float[] vectorFieldArray = new float[vectorFieldDictionary.Count * 8]; int i = 0; int count = 0; foreach (KeyValuePair <GPUParticleVectorField, GPUParticleVectorField> it in vectorFieldDictionary) { GPUParticleVectorField vectorField = it.Value; //Skip if inactive. if (!vectorField.gameObject.activeInHierarchy) { continue; } float scale = Mathf.Max(Mathf.Max(vectorField.transform.localScale.x, vectorField.transform.localScale.y), vectorField.transform.localScale.z); Vector3 vector = vectorField.RelativeVectorField ? vectorField.VectorRelative : vectorField.Vector; vectorFieldArray[i++] = vectorField.transform.position.x; vectorFieldArray[i++] = vectorField.transform.position.y; vectorFieldArray[i++] = vectorField.transform.position.z; vectorFieldArray[i++] = vector.x; vectorFieldArray[i++] = vector.y; vectorFieldArray[i++] = vector.z; vectorFieldArray[i++] = scale * vectorField.Min; vectorFieldArray[i++] = scale * vectorField.Max; count++; } sGPUParticleVectorFieldBuffer.SetData(vectorFieldArray); sComputeShader.SetInt("gVectorFieldCount", count); sComputeShader.SetBuffer(sKernelUpdate, "gVectorFieldBuffer", sGPUParticleVectorFieldBuffer); } // SPHERE COLLIDER. List <GPUParticleSphereCollider> sphereColliderList = GPUParticleSphereCollider.GetGPUParticleSphereColliderList(); if (sphereColliderList == null) { sComputeShader.SetInt("gSphereColliderCount", 0); } else { Debug.Assert(sphereColliderList.Count < sMaxSphereColliderCount); // Reset result buffer. int[] resetArray = new int[sphereColliderList.Count]; for (int i = 0; i < sphereColliderList.Count; ++i) { resetArray[i] = 0; } mSphereColliderResultBuffer.SetData(resetArray); // Update sphere collider buffer. float[] sphereColliderArray = new float[sphereColliderList.Count * 4]; int count = 0; for (int i = 0, j = 0; i < sphereColliderList.Count; ++i) { GPUParticleSphereCollider sphereCollider = sphereColliderList[i]; //Skip if inactive. if (!sphereCollider.gameObject.activeInHierarchy) { continue; } float scale = Mathf.Max(Mathf.Max(sphereCollider.transform.localScale.x, sphereCollider.transform.localScale.y), sphereCollider.transform.localScale.z); sphereColliderArray[j++] = sphereCollider.transform.position.x; sphereColliderArray[j++] = sphereCollider.transform.position.y; sphereColliderArray[j++] = sphereCollider.transform.position.z; sphereColliderArray[j++] = scale * sphereCollider.Radius; count++; } sGPUParticleSphereColliderBuffer.SetData(sphereColliderArray); sComputeShader.SetInt("gSphereColliderCount", count); sComputeShader.SetBuffer(sKernelUpdate, "gSphereColliderBuffer", sGPUParticleSphereColliderBuffer); sComputeShader.SetBuffer(sKernelUpdate, "gSphereColliderResultBufferWRITE", mSphereColliderResultBuffer); } // DISPATCH. sComputeShader.Dispatch(sKernelUpdate, (int)Mathf.Ceil(mMaxParticleCount / 64.0f), 1, 1); }
/// <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); }