Esempio n. 1
0
    // 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));
    }
Esempio n. 2
0
    // 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);
            }
        }
    }
Esempio n. 3
0
    // 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);
    }
Esempio n. 4
0
    /// <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);
    }