public IEnumerator ReplaceUnityTrees() { _isCoroutineActive = true; if (prototypeList.Count > 0) { Vector4[] treeScales = new Vector4[prototypeList.Count]; int count = 0; foreach (GPUInstancerTreePrototype tp in prototypeList) { treeScales[count] = tp.isApplyPrefabScale ? tp.prefabObject.transform.localScale : Vector3.one; count++; } int[] instanceCounts = new int[prototypeList.Count]; List <Vector4> treeDataList = new List <Vector4>(); // prototypeIndex - positionx3 - rotation - scalex2 int instanceTotal = 0; foreach (Terrain terrain in _terrains) { if (terrain == null) { continue; } if (terrain.terrainData.treePrototypes.Length > prototypeList.Count) { Debug.LogError("Additional Terrain has more Tree protototypes than defined prototypes on the Tree Manager. Tree Manager requires every Terrain to have the same Tree prototypes defined.", terrain); continue; } terrain.treeDistance = 0f; // will not persist if called at runtime. Vector3 terrainSize = terrain.terrainData.size; Vector3 terrainPosition = terrain.GetPosition(); TreeInstance[] treeInstances = terrain.terrainData.treeInstances; instanceTotal += treeInstances.Length; foreach (TreeInstance treeInstance in treeInstances) { treeDataList.Add(new Vector4( treeInstance.prototypeIndex, treeInstance.position.x * terrainSize.x + terrainPosition.x, treeInstance.position.y * terrainSize.y + terrainPosition.y, treeInstance.position.z * terrainSize.z + terrainPosition.z )); treeDataList.Add(new Vector4( treeInstance.rotation, treeInstance.widthScale, treeInstance.heightScale, 0 )); instanceCounts[treeInstance.prototypeIndex]++; } } if (instanceTotal > 0) { if (initializeWithCoroutine && !isInitialized) { yield return(null); } ComputeBuffer treeDataBuffer = new ComputeBuffer(treeDataList.Count, GPUInstancerConstants.STRIDE_SIZE_FLOAT4); #if UNITY_2019_1_OR_NEWER treeDataBuffer.SetData(treeDataList); #else treeDataBuffer.SetData(treeDataList.ToArray()); #endif ComputeBuffer treeScalesBuffer = new ComputeBuffer(treeScales.Length, GPUInstancerConstants.STRIDE_SIZE_FLOAT4); treeScalesBuffer.SetData(treeScales); ComputeBuffer counterBuffer = new ComputeBuffer(1, GPUInstancerConstants.STRIDE_SIZE_INT); uint[] emptyCounterData = new uint[1]; treeDataList = null; treeScales = null; GPUInstancerRuntimeData runtimeData; for (int i = 0; i < runtimeDataList.Count; i++) { runtimeData = runtimeDataList[i]; int instanceCount = instanceCounts[i]; runtimeData.bufferSize = instanceCount; runtimeData.instanceCount = instanceCount; if (instanceCount == 0) { GPUInstancerUtility.ReleaseInstanceBuffers(runtimeData); continue; } counterBuffer.SetData(emptyCounterData); if (runtimeData.transformationMatrixVisibilityBuffer != null) { runtimeData.transformationMatrixVisibilityBuffer.Release(); } runtimeData.transformationMatrixVisibilityBuffer = new ComputeBuffer(instanceCount, GPUInstancerConstants.STRIDE_SIZE_MATRIX4X4); _treeInstantiationComputeShader.SetBuffer(0, GPUInstancerConstants.VisibilityKernelPoperties.INSTANCE_DATA_BUFFER, runtimeData.transformationMatrixVisibilityBuffer); _treeInstantiationComputeShader.SetBuffer(0, GPUInstancerConstants.TreeKernelProperties.TREE_DATA, treeDataBuffer); _treeInstantiationComputeShader.SetBuffer(0, GPUInstancerConstants.TreeKernelProperties.TREE_SCALES, treeScalesBuffer); _treeInstantiationComputeShader.SetBuffer(0, GPUInstancerConstants.GrassKernelProperties.COUNTER_BUFFER, counterBuffer); _treeInstantiationComputeShader.SetInt( GPUInstancerConstants.VisibilityKernelPoperties.BUFFER_PARAMETER_BUFFER_SIZE, instanceTotal); //_treeInstantiationComputeShader.SetVector( // GPUInstancerConstants.GrassKernelProperties.TERRAIN_SIZE_DATA, terrain.terrainData.size); //_treeInstantiationComputeShader.SetVector( // GPUInstancerConstants.TreeKernelProperties.TERRAIN_POSITION, terrain.GetPosition()); _treeInstantiationComputeShader.SetBool( GPUInstancerConstants.TreeKernelProperties.IS_APPLY_ROTATION, ((GPUInstancerTreePrototype)runtimeData.prototype).isApplyRotation); _treeInstantiationComputeShader.SetBool( GPUInstancerConstants.TreeKernelProperties.IS_APPLY_TERRAIN_HEIGHT, ((GPUInstancerTreePrototype)runtimeData.prototype).isApplyTerrainHeight); _treeInstantiationComputeShader.SetInt( GPUInstancerConstants.TreeKernelProperties.PROTOTYPE_INDEX, i); _treeInstantiationComputeShader.Dispatch(0, Mathf.CeilToInt(instanceTotal / GPUInstancerConstants.COMPUTE_SHADER_THREAD_COUNT), 1, 1); GPUInstancerUtility.InitializeGPUBuffer(runtimeData); if (initializeWithCoroutine && !isInitialized) { yield return(null); } } treeDataBuffer.Release(); treeScalesBuffer.Release(); counterBuffer.Release(); } else { GPUInstancerUtility.ReleaseInstanceBuffers(runtimeDataList); } } isInitial = true; if (!isInitialized) { GPUInstancerUtility.TriggerEvent(GPUInstancerEventType.TreeInitializationFinished); } _isCoroutineActive = false; }
public IEnumerator ReplaceUnityTrees() { TreeInstance[] treeInstances = terrain.terrainData.treeInstances; int instanceTotal = treeInstances.Length; if (instanceTotal > 0) { Vector3 terrainSize = terrain.terrainData.size; Vector3 terrainPosition = terrain.GetPosition(); Vector3 treePos = Vector3.zero; TreeInstance treeInstance; Vector4[] treeScales = new Vector4[prototypeList.Count]; int count = 0; foreach (GPUInstancerTreePrototype tp in prototypeList) { treeScales[count] = tp.prefabObject.transform.localScale; count++; } terrain.treeDistance = 0f; // will not persist if called at runtime. Vector4[] treeDataArray = new Vector4[instanceTotal * 2]; // prototypeIndex - positionx3 - rotation - scalex2 int[] instanceCounts = new int[terrain.terrainData.treePrototypes.Length]; int index = 0; for (int i = 0; i < instanceTotal; i++) { treeInstance = treeInstances[i]; treePos = treeInstance.position; treeDataArray[index].x = treeInstance.prototypeIndex; treeDataArray[index].y = treePos.x; treeDataArray[index].z = treePos.y; treeDataArray[index].w = treePos.z; index++; treeDataArray[index].x = treeInstance.rotation; treeDataArray[index].y = treeInstance.widthScale; treeDataArray[index].z = treeInstance.heightScale; index++; instanceCounts[treeInstance.prototypeIndex]++; } yield return(null); ComputeBuffer treeDataBuffer = new ComputeBuffer(treeDataArray.Length, GPUInstancerConstants.STRIDE_SIZE_FLOAT4); treeDataBuffer.SetData(treeDataArray); ComputeBuffer treeScalesBuffer = new ComputeBuffer(treeScales.Length, GPUInstancerConstants.STRIDE_SIZE_FLOAT4); treeScalesBuffer.SetData(treeScales); ComputeBuffer counterBuffer = new ComputeBuffer(1, GPUInstancerConstants.STRIDE_SIZE_INT); uint[] emptyCounterData = new uint[1]; GPUInstancerRuntimeData runtimeData; for (int i = 0; i < runtimeDataList.Count; i++) { if (instanceCounts[i] == 0) { continue; } runtimeData = runtimeDataList[i]; counterBuffer.SetData(emptyCounterData); runtimeData.transformationMatrixVisibilityBuffer = new ComputeBuffer(instanceCounts[i], GPUInstancerConstants.STRIDE_SIZE_MATRIX4X4); _treeInstantiationComputeShader.SetBuffer(0, GPUInstancerConstants.VisibilityKernelPoperties.INSTANCE_DATA_BUFFER, runtimeData.transformationMatrixVisibilityBuffer); _treeInstantiationComputeShader.SetBuffer(0, GPUInstancerConstants.TreeKernelProperties.TREE_DATA, treeDataBuffer); _treeInstantiationComputeShader.SetBuffer(0, GPUInstancerConstants.TreeKernelProperties.TREE_SCALES, treeScalesBuffer); _treeInstantiationComputeShader.SetBuffer(0, GPUInstancerConstants.GrassKernelProperties.COUNTER_BUFFER, counterBuffer); _treeInstantiationComputeShader.SetInt( GPUInstancerConstants.VisibilityKernelPoperties.BUFFER_PARAMETER_BUFFER_SIZE, instanceTotal); _treeInstantiationComputeShader.SetVector( GPUInstancerConstants.GrassKernelProperties.TERRAIN_SIZE_DATA, terrainSize); _treeInstantiationComputeShader.SetVector( GPUInstancerConstants.TreeKernelProperties.TERRAIN_POSITION, terrainPosition); _treeInstantiationComputeShader.SetBool( GPUInstancerConstants.TreeKernelProperties.IS_APPLY_ROTATION, ((GPUInstancerTreePrototype)runtimeData.prototype).isApplyRotation); _treeInstantiationComputeShader.SetInt( GPUInstancerConstants.TreeKernelProperties.PROTOTYPE_INDEX, i); _treeInstantiationComputeShader.Dispatch(0, Mathf.CeilToInt(instanceTotal / GPUInstancerConstants.VISIBILITY_SHADER_THREAD_COUNT), 1, 1); runtimeData.bufferSize = instanceCounts[i]; runtimeData.instanceCount = instanceCounts[i]; GPUInstancerUtility.InitializeGPUBuffer(runtimeData); yield return(null); } treeDataBuffer.Release(); treeScalesBuffer.Release(); counterBuffer.Release(); } isInitial = true; GPUInstancerUtility.TriggerEvent(GPUInstancerEventType.TreeInitializationFinished); }