Ejemplo n.º 1
0
        /// <summary>
        /// Can be used to change the mesh of a prototype at runtime
        /// </summary>
        /// <param name="manager">GPUI Manager</param>
        /// <param name="prototype">GPUI Prototype</param>
        /// <param name="mesh">New mesh 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 ChangeMesh(GPUInstancerManager manager, GPUInstancerPrototype prototype, Mesh mesh, 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];

            if (gpuiRenderer.mesh.subMeshCount != mesh.subMeshCount)
            {
                Debug.LogError("ChangeMesh method can not be used with a mesh that has different amount of submeshes than the original mesh.");
                return;
            }

            if (gpuiRenderer.mesh.vertexCount != mesh.vertexCount)
            {
                int argsLastIndex = gpuiRenderer.argsBufferOffset;
                // Setup the indirect renderer buffer:
                for (int j = 0; j < gpuiRenderer.mesh.subMeshCount; j++)
                {
                    runtimeData.args[argsLastIndex++] = gpuiRenderer.mesh.GetIndexCount(j); // index count per instance
                    runtimeData.args[argsLastIndex++] = 0;                                  // (uint)runtimeData.bufferSize;
                    runtimeData.args[argsLastIndex++] = gpuiRenderer.mesh.GetIndexStart(j); // start index location
                    runtimeData.args[argsLastIndex++] = 0;                                  // base vertex location
                    runtimeData.args[argsLastIndex++] = 0;                                  // start instance location
                }
                runtimeData.argsBuffer.SetData(runtimeData.args);
            }

            gpuiRenderer.mesh = mesh;
        }
Ejemplo n.º 2
0
        /// <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);
        }
Ejemplo n.º 3
0
        public GPUInstancerRuntimeData GetRuntimeData(GPUInstancerPrototype prototype, bool logError = false)
        {
            GPUInstancerRuntimeData runtimeData = null;

            if (!runtimeDataDictionary.TryGetValue(prototype, out runtimeData) && logError)
            {
                Debug.LogError("Can not find runtime data for prototype: " + prototype + ". Please check if the prototype was added to the Manager and the initialize method was called.");
            }
            return(runtimeData);
        }
