/// <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; }
/// <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); }
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); }
public ComputeBuffer GetTransformDataBuffer(GPUInstancerPrototype prototype) { GPUInstancerRuntimeData runtimeData = GetRuntimeData(prototype); if (runtimeData != null) { return(runtimeData.transformationMatrixVisibilityBuffer); } return(null); }
/// <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); }
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); }
/// <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; }
public virtual void SetupPrefabInstance(GPUInstancerRuntimeData runtimeData, bool forceNew = false) { }
// 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; } }