public void UpdateTreeMPB()
        {
            if (treeProxyList != null && treeProxyList.Count > 0)
            {
                GPUInstancerPrototypeLOD rdLOD;
                GPUInstancerRenderer     rdRenderer;
                MeshRenderer             meshRenderer;
                Transform proxyTransform;
                foreach (GPUInstancerRuntimeData runtimeData in runtimeDataList)
                {
                    // Do not set append buffers if there is no instance of this tree prototype on the terrain
                    if (runtimeData.bufferSize == 0)
                    {
                        continue;
                    }

                    if (runtimeData.prototype.treeType != GPUInstancerTreeType.SpeedTree && runtimeData.prototype.treeType != GPUInstancerTreeType.SpeedTree8)
                    {
                        continue;
                    }

                    proxyTransform = treeProxyList[runtimeData.prototype.prefabObject];

                    if (!proxyTransform)
                    {
                        continue;
                    }

                    for (int lod = 0; lod < runtimeData.instanceLODs.Count; lod++)
                    {
                        if (proxyTransform.childCount <= lod)
                        {
                            continue;
                        }

                        rdLOD        = runtimeData.instanceLODs[lod];
                        meshRenderer = proxyTransform.GetChild(lod).GetComponent <MeshRenderer>();

                        for (int r = 0; r < rdLOD.renderers.Count; r++)
                        {
                            rdRenderer = rdLOD.renderers[r];
                            //if (treeType == GPUInstancerTreeType.SoftOcclusionTree)
                            //{
                            //    // Soft occlusion shader wind parameters here.
                            //    // rdRenderer.mpb.SetFloat("_ShakeDisplacement", 0.8f);
                            //    continue;
                            //}

                            meshRenderer.GetPropertyBlock(rdRenderer.mpb);
                            if (rdRenderer.shadowMPB != null)
                            {
                                meshRenderer.GetPropertyBlock(rdRenderer.shadowMPB);
                            }
                        }
                    }

                    GPUInstancerUtility.SetAppendBuffers(runtimeData);
                }
            }
        }
        /// <summary>
        /// Can be used to change the material of a prototype at runtime
        /// </summary>
        /// <param name="manager">GPUI Manager</param>
        /// <param name="prototype">GPUI Prototype</param>
        /// <param name="material">New material to set on the renderer</param>
        /// <param name="lodLevel">LOD level</param>
        /// <param name="rendererIndex">Renderer index on the LOD level</param>
        /// <param name="subMeshIndex">Submesh index of the renderer</param>
        public static void ChangeMaterial(GPUInstancerManager manager, GPUInstancerPrototype prototype, Material material, int lodLevel = 0, int rendererIndex = 0, int subMeshIndex = 0)
        {
            GPUInstancerRuntimeData runtimeData = manager.GetRuntimeData(prototype, true);

            if (runtimeData == null)
            {
                return;
            }
            GPUInstancerRenderer gpuiRenderer = runtimeData.instanceLODs[lodLevel].renderers[rendererIndex];

            // Generate proxy GO with a Mesh Renderer to get material property blocks
            GameObject   proxyGameObject = new GameObject("ProxyGO");
            MeshFilter   meshFilter      = proxyGameObject.AddComponent <MeshFilter>();
            MeshRenderer proxyRenderer   = proxyGameObject.AddComponent <MeshRenderer>();

            // Set mesh to proxy GO
            meshFilter.mesh = gpuiRenderer.mesh;
            // Set new material to runtime data
            gpuiRenderer.materials[subMeshIndex] = GPUInstancerConstants.gpuiSettings.shaderBindings.GetInstancedMaterial(material);
            // Set new material to proxy GO
            proxyRenderer.materials[subMeshIndex] = material;
            // Get material property blocks
            proxyRenderer.GetPropertyBlock(gpuiRenderer.mpb);
            if (gpuiRenderer.shadowMPB != null)
            {
                proxyRenderer.GetPropertyBlock(gpuiRenderer.shadowMPB);
            }

            // Destroy proxy GO
            GameObject.Destroy(proxyGameObject);

            // Setup new materials for instancing
            GPUInstancerUtility.SetAppendBuffers(runtimeData);
        }