Ejemplo n.º 4
0
        public ComputeBuffer GetTransformDataBuffer(GPUInstancerPrototype prototype)
        {
            GPUInstancerRuntimeData runtimeData = GetRuntimeData(prototype);

            if (runtimeData != null)
            {
                return(runtimeData.transformationMatrixVisibilityBuffer);
            }
            return(null);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Returns the array that stores the transform data of the instances
        /// </summary>
        /// <param name="manager">GPUI Manager</param>
        /// <param name="prototype">GPUI Prototype</param>
        /// <returns>Instance data array</returns>
        public static Matrix4x4[] GetInstanceDataArray(GPUInstancerManager manager, GPUInstancerPrototype prototype)
        {
            GPUInstancerRuntimeData runtimeData = manager.GetRuntimeData(prototype, true);

            if (runtimeData == null)
            {
                return(null);
            }
            return(runtimeData.instanceDataArray);
        }
Ejemplo n.º 6
0
 public ComputeBuffer GetTransformDataBuffer(GPUInstancerPrototype prototype)
 {
     if (runtimeDataList != null && runtimeDataList.Count > 0)
     {
         GPUInstancerRuntimeData runtimeData = runtimeDataList.Find(rd => rd != null && rd.prototype == prototype);
         if (runtimeData != null)
         {
             return(runtimeData.transformationMatrixVisibilityBuffer);
         }
     }
     return(null);
 }
Ejemplo n.º 7
0
        /// <summary>
        /// SetInstanceCount can be used to discard instances that are indexed higher than the given index count
        /// </summary>
        /// <param name="manager">GPUI Manager</param>
        /// <param name="prototype">GPUI Prototype</param>
        /// <param name="instanceCount">New instance count to set on the runtime data</param>
        public static void SetInstanceCount(GPUInstancerManager manager, GPUInstancerPrototype prototype, int instanceCount)
        {
            GPUInstancerRuntimeData runtimeData = manager.GetRuntimeData(prototype, true);

            if (runtimeData == null)
            {
                return;
            }
            if (instanceCount > runtimeData.bufferSize)
            {
                Debug.LogError("Instance count can not be higher than the buffer size.");
                return;
            }
            runtimeData.instanceCount = instanceCount;
        }
Ejemplo n.º 8
0
 public virtual void SetupPrefabInstance(GPUInstancerRuntimeData runtimeData, bool forceNew = false)
 {
 }
Ejemplo n.º 9
0
        // Wind workaround:
        public static void AddTreeProxy(GPUInstancerPrototype treePrototype, GPUInstancerRuntimeData runtimeData)
        {
            switch (treePrototype.treeType)
            {
            case GPUInstancerTreeType.SpeedTree:
            case GPUInstancerTreeType.SpeedTree8:

                if (treeProxyParent == null)
                {
                    treeProxyParent = new GameObject("GPUI Tree Manager Proxy");
                    if (treeProxyList != null)
                    {
                        treeProxyList.Clear();
                    }
                }

                if (treeProxyList == null)
                {
                    treeProxyList = new Dictionary <GameObject, Transform>();    // Dict[TreePrefab, TreeProxyGO]
                }
                else if (treeProxyList.ContainsKey(treePrototype.prefabObject))
                {
                    if (treeProxyList[treePrototype.prefabObject] == null)
                    {
                        treeProxyList.Remove(treePrototype.prefabObject);
                    }
                    else
                    {
                        return;
                    }
                }

                Mesh treeProxyMesh = new Mesh();
                treeProxyMesh.name = "TreeProxyMesh";

                GameObject treeProxyObjectParent = new GameObject(treeProxyList.Count + "_" + treePrototype.name);
                treeProxyObjectParent.transform.SetParent(treeProxyParent.transform);
                treeProxyObjectParent.transform.localPosition = Vector3.zero;
                treeProxyObjectParent.transform.localRotation = Quaternion.identity;
                treeProxyList.Add(treePrototype.prefabObject, treeProxyObjectParent.transform);

                if (treePrototype.prefabObject.GetComponent <LODGroup>() != null)
                {
                    LOD[] speedTreeLODs = treePrototype.prefabObject.GetComponent <LODGroup>().GetLODs();
                    for (int lod = 0; lod < speedTreeLODs.Length; lod++)
                    {
                        if (speedTreeLODs[lod].renderers[0].GetComponent <BillboardRenderer>())
                        {
                            continue;
                        }

                        Material[] treeProxyMaterial = new Material[1] {
                            new Material(Shader.Find(GPUInstancerConstants.SHADER_GPUI_TREE_PROXY))
                        };

                        InstantiateTreeProxyObject(speedTreeLODs[lod].renderers[0].gameObject, treeProxyObjectParent, treeProxyMaterial, treeProxyMesh, lod == 0);
                    }
                }
                else
                {
                    Material[] treeProxyMaterial = new Material[1] {
                        new Material(Shader.Find(GPUInstancerConstants.SHADER_GPUI_TREE_PROXY))
                    };

                    InstantiateTreeProxyObject(treePrototype.prefabObject, treeProxyObjectParent, treeProxyMaterial, treeProxyMesh, true);
                }
                break;

            case GPUInstancerTreeType.TreeCreatorTree:

                // no need to create a TreeCreator proxy - setting the global wind vector instead
                Shader.SetGlobalVector("_Wind", GetWindVector());

                //Material[] treeCreatorProxyMaterials = new Material[2];
                //treeCreatorProxyMaterials[0] = new Material(Shader.Find(GPUInstancerConstants.SHADER_GPUI_TREE_PROXY));
                //treeCreatorProxyMaterials[1] = new Material(Shader.Find(GPUInstancerConstants.SHADER_GPUI_TREE_PROXY));
                //InstantiateTreeProxyObject(treePrototype.prefabObject, treeProxyObjectParent, treeCreatorProxyMaterials, treeProxyMesh, true);
                break;
            }
        }