using System; using System.Collections.Generic; using System.Reflection; using AwesomeTechnologies.Utility.Culling; using UnityEngine; using UnityEngine.Profiling; using UnityEngine.Rendering; namespace AwesomeTechnologies.VegetationSystem { public static class GeometryUtilityAllocFree { public static Plane[] FrustrumPlanes = new Plane[6]; private static readonly Action InternalExtractPlanes = (Action)Delegate.CreateDelegate( typeof(Action), // ReSharper disable once AssignNullToNotNullAttribute typeof(GeometryUtility).GetMethod("Internal_ExtractPlanes", BindingFlags.Static | BindingFlags.NonPublic)); public static void CalculateFrustrumPlanes(Camera camera) { InternalExtractPlanes(FrustrumPlanes, camera.projectionMatrix * camera.worldToCameraMatrix); } } public partial class VegetationSystemPro { private void SetFrustumCullingPlanes(Camera selectedCamera) { GeometryUtilityAllocFree.CalculateFrustrumPlanes(selectedCamera); Vector4 cameraFrustumPlane0 = new Vector4(GeometryUtilityAllocFree.FrustrumPlanes[0].normal.x, GeometryUtilityAllocFree.FrustrumPlanes[0].normal.y, GeometryUtilityAllocFree.FrustrumPlanes[0].normal.z, GeometryUtilityAllocFree.FrustrumPlanes[0].distance); Vector4 cameraFrustumPlane1 = new Vector4(GeometryUtilityAllocFree.FrustrumPlanes[1].normal.x, GeometryUtilityAllocFree.FrustrumPlanes[1].normal.y, GeometryUtilityAllocFree.FrustrumPlanes[1].normal.z, GeometryUtilityAllocFree.FrustrumPlanes[1].distance); Vector4 cameraFrustumPlane2 = new Vector4(GeometryUtilityAllocFree.FrustrumPlanes[2].normal.x, GeometryUtilityAllocFree.FrustrumPlanes[2].normal.y, GeometryUtilityAllocFree.FrustrumPlanes[2].normal.z, GeometryUtilityAllocFree.FrustrumPlanes[2].distance); Vector4 cameraFrustumPlane3 = new Vector4(GeometryUtilityAllocFree.FrustrumPlanes[3].normal.x, GeometryUtilityAllocFree.FrustrumPlanes[3].normal.y, GeometryUtilityAllocFree.FrustrumPlanes[3].normal.z, GeometryUtilityAllocFree.FrustrumPlanes[3].distance); Vector4 cameraFrustumPlane4 = new Vector4(GeometryUtilityAllocFree.FrustrumPlanes[4].normal.x, GeometryUtilityAllocFree.FrustrumPlanes[4].normal.y, GeometryUtilityAllocFree.FrustrumPlanes[4].normal.z, GeometryUtilityAllocFree.FrustrumPlanes[4].distance); Vector4 cameraFrustumPlane5 = new Vector4(GeometryUtilityAllocFree.FrustrumPlanes[5].normal.x, GeometryUtilityAllocFree.FrustrumPlanes[5].normal.y, GeometryUtilityAllocFree.FrustrumPlanes[5].normal.z, GeometryUtilityAllocFree.FrustrumPlanes[5].distance); FrusumMatrixShader.SetVector(_cameraFrustumPlan0, cameraFrustumPlane0); FrusumMatrixShader.SetVector(_cameraFrustumPlan1, cameraFrustumPlane1); FrusumMatrixShader.SetVector(_cameraFrustumPlan2, cameraFrustumPlane2); FrusumMatrixShader.SetVector(_cameraFrustumPlan3, cameraFrustumPlane3); FrusumMatrixShader.SetVector(_cameraFrustumPlan4, cameraFrustumPlane4); FrusumMatrixShader.SetVector(_cameraFrustumPlan5, cameraFrustumPlane5); Vector3 worldSpaceCameraPosition = selectedCamera.transform.position; Vector4 worldSpaceCameraPos = new Vector4(worldSpaceCameraPosition.x, worldSpaceCameraPosition.y, worldSpaceCameraPosition.z, 1); //TODO change to ID on setVector FrusumMatrixShader.SetVector("_WorldSpaceCameraPos", worldSpaceCameraPos); } void SetupComputeShaders() { //_dummyMaskTexture = new Texture2D(2, 2); _dummyComputeBuffer = new ComputeBuffer(1, (16 * 4) + 16, ComputeBufferType.Default); // *2 MergeBufferShader = (ComputeShader)Resources.Load("MergeInstancedIndirectBuffers"); MergeBufferKernelHandle = MergeBufferShader.FindKernel("MergeInstancedIndirectBuffers"); FrusumMatrixShader = (ComputeShader)Resources.Load("GPUFrustumCulling"); FrustumKernelHandle = FrusumMatrixShader.FindKernel("GPUFrustumCulling"); _mergeBufferID = Shader.PropertyToID("MergeBuffer"); _floatingOriginOffsetID = Shader.PropertyToID("_FloatingOriginOffset"); _mergeSourceBuffer0ID = Shader.PropertyToID("MergeSourceBuffer0"); _mergeSourceBuffer1ID = Shader.PropertyToID("MergeSourceBuffer1"); _mergeSourceBuffer2ID = Shader.PropertyToID("MergeSourceBuffer2"); _mergeSourceBuffer3ID = Shader.PropertyToID("MergeSourceBuffer3"); _mergeSourceBuffer4ID = Shader.PropertyToID("MergeSourceBuffer4"); _mergeSourceBuffer5ID = Shader.PropertyToID("MergeSourceBuffer5"); _mergeSourceBuffer6ID = Shader.PropertyToID("MergeSourceBuffer6"); _mergeSourceBuffer7ID = Shader.PropertyToID("MergeSourceBuffer7"); _mergeSourceBuffer8ID = Shader.PropertyToID("MergeSourceBuffer8"); _mergeSourceBuffer9ID = Shader.PropertyToID("MergeSourceBuffer9"); _mergeSourceBuffer10ID = Shader.PropertyToID("MergeSourceBuffer10"); _mergeSourceBuffer11ID = Shader.PropertyToID("MergeSourceBuffer11"); _mergeSourceBuffer12ID = Shader.PropertyToID("MergeSourceBuffer12"); _mergeSourceBuffer13ID = Shader.PropertyToID("MergeSourceBuffer13"); _mergeSourceBuffer14ID = Shader.PropertyToID("MergeSourceBuffer14"); _mergeInstanceCount0ID = Shader.PropertyToID("MergeSourceBufferCount0"); _mergeInstanceCount1ID = Shader.PropertyToID("MergeSourceBufferCount1"); _mergeInstanceCount2ID = Shader.PropertyToID("MergeSourceBufferCount2"); _mergeInstanceCount3ID = Shader.PropertyToID("MergeSourceBufferCount3"); _mergeInstanceCount4ID = Shader.PropertyToID("MergeSourceBufferCount4"); _mergeInstanceCount5ID = Shader.PropertyToID("MergeSourceBufferCount5"); _mergeInstanceCount6ID = Shader.PropertyToID("MergeSourceBufferCount6"); _mergeInstanceCount7ID = Shader.PropertyToID("MergeSourceBufferCount7"); _mergeInstanceCount8ID = Shader.PropertyToID("MergeSourceBufferCount8"); _mergeInstanceCount9ID = Shader.PropertyToID("MergeSourceBufferCount9"); _mergeInstanceCount10ID = Shader.PropertyToID("MergeSourceBufferCount10"); _mergeInstanceCount11ID = Shader.PropertyToID("MergeSourceBufferCount11"); _mergeInstanceCount12ID = Shader.PropertyToID("MergeSourceBufferCount12"); _mergeInstanceCount13ID = Shader.PropertyToID("MergeSourceBufferCount13"); _mergeInstanceCount14ID = Shader.PropertyToID("MergeSourceBufferCount14"); _cameraFrustumPlan0 = Shader.PropertyToID("_VS_CameraFrustumPlane0"); _cameraFrustumPlan1 = Shader.PropertyToID("_VS_CameraFrustumPlane1"); _cameraFrustumPlan2 = Shader.PropertyToID("_VS_CameraFrustumPlane2"); _cameraFrustumPlan3 = Shader.PropertyToID("_VS_CameraFrustumPlane3"); _cameraFrustumPlan4 = Shader.PropertyToID("_VS_CameraFrustumPlane4"); _cameraFrustumPlan5 = Shader.PropertyToID("_VS_CameraFrustumPlane5"); _instanceCountID = Shader.PropertyToID("_InstanceCount"); _sourceBufferID = Shader.PropertyToID("SourceShaderDataBuffer"); _visibleBufferLod0ID = Shader.PropertyToID("VisibleBufferLOD0"); _visibleBufferLod1ID = Shader.PropertyToID("VisibleBufferLOD1"); _visibleBufferLod2ID = Shader.PropertyToID("VisibleBufferLOD2"); _visibleBufferLod3ID = Shader.PropertyToID("VisibleBufferLOD3"); _shadowBufferLod0ID = Shader.PropertyToID("ShadowBufferLOD0"); _shadowBufferLod1ID = Shader.PropertyToID("ShadowBufferLOD1"); _shadowBufferLod2ID = Shader.PropertyToID("ShadowBufferLOD2"); _shadowBufferLod3ID = Shader.PropertyToID("ShadowBufferLOD3"); _lightDirection = Shader.PropertyToID("_LightDirection"); _planeOrigin = Shader.PropertyToID("_PlaneOrigin"); _boundsSize = Shader.PropertyToID("_BoundsSize"); _cullFarStartID = Shader.PropertyToID("_CullFarStart"); _visibleShaderDataBufferID = Shader.PropertyToID("VisibleShaderDataBuffer"); _indirectShaderDataBufferID = Shader.PropertyToID("IndirectShaderDataBuffer"); _useLodsID = Shader.PropertyToID("UseLODs"); _noFrustumCullingID = Shader.PropertyToID("NoFrustumCulling"); _shadowCullingID = Shader.PropertyToID("ShadowCulling"); _boundingSphereRadiusID = Shader.PropertyToID("_BoundingSphereRadius"); _lod1Distance = Shader.PropertyToID("_LOD1Distance"); _lod2Distance = Shader.PropertyToID("_LOD2Distance"); _lod3Distance = Shader.PropertyToID("_LOD3Distance"); _lodFactor = Shader.PropertyToID("_LODFactor"); _lodBias = Shader.PropertyToID("_LODBias"); _lodFadeDistance = Shader.PropertyToID("_LODFadeDistance"); _lodCount = Shader.PropertyToID("_LODCount"); } void DisposeComputeShaders() { _dummyComputeBuffer?.Dispose(); } 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] .PotentialVisibleVegetationCellList[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 (VegetationRenderSettings.EnableSinglePassInstancedVR) { if (totalInstanceCount * 2 > cameraComputeBuffers.MergeBuffer.count) { cameraComputeBuffers.UpdateComputeBufferSize(totalInstanceCount * 2+ 5000); } } else { 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); float crossFadeDistance = 0; if (vegetationItemModelInfo.VegetationItemInfo.EnableCrossFade) { crossFadeDistance = VegetationRenderSettings.CrossFadeDistance; } #if USING_HDRP if (vegetationItemModelInfo.VegetationItemInfo.VegetationRenderMode == VegetationRenderMode.Instanced) { crossFadeDistance = 0; } #endif FrusumMatrixShader.SetFloat(_lodFadeDistance, crossFadeDistance); FrusumMatrixShader.SetInt(_lodCount, vegetationItemModelInfo.LODCount); FrusumMatrixShader.Dispatch(FrustumKernelHandle, threadGroupsFrustum, 1, 1); if (VegetationRenderSettings.EnableSinglePassInstancedVR) { 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(); } 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 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); } } 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); } } } }