void UpdatePotentialVisibleCells(bool forceUpdate) { Vector3 selectedCameraPosition = GetCameraPosition(); _potentialCellPadding = VegetationSystemPro.VegetationCellSize * 2; bool needsUpdate = forceUpdate; if (PotentialVisibleCellList == null) { PotentialVisibleCellList = new List <VegetationCell>(); needsUpdate = true; } float distance = Vector3.Distance(_potentialCellsCenterPosition, selectedCameraPosition); if (distance > VegetationSystemPro.VegetationCellSize || Math.Abs(_lastVegetationDistance - VegetationSystemPro.VegetationSettings.GetTreeDistance()) > 0.1f || _dirty) { needsUpdate = true; _potentialCellsCenterPosition = selectedCameraPosition; _lastVegetationDistance = VegetationSystemPro.VegetationSettings.GetTreeDistance(); } if (needsUpdate) { _dirty = false; // if (_lastVisibleVegetationCellList == null) _lastVisibleVegetationCellList = new List<VegetationCell>(); // for (int i = 0; i <= JobCullingGroup.VisibleCellIndexList.Length - 1; i++) // { // _lastVisibleVegetationCellList.Add(PotentialVisibleCellList[JobCullingGroup.VisibleCellIndexList[i]]); // } JobCullingGroup.VisibleCellIndexList.Clear(); Profiler.BeginSample("Potential Cell Selection"); float areaSize = VegetationSystemPro.VegetationSettings.GetTreeDistance() * 2 + _potentialCellPadding * 2; Vector2 position = new Vector2(selectedCameraPosition.x - areaSize / 2f, selectedCameraPosition.z - areaSize / 2f); Rect selectedAreaRect = new Rect(position, new Vector2(areaSize, areaSize)); if (OnPotentialCellInvisibleDelegate != null) { for (int i = 0; i <= PotentialVisibleCellList.Count - 1; i++) { VegetationCell vegetationCell = PotentialVisibleCellList[i]; if (!vegetationCell.Rectangle.Overlaps(selectedAreaRect)) { OnPotentialCellInvisibleDelegate(this, vegetationCell); } } } PotentialVisibleCellList.Clear(); VegetationSystemPro.VegetationCellQuadTree.Query(selectedAreaRect, PotentialVisibleCellList); Profiler.EndSample(); UpdateCullingGroup(); } }
public void SpawnVegetationCell(VegetationCell vegetationCell, string vegetationItemID) { CompleteCellLoading(); if (!vegetationCell.Prepared) { VegetationCellSpawner.PrepareVegetationCell(vegetationCell); } bool hasInstancedIndirect; JobHandle cellSpawnHandle = VegetationCellSpawner.SpawnVegetationCell(vegetationCell, vegetationItemID, out hasInstancedIndirect); cellSpawnHandle.Complete(); if (!hasInstancedIndirect || !Application.isPlaying) { return; } ProcessInstancedIndirectCellList.Add(vegetationCell); JobHandle prepareInstancedIndirectHandle = PrepareInstancedIndirectSetupJobs(); prepareInstancedIndirectHandle.Complete(); SetupInstancedIndirectComputeBuffers(); ReturnVegetationCellTemporaryMemory(vegetationCell); }
public JobHandle SpawnVegetationCell(VegetationCell vegetationCell, out bool hasInstancedIndirect) { hasInstancedIndirect = false; JobHandleList.Clear(); Rect vegetationCellRect = vegetationCell.Rectangle; for (int i = 0; i <= VegetationPackageProList.Count - 1; i++) { for (int j = 0; j <= VegetationPackageProList[i].VegetationInfoList.Count - 1; j++) { VegetationItemInfoPro vegetationItemInfoPro = VegetationPackageProList[i].VegetationInfoList[j]; JobHandleList.Add(ExecuteSpawnRules(vegetationCell, vegetationCellRect, i, j)); if (vegetationItemInfoPro.VegetationRenderMode == VegetationRenderMode.InstancedIndirect) { hasInstancedIndirect = true; } } } if (JobHandleList.Length > 0) { CompactMemoryCellList.Add(vegetationCell); return(JobHandle.CombineDependencies(JobHandleList)); } return(default(JobHandle)); }
public void ClearCache(VegetationCell vegetationCell) { CompleteCellLoading(); vegetationCell.ClearCache(); ClearBillboardCellsCache(vegetationCell.VegetationCellBounds); OnClearCacheVegetationCellDelegate?.Invoke(this, vegetationCell); }
void ReturnVegetationCellTemporaryMemory(VegetationCell vegetationCell) { for (int i = 0; i <= vegetationCell.VegetationInstanceDataList.Count - 1; i++) { VegetationInstanceData vegetationInstanceData = vegetationCell.VegetationInstanceDataList[i]; VegetationCellSpawner.VegetationInstanceDataPool.ReturnObject(vegetationInstanceData); } vegetationCell.VegetationInstanceDataList.Clear(); }
public void ClearCache(VegetationCell vegetationCell, string vegetationItemID) { VegetationItemIndexes indexes = GetVegetationItemIndexes(vegetationItemID); if (indexes.VegetationPackageIndex >= 0) { ClearCache(vegetationCell, indexes.VegetationPackageIndex, indexes.VegetationItemIndex); } }
public JobHandle SpawnVegetationCell(VegetationCell vegetationCell, int currentDistanceBand, out bool hasInstancedIndirect, bool billboardsOnly) { hasInstancedIndirect = false; if (billboardsOnly) { vegetationCell.LoadedBillboards = true; } else { vegetationCell.LoadedDistanceBand = currentDistanceBand; } JobHandleList.Clear(); Rect vegetationCellRect = vegetationCell.Rectangle; for (int i = 0; i <= VegetationPackageProList.Count - 1; i++) { for (int j = 0; j <= VegetationPackageProList[i].VegetationInfoList.Count - 1; j++) { VegetationItemInfoPro vegetationItemInfoPro = VegetationPackageProList[i].VegetationInfoList[j]; if (billboardsOnly) { if (!vegetationItemInfoPro.UseBillboards || vegetationItemInfoPro.VegetationType != VegetationType.Tree) { continue; } } int vegetationItemDistanceBand = vegetationItemInfoPro.GetDistanceBand(); if (currentDistanceBand > vegetationItemDistanceBand) { continue; } JobHandleList.Add(ExecuteSpawnRules(vegetationCell, vegetationCellRect, i, j)); if (vegetationItemInfoPro.VegetationRenderMode == VegetationRenderMode.InstancedIndirect) { hasInstancedIndirect = true; } } } if (JobHandleList.Length > 0) { CompactMemoryCellList.Add(vegetationCell); return(JobHandle.CombineDependencies(JobHandleList)); } return(default(JobHandle)); }
public void ClearCache(VegetationCell vegetationCell, int vegetationPackageIndex, int vegetationItemIndex) { CompleteCellLoading(); VegetationItemInfoPro vegetationItemInfo = VegetationPackageProList[vegetationPackageIndex].VegetationInfoList[vegetationItemIndex]; bool tree = vegetationItemInfo.VegetationType == VegetationType.Tree || vegetationItemInfo.VegetationType == VegetationType.LargeObjects; vegetationCell.ClearCache(vegetationPackageIndex, vegetationItemIndex, tree); ClearBillboardCellsCache(vegetationCell.VegetationCellBounds, vegetationPackageIndex, vegetationItemIndex); OnClearCacheVegetationCellVegetatonItemDelegate?.Invoke(this, vegetationCell, vegetationPackageIndex, vegetationItemIndex); }
void ReturnVegetationCellTemporaryMemory() { for (int i = 0; i <= CompactMemoryCellList.Count - 1; i++) { VegetationCell vegetationCell = CompactMemoryCellList[i]; for (int j = 0; j <= vegetationCell.VegetationInstanceDataList.Count - 1; j++) { VegetationInstanceData vegetationInstanceData = vegetationCell.VegetationInstanceDataList[j]; VegetationCellSpawner.VegetationInstanceDataPool.ReturnObject(vegetationInstanceData); } vegetationCell.VegetationInstanceDataList.Clear(); } CompactMemoryCellList.Clear(); }
public NativeList <MatrixInstance> GetVegetationItemInstances(VegetationCell vegetationCell, string vegetationItemID) { CompleteCellLoading(); VegetationItemIndexes vegetationItemIndexes = GetVegetationItemIndexes(vegetationItemID); if (vegetationCell.Prepared) { return(vegetationCell.VegetationPackageInstancesList[vegetationItemIndexes.VegetationPackageIndex] .VegetationItemMatrixList[vegetationItemIndexes.VegetationItemIndex]); } return(new NativeList <MatrixInstance>()); }
void SetComputeShaderBuffer(int bufferID, int bufferCountID, int cellIndex, int vegetationPackageIndex, int vegetationItemIndex) { if (cellIndex < _hasBufferList.Count) { VegetationCell vegetationCell = _hasBufferList[cellIndex]; int instanceCount = _hasBufferList[cellIndex].VegetationPackageInstancesList[vegetationPackageIndex].VegetationItemMatrixList[vegetationItemIndex].Length; MergeBufferShader.SetBuffer(MergeBufferKernelHandle, bufferID, vegetationCell.VegetationPackageInstancesList[vegetationPackageIndex].VegetationItemComputeBufferList[vegetationItemIndex].ComputeBuffer); MergeBufferShader.SetInt(bufferCountID, instanceCount); } else { MergeBufferShader.SetBuffer(MergeBufferKernelHandle, bufferID, _dummyComputeBuffer); MergeBufferShader.SetInt(bufferCountID, 0); } }
public void PrepareVegetationCell(VegetationCell vegetationCell) { int itemCount = 0; Profiler.BeginSample("PrepareVegetationCell"); for (int i = 0; i <= VegetationPackageProList.Count - 1; i++) { itemCount += VegetationPackageProList[i].VegetationInfoList.Count; VegetationPackageInstances vegetationPackageInstances = new VegetationPackageInstances(VegetationPackageProList[i].VegetationInfoList.Count); vegetationCell.VegetationPackageInstancesList.Add(vegetationPackageInstances); } vegetationCell.VegetationInstanceDataList.Capacity = itemCount; vegetationCell.Prepared = true; Profiler.EndSample(); }
public void ClearCache(Bounds bounds) { Rect clearRect = RectExtension.CreateRectFromBounds(bounds); CompleteCellLoading(); //TODO Use quadtree here for (int i = LoadedVegetationCellList.Count - 1; i >= 0; i--) { VegetationCell vegetationCell = LoadedVegetationCellList[i]; if (!vegetationCell.Rectangle.Overlaps(clearRect)) { continue; } vegetationCell.ClearCache(); LoadedVegetationCellList.RemoveAtSwapBack(i); OnClearCacheVegetationCellDelegate?.Invoke(this, vegetationCell); } ClearBillboardCellsCache(bounds); }
public JobHandle SpawnVegetationCell(VegetationCell vegetationCell, string vegetationItemID, out bool hasInstancedIndirect) { hasInstancedIndirect = false; Rect vegetationCellRect = vegetationCell.Rectangle; VegetationItemIndexes vegetationItemIndexes = VegetationSystemPro.GetVegetationItemIndexes(vegetationItemID); if (vegetationItemIndexes.VegetationPackageIndex >= 0) { VegetationItemInfoPro vegetationItemInfoPro = VegetationPackageProList[vegetationItemIndexes.VegetationPackageIndex].VegetationInfoList[vegetationItemIndexes.VegetationItemIndex]; if (vegetationItemInfoPro.VegetationRenderMode == VegetationRenderMode.InstancedIndirect) { hasInstancedIndirect = true; } CompactMemoryCellList.Add(vegetationCell); return(ExecuteSpawnRules(vegetationCell, vegetationCellRect, vegetationItemIndexes.VegetationPackageIndex, vegetationItemIndexes.VegetationItemIndex)); } return(default(JobHandle)); }
void DrawCellsIndirectComputeShader() { Profiler.BeginSample("Draw instanced indirect vegetation"); float lodBias = QualitySettings.lodBias * VegetationSettings.LODDistanceFactor; Vector4 floatingOriginOffsetVector4 = new Vector4(FloatingOriginOffset.x, FloatingOriginOffset.y, FloatingOriginOffset.z, 0); Vector3 sunLightDirection = SunDirectionalLight ? SunDirectionalLight.transform.forward : new Vector3(0, 0, 0); float minBoundsHeight = VegetationSystemBounds.center.y - VegetationSystemBounds.extents.y; Vector3 planeOrigin = new Vector3(0, minBoundsHeight, 0); bool shadowCulling = (SunDirectionalLight != null); for (int i = 0; i <= VegetationStudioCameraList.Count - 1; i++) { if (!VegetationStudioCameraList[i].Enabled) { continue; } if (VegetationStudioCameraList[i].RenderBillboardsOnly) { continue; } SetFrustumCullingPlanes(VegetationStudioCameraList[i].SelectedCamera); var targetCamera = VegetationStudioCameraList[i].RenderDirectToCamera ? VegetationStudioCameraList[i].SelectedCamera : null; for (int j = 0; j <= VegetationPackageProList.Count - 1; j++) { for (int k = 0; k <= VegetationPackageProList[j].VegetationInfoList.Count - 1; k++) { VegetationItemInfoPro vegetationItemInfo = VegetationPackageProList[j].VegetationInfoList[k]; if (vegetationItemInfo.VegetationRenderMode != VegetationRenderMode.InstancedIndirect) { continue; } VegetationItemModelInfo vegetationItemModelInfo = VegetationPackageProModelsList[j].VegetationItemModelList[k]; float vegetationItemCullDistance; float renderDistanceFactor = vegetationItemModelInfo.VegetationItemInfo.RenderDistanceFactor; if (VegetationSettings.DisableRenderDistanceFactor) { renderDistanceFactor = 1; } //if (vegetationItemModelInfo.DistanceBand == 0) if (vegetationItemModelInfo.VegetationItemInfo.VegetationType == VegetationType.Tree || vegetationItemModelInfo.VegetationItemInfo.VegetationType == VegetationType.LargeObjects) { vegetationItemCullDistance = VegetationSettings.GetTreeDistance() * renderDistanceFactor; } else { vegetationItemCullDistance = VegetationSettings.GetVegetationDistance() * renderDistanceFactor; } ShadowCastingMode shadowCastingMode = VegetationSettings.GetShadowCastingMode(vegetationItemInfo.VegetationType); if (vegetationItemInfo.DisableShadows) { shadowCastingMode = ShadowCastingMode.Off; } bool useShadowCulling = shadowCulling && shadowCastingMode == ShadowCastingMode.On; useShadowCulling = useShadowCulling && vegetationItemModelInfo.DistanceBand == 1; LayerMask layer = VegetationSettings.GetLayer(vegetationItemInfo.VegetationType); int totalInstanceCount = 0; _hasBufferList.Clear(); for (int l = 0; l <= VegetationStudioCameraList[i].JobCullingGroup.VisibleCellIndexList.Length - 1; l++) { int potentialVisibleCellIndex = VegetationStudioCameraList[i].JobCullingGroup.VisibleCellIndexList[l]; VegetationCell vegetationCell = VegetationStudioCameraList[i] .PotentialVisibleCellList[potentialVisibleCellIndex]; BoundingSphereInfo boundingSphereInfo = VegetationStudioCameraList[i] .GetBoundingSphereInfo(potentialVisibleCellIndex); int vegetationItemDistanceBand = vegetationItemModelInfo.DistanceBand; if (boundingSphereInfo.CurrentDistanceBand > vegetationItemDistanceBand) { continue; } if (vegetationCell.VegetationPackageInstancesList[j].VegetationItemMatrixList[k].Length == 0) { continue; } ComputeBufferInfo computeBufferInfo = vegetationCell.VegetationPackageInstancesList[j] .VegetationItemComputeBufferList[k]; if (!computeBufferInfo.Created) { continue; } _hasBufferList.Add(vegetationCell); } if (_hasBufferList.Count == 0) { continue; } int buffercount = 15; for (int m = 0; m <= _hasBufferList.Count - 1; m++) { totalInstanceCount += _hasBufferList[m].VegetationPackageInstancesList[j] .VegetationItemMatrixList[k].Length; } if (totalInstanceCount == 0) { continue; } CameraComputeBuffers cameraComputeBuffers = vegetationItemModelInfo.CameraComputeBufferList[i]; if (totalInstanceCount > cameraComputeBuffers.MergeBuffer.count) { cameraComputeBuffers.UpdateComputeBufferSize(totalInstanceCount + 5000); } cameraComputeBuffers.MergeBuffer.SetCounterValue(0); MergeBufferShader.SetBuffer(MergeBufferKernelHandle, _mergeBufferID, cameraComputeBuffers.MergeBuffer); for (int m = 0; m <= _hasBufferList.Count - 1; m += buffercount) { int instanceCount0 = _hasBufferList[m].VegetationPackageInstancesList[j] .VegetationItemMatrixList[k].Length; for (int n = 1; n <= buffercount - 1; n++) { if (m + n < _hasBufferList.Count) { int tempInstanceCount = _hasBufferList[m + n].VegetationPackageInstancesList[j] .VegetationItemMatrixList[k].Length; if (tempInstanceCount > instanceCount0) { instanceCount0 = tempInstanceCount; } } } // ReSharper disable once RedundantCast int threadGroups = Mathf.CeilToInt((float)instanceCount0 / 32f); if (threadGroups == 0) { continue; } SetComputeShaderBuffer(_mergeSourceBuffer0ID, _mergeInstanceCount0ID, m, j, k); SetComputeShaderBuffer(_mergeSourceBuffer1ID, _mergeInstanceCount1ID, m + 1, j, k); SetComputeShaderBuffer(_mergeSourceBuffer2ID, _mergeInstanceCount2ID, m + 2, j, k); SetComputeShaderBuffer(_mergeSourceBuffer3ID, _mergeInstanceCount3ID, m + 3, j, k); SetComputeShaderBuffer(_mergeSourceBuffer4ID, _mergeInstanceCount4ID, m + 4, j, k); SetComputeShaderBuffer(_mergeSourceBuffer5ID, _mergeInstanceCount5ID, m + 5, j, k); SetComputeShaderBuffer(_mergeSourceBuffer6ID, _mergeInstanceCount6ID, m + 6, j, k); SetComputeShaderBuffer(_mergeSourceBuffer7ID, _mergeInstanceCount7ID, m + 7, j, k); SetComputeShaderBuffer(_mergeSourceBuffer8ID, _mergeInstanceCount8ID, m + 8, j, k); SetComputeShaderBuffer(_mergeSourceBuffer9ID, _mergeInstanceCount9ID, m + 9, j, k); SetComputeShaderBuffer(_mergeSourceBuffer10ID, _mergeInstanceCount10ID, m + 10, j, k); SetComputeShaderBuffer(_mergeSourceBuffer11ID, _mergeInstanceCount11ID, m + 11, j, k); SetComputeShaderBuffer(_mergeSourceBuffer12ID, _mergeInstanceCount12ID, m + 12, j, k); SetComputeShaderBuffer(_mergeSourceBuffer13ID, _mergeInstanceCount13ID, m + 13, j, k); SetComputeShaderBuffer(_mergeSourceBuffer14ID, _mergeInstanceCount14ID, m + 14, j, k); MergeBufferShader.Dispatch(MergeBufferKernelHandle, threadGroups, 1, 1); } for (int n = 0; n <= vegetationItemModelInfo.VegetationMeshLod0.subMeshCount - 1; n++) { ComputeBuffer.CopyCount(cameraComputeBuffers.MergeBuffer, cameraComputeBuffers.ArgsBufferMergedLOD0List[n], sizeof(uint) * 1); } int threadGroupsFrustum = Mathf.CeilToInt(totalInstanceCount / 32f); if (threadGroupsFrustum == 0) { continue; } cameraComputeBuffers.VisibleBufferLOD0.SetCounterValue(0); cameraComputeBuffers.VisibleBufferLOD1.SetCounterValue(0); cameraComputeBuffers.VisibleBufferLOD2.SetCounterValue(0); cameraComputeBuffers.VisibleBufferLOD3.SetCounterValue(0); cameraComputeBuffers.ShadowBufferLOD0.SetCounterValue(0); cameraComputeBuffers.ShadowBufferLOD1.SetCounterValue(0); cameraComputeBuffers.ShadowBufferLOD2.SetCounterValue(0); cameraComputeBuffers.ShadowBufferLOD3.SetCounterValue(0); bool useLODs = true; FrusumMatrixShader.SetFloat(_cullFarStartID, vegetationItemCullDistance); FrusumMatrixShader.SetVector(_floatingOriginOffsetID, floatingOriginOffsetVector4); FrusumMatrixShader.SetBuffer(FrustumKernelHandle, _sourceBufferID, cameraComputeBuffers.MergeBuffer); FrusumMatrixShader.SetBuffer(FrustumKernelHandle, _visibleBufferLod0ID, cameraComputeBuffers.VisibleBufferLOD0); FrusumMatrixShader.SetBuffer(FrustumKernelHandle, _visibleBufferLod1ID, cameraComputeBuffers.VisibleBufferLOD1); FrusumMatrixShader.SetBuffer(FrustumKernelHandle, _visibleBufferLod2ID, cameraComputeBuffers.VisibleBufferLOD2); FrusumMatrixShader.SetBuffer(FrustumKernelHandle, _visibleBufferLod3ID, cameraComputeBuffers.VisibleBufferLOD3); FrusumMatrixShader.SetBuffer(FrustumKernelHandle, _shadowBufferLod0ID, cameraComputeBuffers.ShadowBufferLOD0); FrusumMatrixShader.SetBuffer(FrustumKernelHandle, _shadowBufferLod1ID, cameraComputeBuffers.ShadowBufferLOD1); FrusumMatrixShader.SetBuffer(FrustumKernelHandle, _shadowBufferLod2ID, cameraComputeBuffers.ShadowBufferLOD2); FrusumMatrixShader.SetBuffer(FrustumKernelHandle, _shadowBufferLod3ID, cameraComputeBuffers.ShadowBufferLOD3); FrusumMatrixShader.SetInt(_instanceCountID, totalInstanceCount); FrusumMatrixShader.SetBool(_useLodsID, useLODs); FrusumMatrixShader.SetBool(_noFrustumCullingID, VegetationStudioCameraList[i].CameraCullingMode == CameraCullingMode.Complete360); FrusumMatrixShader.SetBool(_shadowCullingID, useShadowCulling); FrusumMatrixShader.SetFloat(_boundingSphereRadiusID, vegetationItemModelInfo.BoundingSphereRadius); FrusumMatrixShader.SetFloat(_lod1Distance, vegetationItemModelInfo.LOD1Distance); FrusumMatrixShader.SetFloat(_lod2Distance, vegetationItemModelInfo.LOD2Distance); FrusumMatrixShader.SetFloat(_lod3Distance, vegetationItemModelInfo.LOD3Distance); FrusumMatrixShader.SetVector(_lightDirection, sunLightDirection); FrusumMatrixShader.SetVector(_planeOrigin, planeOrigin); FrusumMatrixShader.SetVector(_boundsSize, vegetationItemModelInfo.VegetationItemInfo.Bounds.size); FrusumMatrixShader.SetFloat(_lodFactor, vegetationItemInfo.LODFactor); FrusumMatrixShader.SetFloat(_lodBias, lodBias * 2); FrusumMatrixShader.SetFloat(_lodFadeDistance, 10); FrusumMatrixShader.SetInt(_lodCount, vegetationItemModelInfo.LODCount); FrusumMatrixShader.Dispatch(FrustumKernelHandle, threadGroupsFrustum, 1, 1); for (int n = 0; n <= vegetationItemModelInfo.VegetationMeshLod0.subMeshCount - 1; n++) { ComputeBuffer.CopyCount(cameraComputeBuffers.VisibleBufferLOD0, cameraComputeBuffers.ArgsBufferMergedLOD0List[n], sizeof(uint) * 1); ComputeBuffer.CopyCount(cameraComputeBuffers.ShadowBufferLOD0, cameraComputeBuffers.ShadowArgsBufferMergedLOD0List[n], sizeof(uint) * 1); } if (useLODs) { for (int n = 0; n <= vegetationItemModelInfo.VegetationMeshLod1.subMeshCount - 1; n++) { ComputeBuffer.CopyCount(cameraComputeBuffers.VisibleBufferLOD1, cameraComputeBuffers.ArgsBufferMergedLOD1List[n], sizeof(uint) * 1); ComputeBuffer.CopyCount(cameraComputeBuffers.ShadowBufferLOD1, cameraComputeBuffers.ShadowArgsBufferMergedLOD1List[n], sizeof(uint) * 1); } for (int n = 0; n <= vegetationItemModelInfo.VegetationMeshLod2.subMeshCount - 1; n++) { ComputeBuffer.CopyCount(cameraComputeBuffers.VisibleBufferLOD2, cameraComputeBuffers.ArgsBufferMergedLOD2List[n], sizeof(uint) * 1); ComputeBuffer.CopyCount(cameraComputeBuffers.ShadowBufferLOD2, cameraComputeBuffers.ShadowArgsBufferMergedLOD2List[n], sizeof(uint) * 1); } for (int n = 0; n <= vegetationItemModelInfo.VegetationMeshLod3.subMeshCount - 1; n++) { ComputeBuffer.CopyCount(cameraComputeBuffers.VisibleBufferLOD3, cameraComputeBuffers.ArgsBufferMergedLOD3List[n], sizeof(uint) * 1); ComputeBuffer.CopyCount(cameraComputeBuffers.ShadowBufferLOD3, cameraComputeBuffers.ShadowArgsBufferMergedLOD3List[n], sizeof(uint) * 1); } } //TODO calculate bounds one for each LOD float boundsDistance = vegetationItemCullDistance * 2 + vegetationItemModelInfo.BoundingSphereRadius; Bounds cellBounds = new Bounds(VegetationStudioCameraList[i].SelectedCamera.transform.position, new Vector3(boundsDistance, boundsDistance, boundsDistance)); RenderVegetationItemLODIndirect(vegetationItemModelInfo, cellBounds, 0, i, targetCamera, shadowCastingMode, layer, false); if (shadowCastingMode == ShadowCastingMode.On) { RenderVegetationItemLODIndirect(vegetationItemModelInfo, cellBounds, 0, i, targetCamera, ShadowCastingMode.ShadowsOnly, layer, true); } if (useLODs) { if (vegetationItemModelInfo.LODCount > 1) { RenderVegetationItemLODIndirect(vegetationItemModelInfo, cellBounds, 1, i, targetCamera, shadowCastingMode, layer, false); if (shadowCastingMode == ShadowCastingMode.On) { RenderVegetationItemLODIndirect(vegetationItemModelInfo, cellBounds, 1, i, targetCamera, ShadowCastingMode.ShadowsOnly, layer, true); } } if (vegetationItemModelInfo.LODCount > 2) { RenderVegetationItemLODIndirect(vegetationItemModelInfo, cellBounds, 2, i, targetCamera, shadowCastingMode, layer, false); if (shadowCastingMode == ShadowCastingMode.On) { RenderVegetationItemLODIndirect(vegetationItemModelInfo, cellBounds, 2, i, targetCamera, ShadowCastingMode.ShadowsOnly, layer, true); } } if (vegetationItemModelInfo.LODCount > 3) { RenderVegetationItemLODIndirect(vegetationItemModelInfo, cellBounds, 3, i, targetCamera, shadowCastingMode, layer, false); if (shadowCastingMode == ShadowCastingMode.On) { RenderVegetationItemLODIndirect(vegetationItemModelInfo, cellBounds, 3, i, targetCamera, ShadowCastingMode.ShadowsOnly, layer, true); } } } } } } Profiler.EndSample(); }
JobHandle ExecuteSpawnRules(VegetationCell vegetationCell, Rect vegetationCellRect, int vegetationPackageIndex, int vegetationItemIndex) { int firstUnityTerrainIndex = GetFirstUnityTerrainIndex(); VegetationItemInfoPro vegetationItemInfoPro = VegetationPackageProList[vegetationPackageIndex].VegetationInfoList[vegetationItemIndex]; VegetationPackagePro vegetationPackagePro = VegetationPackageProList[vegetationPackageIndex]; VegetationItemModelInfo vegetationItemModelInfo = VegetationPackageProModelsList[vegetationPackageIndex].VegetationItemModelList[vegetationItemIndex]; BiomeType currentBiome = VegetationPackageProList[vegetationPackageIndex].BiomeType; int currentBiomeSortOrder = VegetationPackageProList[vegetationPackageIndex].BiomeSortOrder; float globalDensity = VegetationSettings.GetVegetationItemDensity(vegetationItemInfoPro.VegetationType); if (vegetationCell.VegetationPackageInstancesList[vegetationPackageIndex].LoadStateList[vegetationItemIndex] == 1) { return(default(JobHandle)); } vegetationCell.VegetationPackageInstancesList[vegetationPackageIndex].LoadStateList[vegetationItemIndex] = 1; bool doRuntimeSpawn = !(currentBiome != BiomeType.Default && !vegetationCell.HasBiome(currentBiome)); NativeList <MatrixInstance> matrixList = vegetationCell.VegetationPackageInstancesList[vegetationPackageIndex].VegetationItemMatrixList[vegetationItemIndex]; matrixList.Clear(); if (!vegetationItemInfoPro.EnableRuntimeSpawn) { doRuntimeSpawn = false; } if (vegetationItemInfoPro.UseVegetationMask) { bool hasVegetationTypeIndex = false; if (vegetationCell.VegetationMaskList != null) { for (int k = 0; k <= vegetationCell.VegetationMaskList.Count - 1; k++) { if (vegetationCell.VegetationMaskList[k] .HasVegetationTypeIndex(vegetationItemInfoPro.VegetationTypeIndex)) { hasVegetationTypeIndex = true; break; } } } if (!hasVegetationTypeIndex) { doRuntimeSpawn = false; } } JobHandle vegetationItemHandle = default(JobHandle); if (doRuntimeSpawn) { VegetationInstanceData instanceData = VegetationInstanceDataPool.GetObject(); instanceData.Clear(); vegetationCell.VegetationInstanceDataList.Add(instanceData); float sampleDistance = vegetationItemInfoPro.SampleDistance / globalDensity; float density = 1; float calculatedSampleDistance = Mathf.Clamp(sampleDistance / density, 0.1f, vegetationCell.VegetationCellBounds.size.x / 2f); int xSamples = Mathf.CeilToInt(vegetationCell.VegetationCellBounds.size.x / calculatedSampleDistance); int zSamples = Mathf.CeilToInt(vegetationCell.VegetationCellBounds.size.z / calculatedSampleDistance); int sampleCount = xSamples * zSamples; matrixList.Capacity = sampleCount; instanceData.SpawnLocations.ResizeUninitialized(sampleCount); if (firstUnityTerrainIndex > -1) { instanceData.ResizeUninitialized(sampleCount); InitInstanceData initInstanceData = new InitInstanceData { HeightmapSampled = instanceData.HeightmapSampled.ToDeferredJobArray(), Excluded = instanceData.Excluded.ToDeferredJobArray() }; vegetationItemHandle = initInstanceData.Schedule(sampleCount, 256, vegetationItemHandle); } else { instanceData.SetCapasity(sampleCount); } float defaultSpawnChance = 0; if (currentBiome == BiomeType.Default) { defaultSpawnChance = 1; } CalculateCellSpawnLocationsWideJob calculateCellSpawnLocationsWideJob = new CalculateCellSpawnLocationsWideJob { SpawnLocations = instanceData.SpawnLocations.ToDeferredJobArray(), CellSize = vegetationCell.VegetationCellBounds.size, CellCorner = vegetationCell.VegetationCellBounds.center - vegetationCell.VegetationCellBounds.extents, SampleDistance = sampleDistance, RandomizePosition = vegetationItemInfoPro.RandomizePosition, Density = 1, DefaultSpawnChance = defaultSpawnChance, RandomNumbers = RandomNumbers, CellRect = vegetationCellRect, CellIndex = vegetationCell.Index, Seed = vegetationItemInfoPro.Seed + VegetationSettings.Seed, UseSamplePointOffset = vegetationItemInfoPro.UseSamplePointOffset, SamplePointMinOffset = vegetationItemInfoPro.SamplePointMinOffset, SamplePointMaxOffset = vegetationItemInfoPro.SamplePointMaxOffset, XSamples = xSamples, ZSamples = zSamples, CalculatedSampleDistance = calculatedSampleDistance }; vegetationItemHandle = calculateCellSpawnLocationsWideJob.Schedule(sampleCount, 64, vegetationItemHandle); if (vegetationCell.BiomeMaskList != null) { for (int k = 0; k <= vegetationCell.BiomeMaskList.Count - 1; k++) { if (vegetationCell.BiomeMaskList[k].BiomeSortOrder < currentBiomeSortOrder) { continue; } vegetationItemHandle = vegetationCell.BiomeMaskList[k] .FilterSpawnLocations(instanceData.SpawnLocations, currentBiome, sampleCount, vegetationItemHandle); } } if (vegetationItemInfoPro.UseNoiseCutoff) { PerlinNoiseCutoffJob perlinNoiseCutoffJob = new PerlinNoiseCutoffJob { InversePerlinMask = vegetationItemInfoPro.NoiseCutoffInverse, PerlinCutoff = vegetationItemInfoPro.NoiseCutoffValue, PerlinScale = vegetationItemInfoPro.NoiseCutoffScale, Offset = vegetationItemInfoPro.NoiseCutoffOffset, SpawnLocationList = instanceData.SpawnLocations.ToDeferredJobArray() }; vegetationItemHandle = perlinNoiseCutoffJob.Schedule(sampleCount, 64, vegetationItemHandle); } if (vegetationItemInfoPro.UseNoiseDensity) { PerlinNoiseDensityJob perlinNoiseDensityJob = new PerlinNoiseDensityJob { InversePerlinMask = vegetationItemInfoPro.NoiseDensityInverse, PerlinScale = vegetationItemInfoPro.NoiseDensityScale, Offset = vegetationItemInfoPro.NoiseDensityOffset, SpawnLocationList = instanceData.SpawnLocations.ToDeferredJobArray() }; vegetationItemHandle = perlinNoiseDensityJob.Schedule(sampleCount, 64, vegetationItemHandle); } FilterSpawnLocationsChanceJob filterSpawnLocationsChanceJob = new FilterSpawnLocationsChanceJob { SpawnLocationList = instanceData.SpawnLocations.ToDeferredJobArray(), RandomNumbers = RandomNumbers, Density = vegetationItemInfoPro.Density }; vegetationItemHandle = filterSpawnLocationsChanceJob.Schedule(sampleCount, 64, vegetationItemHandle); for (int k = 0; k <= VegetationStudioTerrainList.Count - 1; k++) { vegetationItemHandle = VegetationStudioTerrainList[k] .SampleTerrain(instanceData.SpawnLocations, instanceData, sampleCount, vegetationCellRect, vegetationItemHandle); } if (vegetationItemInfoPro.UseTerrainSourceExcludeRule) { TerrainSourceExcludeRuleJob terrainSourceExcludeRuleJob = new TerrainSourceExcludeRuleJob { Excluded = instanceData.Excluded.ToDeferredJobArray(), TerrainSourceID = instanceData.TerrainSourceID.ToDeferredJobArray(), TerrainSourceRule = vegetationItemInfoPro.TerrainSourceExcludeRule }; vegetationItemHandle = terrainSourceExcludeRuleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle); } if (vegetationItemInfoPro.UseTerrainSourceIncludeRule) { TerrainSourceIncludeRuleJob terrainSourceIncludeRuleJob = new TerrainSourceIncludeRuleJob { Excluded = instanceData.Excluded.ToDeferredJobArray(), TerrainSourceID = instanceData.TerrainSourceID.ToDeferredJobArray(), TerrainSourceRule = vegetationItemInfoPro.TerrainSourceIncludeRule }; vegetationItemHandle = terrainSourceIncludeRuleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle); } if (vegetationItemInfoPro.UseSteepnessRule) { InstanceSteepnessRuleJob instanceSteepnessRuleJob = new InstanceSteepnessRuleJob { Excluded = instanceData.Excluded.ToDeferredJobArray(), TerrainNormal = instanceData.TerrainNormal.ToDeferredJobArray(), RandomNumberIndex = instanceData.RandomNumberIndex.ToDeferredJobArray(), MinSteepness = vegetationItemInfoPro.MinSteepness, MaxSteepness = vegetationItemInfoPro.MaxSteepness, Advanced = vegetationItemInfoPro.UseAdvancedSteepnessRule, SteepnessRuleCurveArray = vegetationItemModelInfo.SteepnessRuleCurveArray, RandomNumbers = RandomNumbers }; vegetationItemHandle = instanceSteepnessRuleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle); } if (vegetationItemInfoPro.UseHeightRule) { InstanceHeightRuleJob instanceHeightRuleJob = new InstanceHeightRuleJob { Excluded = instanceData.Excluded.ToDeferredJobArray(), Position = instanceData.Position.ToDeferredJobArray(), RandomNumberIndex = instanceData.RandomNumberIndex.ToDeferredJobArray(), MinHeight = vegetationItemInfoPro.MinHeight + WorldspaceSeaLevel, MaxHeight = vegetationItemInfoPro.MaxHeight + WorldspaceSeaLevel, Advanced = vegetationItemInfoPro.UseAdvancedHeightRule, HeightRuleCurveArray = vegetationItemModelInfo.HeightRuleCurveArray, RandomNumbers = RandomNumbers, MaxCurveHeight = vegetationItemInfoPro.MaxCurveHeight }; vegetationItemHandle = instanceHeightRuleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle); } if (!vegetationItemInfoPro.UseVegetationMask && vegetationCell.VegetationMaskList != null) { for (int k = 0; k <= vegetationCell.VegetationMaskList.Count - 1; k++) { vegetationItemHandle = vegetationCell.VegetationMaskList[k].SampleMask(instanceData, vegetationItemInfoPro.VegetationType, vegetationItemHandle); } } else { if (vegetationCell.VegetationMaskList != null) { for (int k = 0; k <= vegetationCell.VegetationMaskList.Count - 1; k++) { vegetationItemHandle = vegetationCell.VegetationMaskList[k].SampleIncludeVegetationMask( instanceData, vegetationItemInfoPro.VegetationTypeIndex, vegetationItemHandle); } if (vegetationCell.VegetationMaskList.Count > 0) { ProcessIncludeVegetationMaskJob processIncludeVegetationMaskJob = new ProcessIncludeVegetationMaskJob { Excluded = instanceData.Excluded.ToDeferredJobArray(), Scale = instanceData.Scale.ToDeferredJobArray(), RandomNumberIndex = instanceData.RandomNumberIndex.ToDeferredJobArray(), VegetationMaskDensity = instanceData.VegetationMaskDensity.ToDeferredJobArray(), VegetationMaskScale = instanceData.VegetationMaskScale.ToDeferredJobArray(), RandomNumbers = RandomNumbers }; vegetationItemHandle = processIncludeVegetationMaskJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle); } } } if (vegetationItemInfoPro.UseConcaveLocationRule) { for (int k = 0; k <= VegetationStudioTerrainList.Count - 1; k++) { vegetationItemHandle = VegetationStudioTerrainList[k].SampleConcaveLocation(instanceData, vegetationItemInfoPro.ConcaveLoactionMinHeightDifference, vegetationItemInfoPro.ConcaveLoactionDistance, vegetationItemInfoPro.ConcaveLocationInverse, vegetationItemInfoPro.ConcaveLoactionAverage, vegetationCellRect, vegetationItemHandle); } } if (vegetationItemInfoPro.UseTextureMaskIncludeRules) { for (int k = 0; k <= vegetationItemInfoPro.TextureMaskIncludeRuleList.Count - 1; k++) { TextureMaskGroup textureMaskGroup = vegetationPackagePro.GetTextureMaskGroup(vegetationItemInfoPro .TextureMaskIncludeRuleList[k].TextureMaskGroupID); if (textureMaskGroup != null) { vegetationItemHandle = textureMaskGroup.SampleIncludeMask(instanceData, vegetationCellRect, vegetationItemInfoPro.TextureMaskIncludeRuleList[k], vegetationItemHandle); } } FilterIncludeMaskJob filterIncludeMaskJob = new FilterIncludeMaskJob { Excluded = instanceData.Excluded.ToDeferredJobArray(), TextureMaskData = instanceData.TextureMaskData.ToDeferredJobArray() }; vegetationItemHandle = filterIncludeMaskJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle); } if (vegetationItemInfoPro.UseTextureMaskExcludeRules) { for (int k = 0; k <= vegetationItemInfoPro.TextureMaskExcludeRuleList.Count - 1; k++) { TextureMaskGroup textureMaskGroup = vegetationPackagePro.GetTextureMaskGroup(vegetationItemInfoPro .TextureMaskExcludeRuleList[k].TextureMaskGroupID); if (textureMaskGroup != null) { vegetationItemHandle = textureMaskGroup.SampleExcludeMask(instanceData, vegetationCellRect, vegetationItemInfoPro.TextureMaskExcludeRuleList[k], vegetationItemHandle); } } } OffsetAndRotateScaleVegetationInstanceMathJob offsetAndRotateScaleVegetationInstanceJob = new OffsetAndRotateScaleVegetationInstanceMathJob { RandomNumbers = RandomNumbers, Excluded = instanceData.Excluded.ToDeferredJobArray(), Scale = instanceData.Scale.ToDeferredJobArray(), Position = instanceData.Position.ToDeferredJobArray(), Rotation = instanceData.Rotation.ToDeferredJobArray(), RandomNumberIndex = instanceData.RandomNumberIndex.ToDeferredJobArray(), TerrainNormal = instanceData.TerrainNormal.ToDeferredJobArray(), VegetationRotationType = vegetationItemInfoPro.Rotation, MinScale = vegetationItemInfoPro.MinScale, MaxScale = vegetationItemInfoPro.MaxScale, Offset = vegetationItemInfoPro.Offset, RotationOffset = vegetationItemInfoPro.RotationOffset, ScaleMultiplier = vegetationItemInfoPro.ScaleMultiplier }; vegetationItemHandle = offsetAndRotateScaleVegetationInstanceJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle); if (vegetationItemInfoPro.UseNoiseScaleRule) { PerlinNoiseScaleJob perlinNoiseScaleJob = new PerlinNoiseScaleJob { Excluded = instanceData.Excluded.ToDeferredJobArray(), Position = instanceData.Position.ToDeferredJobArray(), Scale = instanceData.Scale.ToDeferredJobArray(), PerlinScale = vegetationItemInfoPro.NoiseScaleScale, MinScale = vegetationItemInfoPro.NoiseScaleMinScale, MaxScale = vegetationItemInfoPro.NoiseScaleMaxScale, InversePerlinMask = vegetationItemInfoPro.NoiseScaleInverse, Offset = vegetationItemInfoPro.NoiseScaleOffset }; vegetationItemHandle = perlinNoiseScaleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle); } if (vegetationItemInfoPro.UseBiomeEdgeScaleRule && currentBiome != BiomeType.Default) { BiomeEdgeDistanceScaleRuleJob biomeEdgeDistanceScaleRuleJob = new BiomeEdgeDistanceScaleRuleJob { Excluded = instanceData.Excluded.ToDeferredJobArray(), Scale = instanceData.Scale.ToDeferredJobArray(), BiomeDistance = instanceData.BiomeDistance.ToDeferredJobArray(), MinScale = vegetationItemInfoPro.BiomeEdgeScaleMinScale, MaxScale = vegetationItemInfoPro.BiomeEdgeScaleMaxScale, MaxDistance = vegetationItemInfoPro.BiomeEdgeScaleDistance, InverseScale = vegetationItemInfoPro.BiomeEdgeScaleInverse }; vegetationItemHandle = biomeEdgeDistanceScaleRuleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle); } if (vegetationItemInfoPro.UseBiomeEdgeIncludeRule && currentBiome != BiomeType.Default) { BiomeEdgeDistanceIncludeRuleJob biomeEdgeDistanceIncludeRuleJob = new BiomeEdgeDistanceIncludeRuleJob { Excluded = instanceData.Excluded.ToDeferredJobArray(), BiomeDistance = instanceData.BiomeDistance.ToDeferredJobArray(), MaxDistance = vegetationItemInfoPro.BiomeEdgeIncludeDistance, Inverse = vegetationItemInfoPro.BiomeEdgeIncludeInverse }; vegetationItemHandle = biomeEdgeDistanceIncludeRuleJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle); } if (vegetationItemInfoPro.UseTerrainTextureIncludeRules) { for (int k = 0; k <= VegetationStudioTerrainList.Count - 1; k++) { vegetationItemHandle = VegetationStudioTerrainList[k] .ProcessSplatmapRules(vegetationItemInfoPro.TerrainTextureIncludeRuleList, instanceData, true, vegetationCellRect, vegetationItemHandle); } } if (vegetationItemInfoPro.UseTerrainTextureExcludeRules) { for (int k = 0; k <= VegetationStudioTerrainList.Count - 1; k++) { vegetationItemHandle = VegetationStudioTerrainList[k] .ProcessSplatmapRules(vegetationItemInfoPro.TerrainTextureExcludeRuleList, instanceData, false, vegetationCellRect, vegetationItemHandle); } } if (vegetationItemInfoPro.UseDistanceFalloff) { DistanceFalloffJob distanceFalloffJob = new DistanceFalloffJob { Excluded = instanceData.Excluded.ToDeferredJobArray(), RandomNumberIndex = instanceData.RandomNumberIndex.ToDeferredJobArray(), DistanceFalloff = instanceData.DistanceFalloff.ToDeferredJobArray(), RandomNumbers = RandomNumbers, DistanceFalloffStartDistance = vegetationItemInfoPro.DistanceFalloffStartDistance }; vegetationItemHandle = distanceFalloffJob.Schedule(instanceData.Excluded, 64, vegetationItemHandle); } NewCreateInstanceMatrixJob createInstanceMatrixJob = new NewCreateInstanceMatrixJob { Excluded = instanceData.Excluded, Position = instanceData.Position, Scale = instanceData.Scale, Rotation = instanceData.Rotation, DistanceFalloff = instanceData.DistanceFalloff, VegetationInstanceMatrixList = matrixList }; vegetationItemHandle = createInstanceMatrixJob.Schedule(vegetationItemHandle); } if (!doRuntimeSpawn) { if (PersistentVegetationStorage && !PersistentVegetationStorage.DisablePersistentStorage) { PersistentVegetationCell persistentVegetationCell = PersistentVegetationStorage.GetPersistentVegetationCell(vegetationCell.Index); PersistentVegetationInfo persistentVegetationInfo = persistentVegetationCell?.GetPersistentVegetationInfo(vegetationItemInfoPro.VegetationItemID); if (persistentVegetationInfo != null && persistentVegetationInfo.VegetationItemList.Count > 0) { persistentVegetationInfo.CopyToNativeArray(); matrixList.ResizeUninitialized(persistentVegetationInfo.NativeVegetationItemArray.Length); LoadPersistentStorageToMatrixWideJob loadPersistentStorageToMatrixJob = new LoadPersistentStorageToMatrixWideJob { InstanceList = persistentVegetationInfo.NativeVegetationItemArray, VegetationInstanceMatrixList = matrixList.ToDeferredJobArray(), VegetationSystemPosition = VegetationSystemPro.VegetationSystemPosition }; vegetationItemHandle = loadPersistentStorageToMatrixJob.Schedule(matrixList, 64, vegetationItemHandle); } } } else { if (PersistentVegetationStorage && !PersistentVegetationStorage.DisablePersistentStorage) { PersistentVegetationCell persistentVegetationCell = PersistentVegetationStorage.GetPersistentVegetationCell(vegetationCell.Index); PersistentVegetationInfo persistentVegetationInfo = persistentVegetationCell?.GetPersistentVegetationInfo(vegetationItemInfoPro.VegetationItemID); if (persistentVegetationInfo != null && persistentVegetationInfo.VegetationItemList.Count > 0) { persistentVegetationInfo.CopyToNativeArray(); LoadPersistentStorageToMatrixJob loadPersistentStorageToMatrixJob = new LoadPersistentStorageToMatrixJob { InstanceList = persistentVegetationInfo.NativeVegetationItemArray, VegetationInstanceMatrixList = matrixList, VegetationSystemPosition = VegetationSystemPro.VegetationSystemPosition }; vegetationItemHandle = loadPersistentStorageToMatrixJob.Schedule(vegetationItemHandle); } } } Profiler.BeginSample("Schedule batched jobs"); JobHandle.ScheduleBatchedJobs(); Profiler.EndSample(); return(vegetationItemHandle); }
private void CreateVegetationCells() { DisposeVegetationCells(); Bounds expandedBounds = new Bounds(VegetationSystemBounds.center, VegetationSystemBounds.size); expandedBounds.Expand(new Vector3(VegetationCellSize * 2f, 0, VegetationCellSize * 2f)); Rect expandedRect = RectExtension.CreateRectFromBounds(expandedBounds); VegetationCellQuadTree = new QuadTree <VegetationCell>(expandedRect); int cellXCount = Mathf.CeilToInt(VegetationSystemBounds.size.x / VegetationCellSize); int cellZCount = Mathf.CeilToInt(VegetationSystemBounds.size.z / VegetationCellSize); Vector2 corner = new Vector2(VegetationSystemBounds.center.x - VegetationSystemBounds.size.x / 2f, VegetationSystemBounds.center.z - VegetationSystemBounds.size.z / 2f); for (int x = 0; x <= cellXCount - 1; x++) { for (int z = 0; z <= cellZCount - 1; z++) { VegetationCell vegetationCell = new VegetationCell(new Rect( new Vector2(VegetationCellSize * x + corner.x, VegetationCellSize * z + corner.y), new Vector2(VegetationCellSize, VegetationCellSize))); VegetationCellList.Add(vegetationCell); vegetationCell.Index = VegetationCellList.Count - 1; VegetationCellQuadTree.Insert(vegetationCell); } } LoadedVegetationCellList.Clear(); LoadedVegetationCellList.Capacity = VegetationCellList.Count; NativeArray <Bounds> vegetationCellBounds = new NativeArray <Bounds>(VegetationCellList.Count, Allocator.Persistent); for (int i = 0; i <= VegetationCellList.Count - 1; i++) { vegetationCellBounds[i] = VegetationCellList[i].VegetationCellBounds; } float minBoundsHeight = VegetationSystemBounds.center.y - VegetationSystemBounds.extents.y; float worldspaceSealevel = minBoundsHeight + SeaLevel; if (!ExcludeSeaLevelCells) { worldspaceSealevel = minBoundsHeight; } JobHandle jobHandle = default(JobHandle); for (int i = 0; i <= VegetationStudioTerrainList.Count - 1; i++) { jobHandle = VegetationStudioTerrainList[i] .SampleCellHeight(vegetationCellBounds, worldspaceSealevel, expandedRect, jobHandle); } jobHandle.Complete(); for (int i = 0; i <= VegetationCellList.Count - 1; i++) { VegetationCellList[i].VegetationCellBounds = vegetationCellBounds[i]; } vegetationCellBounds.Dispose(); PrepareVegetationCells(); VegetationStudioManager.OnVegetationCellRefresh(this); }