////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        // --- GrassComponent ---
        private void Initialize(Grass grass)
        {
            //Init shaders
            grass.ComputeShader = Instantiate(ComputeShader);

            // Init kernels
            grass.MeshGrassGeneratorKernel = new ComputeKernel(_meshGrassGeneratorKernelName, grass.ComputeShader);
            grass.IndirectGrassKernel      = new ComputeKernel(_indirectGrassKernelName, grass.ComputeShader);
            grass.CullKernal = new ComputeKernel(_cullKernelName, grass.ComputeShader);

            var maxGrassMesh = (int)Mathf.Ceil((grass.SurfaceMesh.bounds.size.x * grass.SurfaceMesh.bounds.size.z) / GrassDensity);

            grass.MaxGrass = maxGrassMesh;

            grass.GrassBuffer = new ComputeBuffer(grass.MaxGrass, sizeof(float) * 4, ComputeBufferType.Append);

            var surfaceVertices = grass.SurfaceMesh.vertices;
            var surfaceIndices  = grass.SurfaceMesh.GetIndices(0);
            var surfaceUVs      = grass.SurfaceMesh.uv;

            grass.SurfaceVertices = new ComputeBuffer(surfaceVertices.Length, sizeof(float) * 3, ComputeBufferType.Default);
            grass.SurfaceIndices  = new ComputeBuffer(surfaceIndices.Length, sizeof(int), ComputeBufferType.Default);
            grass.SurfaceUVs      = new ComputeBuffer(surfaceUVs.Length, sizeof(float) * 2, ComputeBufferType.Default);

            grass.ComputeShader.SetInt(ComputeShaderID.cullCount, grass.MaxGrass);
            grass.ComputeShader.SetInt(ComputeShaderID.indexCount, surfaceIndices.Length);

            // fill surface vertices
            grass.SurfaceVertices.SetData(surfaceVertices);
            grass.MeshGrassGeneratorKernel.SetBuffer(ComputeShaderID.surfaceVertices, grass.SurfaceVertices);
            grass.SurfaceIndices.SetData(surfaceIndices);
            grass.MeshGrassGeneratorKernel.SetBuffer(ComputeShaderID.surfaceIndices, grass.SurfaceIndices);
            grass.SurfaceUVs.SetData(surfaceUVs);
            grass.MeshGrassGeneratorKernel.SetBuffer(ComputeShaderID.surfaceUVs, grass.SurfaceUVs);
        }
        private void SafeRelease(Grass grass)
        {
            grass.GrassBuffer.SafeRelease();

            Destroy(grass.ComputeShader);

            grass.SurfaceVertices.SafeRelease();
            grass.SurfaceIndices.SafeRelease();
            grass.SurfaceUVs.SafeRelease();
        }
        private void UpdateShaderValues(Grass grass)
        {
            grass.ComputeShader.SetInt(ComputeShaderID.terrainResolution, grass.SplatMap.height);
            grass.ComputeShader.SetMatrix(ComputeShaderID.objToWorld, grass.GameObject.transform.localToWorldMatrix);
            grass.ComputeShader.SetFloat(ComputeShaderID.surfaceGridStep, GrassDensity);

            grass.MeshGrassGeneratorKernel.SetTexture(ComputeShaderID.splatMap, grass.SplatMap);
            grass.MeshGrassGeneratorKernel.SetTexture(ComputeShaderID.nodeTexture, grass.NodeTexture);

            grass.CullKernal.SetBuffer(ComputeShaderID.cullOutBuffer, _megaBuffer);
        }
        ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

        public void AddGrass(GameObject go)
        {
            var _mesh    = go.GetComponent <MeshFilter>().mesh;
            var _texture = go.GetComponent <MeshRenderer>().material.mainTexture;

            Grass grass = new Grass
            {
                ID          = Guid.NewGuid(),
                GameObject  = go,
                SurfaceMesh = _mesh,
                SplatMap    = DefaultSplatMap,
                NodeTexture = (Texture2D)_texture
            };

            Initialize(grass);

            //add grass to list
            _drawGrass.Add(grass);
        }
 private void UpdatePlanePos(Grass grass)
 {
     grass.ComputeShader.SetVectorArray(ComputeShaderID.frustumPlanes, _frustumPlanes);
 }