public VegetationPackageProModelInfo(VegetationPackagePro vegetationPackagePro, EnvironmentSettings environmentSettings, List <GameObject> windSamplerList, int cameraCount) { EnvironmentSettings = environmentSettings; for (int i = 0; i <= vegetationPackagePro.VegetationInfoList.Count - 1; i++) { VegetationItemModelInfo vegetationItemModelInfo = new VegetationItemModelInfo(vegetationPackagePro.VegetationInfoList[i], EnvironmentSettings, windSamplerList, cameraCount); VegetationItemModelList.Add(vegetationItemModelInfo); } }
void RenderVegetationItemLODIndirect(VegetationItemModelInfo vegetationItemModelInfo, Bounds cellBounds, int lodIndex, int cameraIndex, Camera selectedCamera, ShadowCastingMode shadowCastingMode, int layer, bool shadows) { MaterialPropertyBlock materialPropertyBlock = vegetationItemModelInfo.GetLODMaterialPropertyBlock(lodIndex); materialPropertyBlock.Clear(); ComputeBuffer visibleBuffer = vegetationItemModelInfo.GetLODVisibleBuffer(lodIndex, cameraIndex, shadows); Mesh mesh = vegetationItemModelInfo.GetLODMesh(lodIndex); Material[] materials = vegetationItemModelInfo.GetLODMaterials(lodIndex); if (vegetationItemModelInfo.ShaderControler != null && vegetationItemModelInfo.ShaderControler.Settings.SampleWind) { MeshRenderer meshRenderer = vegetationItemModelInfo.WindSamplerMeshRendererList[cameraIndex]; if (meshRenderer) { meshRenderer.GetPropertyBlock(materialPropertyBlock); } } materialPropertyBlock.SetBuffer(_visibleShaderDataBufferID, visibleBuffer); materialPropertyBlock.SetBuffer(_indirectShaderDataBufferID, visibleBuffer); List <ComputeBuffer> argsBufferList = vegetationItemModelInfo.GetLODArgsBufferList(lodIndex, cameraIndex, shadows); //int[] data = new int[5]; //argsBufferList[0].GetData(data); //Debug.Log("Indirect - LOD" + lodIndex + ":" + data[1]); int submeshesToRender = Mathf.Min(mesh.subMeshCount, materials.Length); for (int i = 0; i <= submeshesToRender - 1; i++) { Graphics.DrawMeshInstancedIndirect(mesh, i, materials[i], cellBounds, argsBufferList[i], 0, materialPropertyBlock, shadowCastingMode, true, layer, selectedCamera, LightProbeUsage.Off); } }
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); }
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(); }