Firstborn/Assets/AwesomeTechnologies/VegetationStudioPro/Runtime/VegetationSystemPro/VegetationSystemPro.cs

1305 lines
59 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
using AwesomeTechnologies.BillboardSystem;
using AwesomeTechnologies.Utility;
using AwesomeTechnologies.Utility.Culling;
using AwesomeTechnologies.Utility.Quadtree;
using AwesomeTechnologies.Vegetation.Masks;
using AwesomeTechnologies.Vegetation.PersistentStorage;
using AwesomeTechnologies.VegetationStudio;
using AwesomeTechnologies.VegetationSystem.Wind;
using Unity.Collections;
using Unity.Jobs;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.Rendering;
namespace AwesomeTechnologies.VegetationSystem
{
[AwesomeTechnologiesScriptOrder(100)]
[ExecuteInEditMode]
public partial class VegetationSystemPro : MonoBehaviour
{
public QuadTree<VegetationCell> VegetationCellQuadTree;
public QuadTree<BillboardCell> BillboardCellQuadTree;
[NonSerialized] public readonly List<VegetationCell> VegetationCellList = new List<VegetationCell>();
[NonSerialized] public readonly List<BillboardCell> BillboardCellList = new List<BillboardCell>();
[NonSerialized] public readonly List<VegetationCell> LoadedVegetationCellList = new List<VegetationCell>();
[NonSerialized]
public readonly List<VegetationCell> ProcessInstancedIndirectCellList = new List<VegetationCell>();
[NonSerialized] public readonly List<VegetationCell> CompactMemoryCellList = new List<VegetationCell>();
[NonSerialized] public readonly List<VegetationCell> PredictiveCellLoaderList = new List<VegetationCell>();
public VegetationCellSpawner VegetationCellSpawner = new VegetationCellSpawner();
public Bounds VegetationSystemBounds;
public bool AutomaticBoundsCalculation = true;
public PersistentVegetationStorage PersistentVegetationStorage;
public PredictiveCellLoader PredictiveCellLoader;
public int PredictiveCellLoaderCellsPerFrame = 1;
public bool LoadPotentialVegetationCells = true;
public int CurrentTabIndex;
public int VegetationPackageIndex;
public float SeaLevel;
public bool ExcludeSeaLevelCells;
public float VegetationCellSize = 100;
public float BillboardCellSize = 500;
public bool UseCacheCompacter = false;
[NonSerialized] public float AdditionalBoundingSphereRadius;
public int SelectedTextureMaskGroupTextureIndex;
public int SelectedTextureMaskGroupIndex;
public TextureMask DebugTextureMask;
[NonSerialized] public bool InitDone;
private JobHandle _prepareVegetationHandle;
public VegetationSettings VegetationSettings = new VegetationSettings();
public VegetationRenderSettings VegetationRenderSettings = new VegetationRenderSettings();
public EnvironmentSettings EnvironmentSettings = new EnvironmentSettings();
public List<VegetationStudioCamera> VegetationStudioCameraList = new List<VegetationStudioCamera>();
public bool ShowVegetationCells;
public bool ShowBillboardCells;
public bool ShowVisibleBillboardCells;
public bool ShowPotentialVisibleCells;
public bool ShowVisibleCells;
public bool ShowBiomeCells;
public bool ShowVegetationMaskCells;
public bool ShowHeatMap;
public bool ShowTerrainTextures = true;
public bool ShowLODDebug = false;
public bool ShowVegetationPackageGeneralSettingsMenu = true;
public bool ShowVegetationPackageNoiseMenu = true;
public bool ShowTerrainTextureRulesMenu = true;
public bool ShowTextureMaskRulesMenu = true;
public bool ShowVegetationMaskRulesMenu = true;
public bool ShowShaderSettingsMenu = true;
public bool ShowPositionMenu = true;
public bool ShowDistanceFalloffMenu = true;
public bool ShowBiomeRulesMenu = true;
public bool ShowConcaveLocationRulesMenu = true;
public bool ShowColliderRulesMenu = true;
public bool ShowBillboardsMenu = true;
public bool ShowVegetationItemSettingsMenu = true;
public bool ShowTerrainSourceSettingsMenu = true;
public bool ShowAddVegetationItemMenu = true;
public bool ShowLODMenu = true;
//public bool ForceBillboardCellLoadinComplete = false;
public List<IVegetationStudioTerrain> VegetationStudioTerrainList = new List<IVegetationStudioTerrain>();
public List<GameObject> VegetationStudioTerrainObjectList = new List<GameObject>();
public List<VegetationPackagePro> VegetationPackageProList = new List<VegetationPackagePro>();
public List<VegetationPackageProModelInfo> VegetationPackageProModelsList =
new List<VegetationPackageProModelInfo>();
public List<WindControllerSettings> WindControllerSettingsList = new List<WindControllerSettings>();
public delegate void MultiOnAddCameraDelegate(VegetationStudioCamera vegetationStudioCamera);
public MultiOnAddCameraDelegate OnAddCameraDelegate;
public delegate void MultiOnRemoveCameraDelegate(VegetationStudioCamera vegetationStudioCamera);
public MultiOnRemoveCameraDelegate OnRemoveCameraDelegate;
public delegate void MultiOnVegetationStudioRefreshDelegate(VegetationSystemPro vegetationSystemPro);
public MultiOnVegetationStudioRefreshDelegate OnRefreshVegetationSystemDelegate;
public MultiOnVegetationStudioRefreshDelegate OnRefreshColliderSystemDelegate;
public MultiOnVegetationStudioRefreshDelegate OnRefreshRuntimePrefabSpawnerDelegate;
public delegate void MultiOnClearCacheDelegate(VegetationSystemPro vegetationSystemPro);
public delegate void MultiOnClearCacheVegetationCellDelegate(VegetationSystemPro vegetationSystemPro,
VegetationCell vegetationCell);
public delegate void MultiOnClearCacheVegetationItemDelegate(VegetationSystemPro vegetationSystemPro,
int vegetationPackageIndex, int vegetationItemIndex);
public delegate void MultiOnClearCacheVegetationCellVegetationItemDelegate(
VegetationSystemPro vegetationSystemPro, VegetationCell vegetationCell, int vegetationPackageIndex,
int vegetationItemIndex);
public delegate void MultiOnVegetationCellSpawnedDelegate(VegetationCell vegetationCell);
public MultiOnVegetationCellSpawnedDelegate OnVegetationCellLoaded;
public MultiOnClearCacheDelegate OnClearCacheDelegate;
public MultiOnClearCacheVegetationItemDelegate OnClearCacheVegetationItemDelegate;
public MultiOnClearCacheVegetationCellDelegate OnClearCacheVegetationCellDelegate;
public MultiOnClearCacheVegetationCellVegetationItemDelegate OnClearCacheVegetationCellVegetatonItemDelegate;
public delegate void MultOnRenderCompleteDelegate(VegetationSystemPro vegetationSystemPro);
public MultOnRenderCompleteDelegate OnRenderCompleteDelegate;
[NonSerialized] private readonly List<IWindController> _windControllerList = new List<IWindController>();
public WindZone SelectedWindZone;
public float WindSpeedFactor = 1f;
public Light SunDirectionalLight;
// ReSharper disable once UnusedMember.Local
//private Texture _dummyMaskTexture;
private ComputeBuffer _dummyComputeBuffer;
public int FrustumKernelHandle;
//public int DistanceKernelHandle;
public ComputeShader FrusumMatrixShader;
private int _cameraFrustumPlan0;
private int _cameraFrustumPlan1;
private int _cameraFrustumPlan2;
private int _cameraFrustumPlan3;
private int _cameraFrustumPlan4;
private int _cameraFrustumPlan5;
public int MergeBufferKernelHandle;
public ComputeShader MergeBufferShader;
private int _floatingOriginOffsetID = -1;
private int _mergeBufferID = -1;
private int _mergeSourceBuffer0ID = -1;
private int _mergeSourceBuffer1ID = -1;
private int _mergeSourceBuffer2ID = -1;
private int _mergeSourceBuffer3ID = -1;
private int _mergeSourceBuffer4ID = -1;
private int _mergeSourceBuffer5ID = -1;
private int _mergeSourceBuffer6ID = -1;
private int _mergeSourceBuffer7ID = -1;
private int _mergeSourceBuffer8ID = -1;
private int _mergeSourceBuffer9ID = -1;
private int _mergeSourceBuffer10ID = -1;
private int _mergeSourceBuffer11ID = -1;
private int _mergeSourceBuffer12ID = -1;
private int _mergeSourceBuffer13ID = -1;
private int _mergeSourceBuffer14ID = -1;
private int _mergeInstanceCount0ID = -1;
private int _mergeInstanceCount1ID = -1;
private int _mergeInstanceCount2ID = -1;
private int _mergeInstanceCount3ID = -1;
private int _mergeInstanceCount4ID = -1;
private int _mergeInstanceCount5ID = -1;
private int _mergeInstanceCount6ID = -1;
private int _mergeInstanceCount7ID = -1;
private int _mergeInstanceCount8ID = -1;
private int _mergeInstanceCount9ID = -1;
private int _mergeInstanceCount10ID = -1;
private int _mergeInstanceCount11ID = -1;
private int _mergeInstanceCount12ID = -1;
private int _mergeInstanceCount13ID = -1;
private int _mergeInstanceCount14ID = -1;
private int _visibleBufferLod0ID = -1;
private int _visibleBufferLod1ID = -1;
private int _visibleBufferLod2ID = -1;
private int _visibleBufferLod3ID = -1;
private int _shadowBufferLod0ID = -1;
private int _shadowBufferLod1ID = -1;
private int _shadowBufferLod2ID = -1;
private int _shadowBufferLod3ID = -1;
private int _sourceBufferID = -1;
private int _instanceCountID = -1;
private int _boundingSphereRadiusID = -1;
private int _useLodsID = -1;
private int _noFrustumCullingID = -1;
private int _shadowCullingID = -1;
private int _cullFarStartID;
private int _visibleShaderDataBufferID;
private int _indirectShaderDataBufferID;
private int _cameraPositionID;
private int _cullDistanceID;
private int _farCullDistanceID;
private static readonly int _nearFadeDistanceID = Shader.PropertyToID("_NearFadeDistance");
private int _unityLODFadeID;
private int _lod1Distance = -1;
private int _lod2Distance = -1;
private int _lod3Distance = -1;
private int _lightDirection = -1;
private int _planeOrigin = -1;
private int _boundsSize = -1;
private int _lodFactor = -1;
private int _lodBias = -1;
private int _lodFadeDistance = -1;
private int _lodCount = -1;
private readonly List<VegetationCell> _hasBufferList = new List<VegetationCell>();
private readonly Matrix4x4[] _renderArray = new Matrix4x4[1000];
private readonly float[] _renderingLayerArray = new float[1000];
private readonly Vector4[] _renderLodFadeArray = new Vector4[1000];
//private Vector4[] _lodFadeSingleArray = new Vector4[1];
//Floating origin variables
public Transform FloatingOriginAnchor;
public Vector3 FloatingOriginOffset;
public Vector3 FloatingOriginStartPosition;
private static readonly int UnityRenderingLayerID = Shader.PropertyToID("unity_RenderingLayer");
public Vector3 VegetationSystemPosition
{
get
{
Vector3 position = VegetationSystemBounds.center - VegetationSystemBounds.extents;
position.y = 0;
return position;
}
}
public void DetectPersistentVegetationStorage()
{
if (!PersistentVegetationStorage)
{
PersistentVegetationStorage = GetComponent<PersistentVegetationStorage>();
}
}
// ReSharper disable once UnusedMember.Local
void Reset()
{
AutoSelectCamera();
FindWindZone();
FindDirectionalLight();
DetectPersistentVegetationStorage();
}
void FindDirectionalLight()
{
if (SunDirectionalLight) return;
Light selectedLight = null;
float intensity = float.MinValue;
Light[] lights = FindObjectsOfType<Light>();
for (int i = 0; i <= lights.Length - 1; i++)
{
if (lights[i].type == LightType.Directional)
{
if (lights[i].intensity > intensity)
{
intensity = lights[i].intensity;
selectedLight = lights[i];
}
}
}
SunDirectionalLight = selectedLight;
}
void AutoSelectCamera()
{
Camera selectedCamera = Camera.main;
if (selectedCamera == null)
{
Camera[] cameras = FindObjectsOfType<Camera>();
for (int i = 0; i <= cameras.Length - 1; i++)
{
if (cameras[i].gameObject.name.Contains("Main Camera") ||
cameras[i].gameObject.name.Contains("MainCamera"))
{
selectedCamera = cameras[i];
break;
}
}
}
AddCamera(selectedCamera);
}
public void RefreshVegetationSystem()
{
SetupVegetationSystem();
}
public void RefreshColliderSystem()
{
OnRefreshColliderSystemDelegate?.Invoke(this);
}
public void RefreshRuntimePrefabSpawner()
{
OnRefreshRuntimePrefabSpawnerDelegate?.Invoke(this);
}
void SetupVegetationSystem()
{
CompleteCellLoading();
ProcessInstancedIndirectCellList.Clear();
DisposeVegetationStudioCameras();
DisposeVegetationCells();
DisposeBillboardCells();
if (VegetationSystemBounds.size.magnitude < 1) return;
SetupWindSamplers();
SetupVegetationItemModels();
RefreshVegetationStudioTerrains();
CreateVegetationCells();
CreateBillboardCells();
SetVegetationStudioCamerasDirty();
RefreshMaterials();
OnRefreshVegetationSystemDelegate?.Invoke(this);
}
public void CompleteCellLoading()
{
_prepareVegetationHandle.Complete();
}
// ReSharper disable once UnusedMember.Local
void OnEnable()
{
VegetationStudioManager.RegisterVegetationSystem(this);
DetectPersistentVegetationStorage();
FindDirectionalLight();
EnableEditorApi();
LoadSettingsFromQualityManager();
SetupPredictiveCellLoader();
SetupVegetationCellSpawner();
SetupSceneviewCamera();
SetupFloatingOrigin();
SetupComputeShaders();
SetupBillboardShaderIDs();
SetupInstancedRenderMaterialPropertiesIDs();
SetupRenderingLayerData();
SetupVegetationSystem();
VegetationCellSpawner.Init();
SetupWind();
InitDone = true;
}
public void SetupRenderingLayerData()
{
int flags = VegetationRenderSettings.RenderingLayerMask;
float flagsFloat = BitConverter.ToSingle(System.BitConverter.GetBytes(flags), 0);
for (int i = 0; i < _renderingLayerArray.Length; i++)
{
_renderingLayerArray[i] = flagsFloat;
}
Shader.SetGlobalFloat("VSPRenderingLayerMask", flagsFloat);
}
void LoadSettingsFromQualityManager()
{
if (!Application.isPlaying)
{
return;
}
QualityManager qualityManager = GetComponent<QualityManager>();
if (qualityManager)
{
qualityManager.SetQualityLevel(false);
}
}
void EnableEditorApi()
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
SceneViewDetector.OnSceneViewTransformChangeDelegate += OnSceneviewTransformChanged;
}
#endif
}
void DisableEditorApi()
{
#if UNITY_EDITOR
if (!Application.isPlaying)
{
// ReSharper disable once DelegateSubtraction
SceneViewDetector.OnSceneViewTransformChangeDelegate -= OnSceneviewTransformChanged;
}
#endif
}
void OnSceneviewTransformChanged(Camera currentCamera)
{
#if UNITY_EDITOR
EditorUtility.SetDirty(this);
#endif
}
void SetupSceneviewCamera()
{
for (int i = VegetationStudioCameraList.Count - 1; i >= 0; i--)
{
if (VegetationStudioCameraList[i].VegetationStudioCameraType == VegetationStudioCameraType.SceneView ||
VegetationStudioCameraList[i].SelectedCamera == null)
{
RemoveVegetationStudioCamera(VegetationStudioCameraList[i]);
}
}
if (!Application.isPlaying)
{
VegetationStudioCamera sceneviewCamera =
new VegetationStudioCamera(VegetationStudioCameraType.SceneView)
{
CameraCullingMode = CameraCullingMode.Frustum,
RenderDirectToCamera = false,
VegetationSystemPro = this
};
AddVegetationStudioCamera(sceneviewCamera);
//VegetationStudioCameraList.Add(sceneviewCamera);
}
if (Application.isPlaying && VegetationStudioCameraList.Count == 0)
{
AutoSelectCamera();
}
}
void SetupFloatingOrigin()
{
Transform anchor = GetFloatingOriginAnchor();
FloatingOriginStartPosition = anchor.position;
}
void UpdateFloatingOrigin()
{
if (Application.isPlaying)
{
Transform anchor = GetFloatingOriginAnchor();
FloatingOriginOffset = anchor.transform.position - FloatingOriginStartPosition;
}
else
{
FloatingOriginOffset = Vector3.zero;
}
}
Transform GetFloatingOriginAnchor()
{
if (FloatingOriginAnchor) return FloatingOriginAnchor;
return transform;
}
// void PrepareRenderLists()
// {
// for (int i = 0; i <= VegetationStudioCameraList.Count - 1; i++)
// {
// VegetationStudioCameraList[i].PrepareRenderLists(VegetationPackageProList);
// }
// }
// ReSharper disable once UnusedMember.Local
void Update()
{
if (!InitDone) return;
UpdateFloatingOrigin();
if (VegetationCellList.Count <= 0) return;
JobHandle cullingHandle = default(JobHandle);
for (int i = 0; i <= VegetationStudioCameraList.Count - 1; i++)
{
VegetationStudioCameraList[i].SetFloatingOriginOffset(FloatingOriginOffset);
VegetationStudioCameraList[i].PreCullVegetation(false);
VegetationStudioCameraList[i].PrepareRenderLists(VegetationPackageProList);
}
//PrepareRenderLists();
for (int i = 0; i <= VegetationStudioCameraList.Count - 1; i++)
{
if (!VegetationStudioCameraList[i].Enabled) continue;
cullingHandle = VegetationStudioCameraList[i].ScheduleCullVegetationJob(cullingHandle);
}
Profiler.BeginSample("VegetationCell culling");
cullingHandle.Complete();
Profiler.EndSample();
Profiler.BeginSample("Process culling events");
for (int i = 0; i <= VegetationStudioCameraList.Count - 1; i++)
{
if (!VegetationStudioCameraList[i].Enabled) continue;
VegetationStudioCameraList[i].ProcessEvents();
}
Profiler.EndSample();
VerifySplatmapAccess();
Profiler.BeginSample("Prepare cell loading jobs");
VegetationCellSpawner.CellJobHandleList.Clear();
float worldspaceMinHeight = VegetationSystemBounds.center.y -
VegetationSystemBounds.extents.y;
float worldspaceSeaLevel = worldspaceMinHeight + SeaLevel;
VegetationCellSpawner.WorldspaceSeaLevel = worldspaceSeaLevel;
PredictiveCellLoaderList.Clear();
PredictiveCellLoader.GetCellsToLoad(PredictiveCellLoaderList);
for (int i = 0; i <= PredictiveCellLoaderList.Count - 1; i++)
{
VegetationCell vegetationCell = PredictiveCellLoaderList[i];
bool hasData = vegetationCell.LoadedDistanceBand != 99;
bool hasInstancedIndirect;
JobHandle vegetationCellHandle =
VegetationCellSpawner.SpawnVegetationCell(vegetationCell, 0, out hasInstancedIndirect, false);
OnVegetationCellLoaded?.Invoke(vegetationCell);
if (!hasData)
{
if (!LoadedVegetationCellList.Contains(vegetationCell))
{
LoadedVegetationCellList.Add(vegetationCell);
}
}
if (hasInstancedIndirect)
{
ProcessInstancedIndirectCellList.Add(vegetationCell);
}
VegetationCellSpawner.CellJobHandleList.Add(vegetationCellHandle);
}
for (int i = 0; i <= VegetationStudioCameraList.Count - 1; i++)
{
if (!VegetationStudioCameraList[i].Enabled) continue;
for (int j = 0; j <= VegetationStudioCameraList[i].JobCullingGroup.VisibleCellIndexList.Length - 1; j++)
{
int potentialVisibleCellIndex =
VegetationStudioCameraList[i].JobCullingGroup.VisibleCellIndexList[j];
VegetationCell vegetationCell = VegetationStudioCameraList[i]
.PotentialVisibleVegetationCellList[potentialVisibleCellIndex];
BoundingSphereInfo boundingSphereInfo =
VegetationStudioCameraList[i].GetBoundingSphereInfo(potentialVisibleCellIndex);
if (vegetationCell.LoadedDistanceBand <= boundingSphereInfo.CurrentDistanceBand) continue;
// if (!Application.isPlaying && !vegetationCell.Prepared)
// {
// VegetationCellSpawner.PrepareVegetationCell(vegetationCell);
// }
// ReSharper disable once InlineOutVariableDeclaration
bool hasInstancedIndirect;
JobHandle vegetationCellHandle = VegetationCellSpawner.SpawnVegetationCell(vegetationCell,
boundingSphereInfo.CurrentDistanceBand, out hasInstancedIndirect, false);
OnVegetationCellLoaded?.Invoke(vegetationCell);
LoadedVegetationCellList.Add(vegetationCell);
if (hasInstancedIndirect)
{
ProcessInstancedIndirectCellList.Add(vegetationCell);
}
VegetationCellSpawner.CellJobHandleList.Add(vegetationCellHandle);
}
}
_prepareVegetationHandle = JobHandle.CombineDependencies(VegetationCellSpawner.CellJobHandleList);
Profiler.EndSample();
JobHandle.ScheduleBatchedJobs();
Profiler.BeginSample("Prepare render list jobs");
float lodBias = QualitySettings.lodBias * VegetationSettings.LODDistanceFactor;
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);
bool isPlaying = Application.isPlaying;
VegetationCellSpawner.CellJobHandleList.Clear();
for (int i = 0; i <= VegetationStudioCameraList.Count - 1; i++)
{
if (!VegetationStudioCameraList[i].Enabled) continue;
if (VegetationStudioCameraList[i].RenderBillboardsOnly) continue;
for (int j = 0; j <= VegetationPackageProList.Count - 1; j++)
{
for (int k = 0; k <= VegetationPackageProList[j].VegetationInfoList.Count - 1; k++)
{
NativeList<MatrixInstance> vegetationItemMatrixList =
VegetationStudioCameraList[i].VegetationStudioCameraRenderList[j]
.VegetationItemMergeMatrixList[k];
vegetationItemMatrixList.Clear();
VegetationItemModelInfo vegetationItemModelInfo =
VegetationPackageProModelsList[j].VegetationItemModelList[k];
bool useInstancedIndirect = VegetationRenderSettings.UseInstancedIndirect();
if (useInstancedIndirect && vegetationItemModelInfo.VegetationItemInfo.VegetationRenderMode ==
VegetationRenderMode.InstancedIndirect) continue;
//if (isPlaying && vegetationItemModelInfo.VegetationItemInfo.VegetationRenderMode ==
// VegetationRenderMode.InstancedIndirect) continue;
//if (!vegetationItemModelInfo.VegetationItemInfo.EnableRuntimeSpawn) continue;
JobHandle vegetationItemMergeJobHandle = _prepareVegetationHandle;
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 (vegetationItemModelInfo.VegetationItemInfo.VegetationType == VegetationType.Objects)
// {
// vegetationItemDistanceBand = 0;
// }
if (boundingSphereInfo.CurrentDistanceBand > vegetationItemDistanceBand) continue;
MergeCellInstancesJob mergeCellInstancesJob =
new MergeCellInstancesJob
{
OutputNativeList = vegetationItemMatrixList,
InputNativeList = vegetationCell.VegetationPackageInstancesList[j]
.VegetationItemMatrixList[k]
};
Profiler.BeginSample("Schedule");
vegetationItemMergeJobHandle = mergeCellInstancesJob.Schedule(vegetationItemMergeJobHandle);
Profiler.EndSample();
}
NativeList<Matrix4x4> lod0MatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD0MatrixList[k];
NativeList<Matrix4x4> lod1MatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD1MatrixList[k];
NativeList<Matrix4x4> lod2MatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD2MatrixList[k];
NativeList<Matrix4x4> lod3MatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD3MatrixList[k];
NativeList<Matrix4x4> lod0ShadowMatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD0ShadowMatrixList[k];
NativeList<Matrix4x4> lod1ShadowMatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD1ShadowMatrixList[k];
NativeList<Matrix4x4> lod2ShadowMatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD2ShadowMatrixList[k];
NativeList<Matrix4x4> lod3ShadowMatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD3ShadowMatrixList[k];
NativeList<Vector4> lod0FadeList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD0LodFadeList[k];
NativeList<Vector4> lod1FadeList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD1LodFadeList[k];
NativeList<Vector4> lod2FadeList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD2LodFadeList[k];
NativeList<Vector4> lod3FadeList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD3LodFadeList[k];
lod0MatrixList.Clear();
lod1MatrixList.Clear();
lod2MatrixList.Clear();
lod3MatrixList.Clear();
lod0ShadowMatrixList.Clear();
lod1ShadowMatrixList.Clear();
lod2ShadowMatrixList.Clear();
lod3ShadowMatrixList.Clear();
lod0FadeList.Clear();
lod1FadeList.Clear();
lod2FadeList.Clear();
lod3FadeList.Clear();
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(vegetationItemModelInfo.VegetationItemInfo
.VegetationType);
bool useShadowCulling = shadowCulling && shadowCastingMode == ShadowCastingMode.On;
useShadowCulling = useShadowCulling && vegetationItemModelInfo.DistanceBand == 1;
if (VegetationStudioCameraList[i].SelectedCamera == null)
{
VegetationCellSpawner.CellJobHandleList.Add(vegetationItemMergeJobHandle);
continue;
}
float crossFadeDistance = 0;
if (vegetationItemModelInfo.VegetationItemInfo.EnableCrossFade)
{
crossFadeDistance = VegetationRenderSettings.CrossFadeDistance;
}
#if USING_HDRP
if (vegetationItemModelInfo.VegetationItemInfo.VegetationRenderMode ==
VegetationRenderMode.Instanced)
{
crossFadeDistance = 0;
}
#endif
VegetationItemLODSplitAndFrustumCullingJob lodJob =
new VegetationItemLODSplitAndFrustumCullingJob
{
BoundingSphereRadius = vegetationItemModelInfo.BoundingSphereRadius,
BoundsSize = vegetationItemModelInfo.VegetationItemInfo.Bounds.size,
VegetationItemDistanceBand = vegetationItemModelInfo.DistanceBand,
VegetationItemMatrixList = vegetationItemMatrixList,
VegetationItemLOD0MatrixList = lod0MatrixList,
VegetationItemLOD1MatrixList = lod1MatrixList,
VegetationItemLOD2MatrixList = lod2MatrixList,
VegetationItemLOD3MatrixList = lod3MatrixList,
VegetationItemLOD0ShadowMatrixList = lod0ShadowMatrixList,
VegetationItemLOD1ShadowMatrixList = lod1ShadowMatrixList,
VegetationItemLOD2ShadowMatrixList = lod2ShadowMatrixList,
VegetationItemLOD3ShadowMatrixList = lod3ShadowMatrixList,
LOD0FadeList = lod0FadeList,
LOD1FadeList = lod1FadeList,
LOD2FadeList = lod2FadeList,
LOD3FadeList = lod3FadeList,
LightDirection = sunLightDirection,
ShadowCulling = useShadowCulling,
PlaneOrigin = planeOrigin,
FrustumPlanes = VegetationStudioCameraList[i].JobCullingGroup.FrustumPlanes,
CameraPosition = VegetationStudioCameraList[i].SelectedCamera.transform.position,
NoFrustumCulling = VegetationStudioCameraList[i].CameraCullingMode ==
CameraCullingMode.Complete360,
CullDistance = vegetationItemCullDistance,
LOD1Distance = vegetationItemModelInfo.LOD1Distance,
LOD2Distance = vegetationItemModelInfo.LOD2Distance,
LOD3Distance = vegetationItemModelInfo.LOD3Distance,
LODFactor = vegetationItemModelInfo.VegetationItemInfo.LODFactor,
LODBias = lodBias,
LODCount = vegetationItemModelInfo.LODCount,
LODFadeDistance = crossFadeDistance,
LODFadePercentage = vegetationItemModelInfo.LODFadePercentage,
LODFadeCrossfade = vegetationItemModelInfo.LODFadeCrossfade,
FloatingOriginOffset = FloatingOriginOffset
};
vegetationItemMergeJobHandle = lodJob.Schedule(vegetationItemMergeJobHandle);
VegetationCellSpawner.CellJobHandleList.Add(vegetationItemMergeJobHandle);
//#if UNITY_EDITOR
// if (JobsUtility.JobDebuggerEnabled) vegetationItemMergeJobHandle.Complete();
//#endif
}
}
}
Profiler.EndSample();
if (VegetationCellSpawner.CellJobHandleList.Length > 0)
{
_prepareVegetationHandle = JobHandle.CombineDependencies(VegetationCellSpawner.CellJobHandleList);
}
JobHandle.ScheduleBatchedJobs();
//TODO add merge vegetation instances for buillboards here
}
void SetShadowMapVariables()
{
if (SunDirectionalLight)
{
Vector3 sundirection = -SunDirectionalLight.transform.forward * 2.5f;
Vector4 gVsSunDirection = new Vector4(sundirection.x, sundirection.y, sundirection.z,
SunDirectionalLight.intensity);
Shader.SetGlobalVector("gVSSunDirection", gVsSunDirection);
Shader.SetGlobalVector("gVSSunSettings",
new Vector4(SunDirectionalLight.shadowStrength, SunDirectionalLight.shadowBias, 0, 0));
}
else
{
Shader.SetGlobalVector("gVSSunDirection", Vector4.zero);
Shader.SetGlobalVector("gVSSunSettings", new Vector4(0, 0, 0, 0));
}
}
void InitGlobalShaderProperties()
{
float minVegetationDistance = Mathf.Clamp(VegetationSettings.GetVegetationDistance(), 20,
VegetationSettings.GetVegetationDistance() - 20);
Shader.SetGlobalVector("_VSGrassFade", new Vector4(minVegetationDistance, 20, 0, 0));
Shader.SetGlobalVector("_VSShadowMapFadeScale", new Vector4(QualitySettings.shadowDistance - 30, 20, 1, 1));
}
// ReSharper disable once UnusedMember.Local
void LateUpdate()
{
if (!InitDone) return;
UpdateWind();
SetShadowMapVariables();
InitGlobalShaderProperties();
Profiler.BeginSample("Complete spawning jobs");
_prepareVegetationHandle.Complete();
Profiler.EndSample();
VerifySplatmapAccess();
LoadBillboardCells();
RenderBillboardCells();
JobHandle prepareInstancedIndirectHandle = default(JobHandle);
bool useInstancedIndirect = VegetationRenderSettings.UseInstancedIndirect();
if (Application.isPlaying && useInstancedIndirect)
{
prepareInstancedIndirectHandle = PrepareInstancedIndirectSetupJobs();
}
RenderInstancedVegetation();
if (Application.isPlaying && useInstancedIndirect)
{
prepareInstancedIndirectHandle.Complete();
SetupInstancedIndirectComputeBuffers();
RenderInstancedIndirectVegetation();
}
DisposeTemporaryTerrainMemory();
ReturnVegetationCellTemporaryMemory();
if (UseCacheCompacter)
{
CompactCache();
}
OnRenderCompleteDelegate?.Invoke(this);
}
JobHandle PrepareInstancedIndirectSetupJobs()
{
VegetationCellSpawner.CellJobHandleList.Clear();
for (int i = 0; i <= ProcessInstancedIndirectCellList.Count - 1; i++)
{
VegetationCell vegetationCell = ProcessInstancedIndirectCellList[i];
for (int j = 0; j <= vegetationCell.VegetationPackageInstancesList.Count - 1; j++)
{
for (int k = 0;
k <= vegetationCell.VegetationPackageInstancesList[j].VegetationItemMatrixList.Count - 1;
k++)
{
VegetationItemInfoPro vegetationItemInfoPro = VegetationPackageProList[j].VegetationInfoList[k];
IndirectInstanceInfo indirectInstanceInfo = vegetationCell.VegetationPackageInstancesList[j]
.VegetationItemInstancedIndirectInstanceList[k];
VegetationItemModelInfo vegetationItemModelInfo =
VegetationPackageProModelsList[j].VegetationItemModelList[k];
bool hasTreesLoaded = vegetationCell.LoadedBillboards && vegetationItemInfoPro.UseBillboards &&
vegetationItemInfoPro.VegetationType == VegetationType.Tree;
if (vegetationItemModelInfo.DistanceBand < vegetationCell.LoadedDistanceBand &&
!hasTreesLoaded) continue;
if (vegetationItemInfoPro.VegetationRenderMode == VegetationRenderMode.InstancedIndirect &&
!indirectInstanceInfo.Created)
{
NativeArray<MatrixInstance> vegetationItemMatrixList =
vegetationCell.VegetationPackageInstancesList[j].VegetationItemMatrixList[k];
indirectInstanceInfo.InstancedIndirectInstanceList =
new NativeArray<InstancedIndirectInstance>(vegetationItemMatrixList.Length,
Allocator.Persistent);
indirectInstanceInfo.Created = true;
CreateInstancedIndirectInstancesJob createInstancedIndirectInstancesJob =
new CreateInstancedIndirectInstancesJob
{
InstanceList = vegetationItemMatrixList,
IndirectInstanceList = indirectInstanceInfo.InstancedIndirectInstanceList
};
JobHandle handle = createInstancedIndirectInstancesJob.Schedule(
indirectInstanceInfo.InstancedIndirectInstanceList.Length, 32);
VegetationCellSpawner.CellJobHandleList.Add(handle);
}
}
}
}
JobHandle processHandle = JobHandle.CombineDependencies(VegetationCellSpawner.CellJobHandleList);
VegetationCellSpawner.CellJobHandleList.Clear();
JobHandle.ScheduleBatchedJobs();
return processHandle;
}
void SetupInstancedIndirectComputeBuffers()
{
bool useInstancedIndirect = VegetationRenderSettings.UseInstancedIndirect();
if (!useInstancedIndirect) return;
Profiler.BeginSample("Update compute buffers");
for (int i = 0; i <= ProcessInstancedIndirectCellList.Count - 1; i++)
{
VegetationCell vegetationCell = ProcessInstancedIndirectCellList[i];
for (int j = 0; j <= vegetationCell.VegetationPackageInstancesList.Count - 1; j++)
{
for (int k = 0;
k <= vegetationCell.VegetationPackageInstancesList[j].VegetationItemMatrixList.Count - 1;
k++)
{
VegetationItemInfoPro vegetationItemInfoPro = VegetationPackageProList[j].VegetationInfoList[k];
IndirectInstanceInfo indirectInstanceInfo = vegetationCell.VegetationPackageInstancesList[j]
.VegetationItemInstancedIndirectInstanceList[k];
ComputeBufferInfo computeBufferInfo = vegetationCell.VegetationPackageInstancesList[j]
.VegetationItemComputeBufferList[k];
VegetationItemModelInfo vegetationItemModelInfo =
VegetationPackageProModelsList[j].VegetationItemModelList[k];
//if (vegetationItemModelInfo.DistanceBand < vegetationCell.LoadedDistanceBand) continue;
bool hasTreesLoaded = vegetationCell.LoadedBillboards && vegetationItemInfoPro.UseBillboards &&
vegetationItemInfoPro.VegetationType == VegetationType.Tree;
if (vegetationItemModelInfo.DistanceBand < vegetationCell.LoadedDistanceBand &&
!hasTreesLoaded) continue;
if (vegetationItemInfoPro.VegetationRenderMode == VegetationRenderMode.InstancedIndirect &&
!computeBufferInfo.Created)
{
int length = indirectInstanceInfo.InstancedIndirectInstanceList.Length;
if (length == 0) length = 1;
//TODO handle 0 length cells better
computeBufferInfo.ComputeBuffer = new ComputeBuffer(length, 16 * 4 + 4 * 4); //*2
computeBufferInfo.ComputeBuffer.SetData(indirectInstanceInfo.InstancedIndirectInstanceList);
computeBufferInfo.Created = true;
//TODO clear indirectInstanceInfo.InstancedIndirectInstanceList; //might be needed if unity clears buffers
}
}
}
}
ProcessInstancedIndirectCellList.Clear();
Profiler.EndSample();
}
void RenderInstancedIndirectVegetation()
{
DrawCellsIndirectComputeShader();
}
void DisposeTemporaryTerrainMemory()
{
for (int i = 0; i <= VegetationStudioTerrainList.Count - 1; i++)
{
VegetationStudioTerrainList[i].DisposeTemporaryMemory();
}
}
//public List<Matrix4x4> RenderList = new List<Matrix4x4>();
// private readonly byte[] _renderbyteArray = new byte[1000 * 16 * 4];
// private readonly byte[] _renderbyteLodFadeArray = new byte[1000 * 4 * 4];
void RenderInstancedVegetation()
{
Profiler.BeginSample("Draw instanced vegetation");
bool isPlaying = Application.isPlaying;
for (int i = 0; i <= VegetationStudioCameraList.Count - 1; i++)
{
if (!VegetationStudioCameraList[i].Enabled) continue;
if (VegetationStudioCameraList[i].RenderBillboardsOnly) continue;
var targetCamera = VegetationStudioCameraList[i].RenderDirectToCamera
? VegetationStudioCameraList[i].SelectedCamera
: null;
if (!Application.isPlaying) targetCamera = null;
for (int j = 0; j <= VegetationPackageProList.Count - 1; j++)
{
for (int k = 0; k <= VegetationPackageProList[j].VegetationInfoList.Count - 1; k++)
{
VegetationItemInfoPro vegetationItemInfoPro = VegetationPackageProList[j].VegetationInfoList[k];
bool useInstancedIndirect = VegetationRenderSettings.UseInstancedIndirect();
if (useInstancedIndirect && vegetationItemInfoPro.VegetationRenderMode ==
VegetationRenderMode.InstancedIndirect) continue;
//if (isPlaying && vegetationItemInfoPro.VegetationRenderMode == VegetationRenderMode.InstancedIndirect) continue;
//if (!vegetationItemInfoPro.EnableRuntimeSpawn) continue;
ShadowCastingMode shadowCastingMode =
VegetationSettings.GetShadowCastingMode(vegetationItemInfoPro.VegetationType);
if (vegetationItemInfoPro.DisableShadows)
{
shadowCastingMode = ShadowCastingMode.Off;
}
LayerMask layer = VegetationSettings.GetLayer(vegetationItemInfoPro.VegetationType);
VegetationItemModelInfo vegetationItemModelInfo =
VegetationPackageProModelsList[j].VegetationItemModelList[k];
NativeList<Matrix4x4> lod0MatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD0MatrixList[k];
NativeList<Matrix4x4> lod1MatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD1MatrixList[k];
NativeList<Matrix4x4> lod2MatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD2MatrixList[k];
NativeList<Matrix4x4> lod3MatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD3MatrixList[k];
NativeList<Vector4> lod0Fadeist = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD0LodFadeList[k];
NativeList<Vector4> lod1Fadeist = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD1LodFadeList[k];
NativeList<Vector4> lod2Fadeist = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD2LodFadeList[k];
NativeList<Vector4> lod3Fadeist = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD3LodFadeList[k];
if (vegetationItemInfoPro.VegetationRenderMode == VegetationRenderMode.Normal)
{
RenderVegetationItemLODDrawMesh(lod0MatrixList, lod0Fadeist, vegetationItemModelInfo, 0,
targetCamera, i, shadowCastingMode, layer);
RenderVegetationItemLODDrawMesh(lod1MatrixList, lod1Fadeist, vegetationItemModelInfo, 1,
targetCamera, i, shadowCastingMode, layer);
RenderVegetationItemLODDrawMesh(lod2MatrixList, lod2Fadeist, vegetationItemModelInfo, 2,
targetCamera, i, shadowCastingMode, layer);
RenderVegetationItemLODDrawMesh(lod3MatrixList, lod3Fadeist, vegetationItemModelInfo, 3,
targetCamera, i, shadowCastingMode, layer);
}
else
{
RenderVegetationItemLOD(lod0MatrixList, lod0Fadeist, vegetationItemModelInfo, 0,
targetCamera, i, shadowCastingMode, layer);
RenderVegetationItemLOD(lod1MatrixList, lod1Fadeist, vegetationItemModelInfo, 1,
targetCamera, i, shadowCastingMode, layer);
RenderVegetationItemLOD(lod2MatrixList, lod2Fadeist, vegetationItemModelInfo, 2,
targetCamera, i, shadowCastingMode, layer);
RenderVegetationItemLOD(lod3MatrixList, lod3Fadeist, vegetationItemModelInfo, 3,
targetCamera, i, shadowCastingMode, layer);
}
if (shadowCastingMode == ShadowCastingMode.On)
{
NativeList<Matrix4x4> lod0ShadowMatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD0ShadowMatrixList[k];
NativeList<Matrix4x4> lod1ShadowMatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD1ShadowMatrixList[k];
NativeList<Matrix4x4> lod2ShadowMatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD2ShadowMatrixList[k];
NativeList<Matrix4x4> lod3ShadowMatrixList = VegetationStudioCameraList[i]
.VegetationStudioCameraRenderList[j].VegetationItemLOD3ShadowMatrixList[k];
if (vegetationItemInfoPro.VegetationRenderMode == VegetationRenderMode.Normal)
{
RenderVegetationItemLODDrawMesh(lod0ShadowMatrixList, lod0Fadeist,
vegetationItemModelInfo, 0, targetCamera, i, ShadowCastingMode.ShadowsOnly, layer);
RenderVegetationItemLODDrawMesh(lod1ShadowMatrixList, lod1Fadeist,
vegetationItemModelInfo, 1, targetCamera, i, ShadowCastingMode.ShadowsOnly, layer);
RenderVegetationItemLODDrawMesh(lod2ShadowMatrixList, lod2Fadeist,
vegetationItemModelInfo, 2, targetCamera, i, ShadowCastingMode.ShadowsOnly, layer);
RenderVegetationItemLODDrawMesh(lod3ShadowMatrixList, lod3Fadeist,
vegetationItemModelInfo, 3, targetCamera, i, ShadowCastingMode.ShadowsOnly, layer);
}
else
{
RenderVegetationItemLOD(lod0ShadowMatrixList, lod0Fadeist, vegetationItemModelInfo, 0,
targetCamera, i, ShadowCastingMode.ShadowsOnly, layer);
RenderVegetationItemLOD(lod1ShadowMatrixList, lod1Fadeist, vegetationItemModelInfo, 1,
targetCamera, i, ShadowCastingMode.ShadowsOnly, layer);
RenderVegetationItemLOD(lod2ShadowMatrixList, lod2Fadeist, vegetationItemModelInfo, 2,
targetCamera, i, ShadowCastingMode.ShadowsOnly, layer);
RenderVegetationItemLOD(lod3ShadowMatrixList, lod3Fadeist, vegetationItemModelInfo, 3,
targetCamera, i, ShadowCastingMode.ShadowsOnly, layer);
}
}
}
}
}
Profiler.EndSample();
}
void SetupInstancedRenderMaterialPropertiesIDs()
{
_unityLODFadeID = Shader.PropertyToID("unity_LODFade");
}
//float[] _singleFloatArray = new float[1];
void RenderVegetationItemLODDrawMesh(NativeList<Matrix4x4> matrixList, NativeList<Vector4> lodFadeList,
VegetationItemModelInfo vegetationItemModelInfo, int lodIndex, Camera targetCamera, int cameraIndex,
ShadowCastingMode shadowCastingMode, LayerMask layer)
{
if (matrixList.Length == 0) return;
if (lodIndex >= vegetationItemModelInfo.LODCount) return;
Mesh mesh = vegetationItemModelInfo.GetLODMesh(lodIndex);
Material[] materials = vegetationItemModelInfo.GetLODMaterials(lodIndex);
MaterialPropertyBlock materialPropertyBlock = vegetationItemModelInfo.GetLODMaterialPropertyBlock(lodIndex);
materialPropertyBlock.Clear();
if (vegetationItemModelInfo.ShaderControler != null &&
vegetationItemModelInfo.ShaderControler.Settings.SampleWind)
{
MeshRenderer meshRenderer = vegetationItemModelInfo.WindSamplerMeshRendererList[cameraIndex];
if (meshRenderer)
{
meshRenderer.GetPropertyBlock(materialPropertyBlock);
}
}
for (int i = 0; i <= matrixList.Length - 1; i++)
{
int submeshesToRender = Mathf.Min(mesh.subMeshCount, materials.Length);
for (int m = 0; m <= submeshesToRender - 1; m++)
{
Graphics.DrawMesh(mesh, matrixList[i], materials[m], layer, targetCamera, m, materialPropertyBlock,
shadowCastingMode, true, null, LightProbeUsage.Off);
}
}
}
void RenderVegetationItemLOD(NativeList<Matrix4x4> matrixList, NativeList<Vector4> lodFadeList,
VegetationItemModelInfo vegetationItemModelInfo, int lodIndex, Camera targetCamera, int cameraIndex,
ShadowCastingMode shadowCastingMode, LayerMask layer)
{
if (matrixList.Length == 0) return;
if (lodIndex >= vegetationItemModelInfo.LODCount) return;
//bool uniqueMaterialPropertyBlock = matrixList.Length > 999;
int count = Mathf.CeilToInt(matrixList.Length / 1000f);
// count = Mathf.Clamp(count, 0, 1);
int totalCount = matrixList.Length;
for (int l = 0; l <= count - 1; l++)
{
int copyCount = 1000;
if (totalCount < 1000) copyCount = totalCount;
NativeSlice<Matrix4x4> matrixSlice = new NativeSlice<Matrix4x4>(matrixList, l * 1000, copyCount);
matrixSlice.CopyToFast(_renderArray);
Mesh mesh = vegetationItemModelInfo.GetLODMesh(lodIndex);
Material[] materials = vegetationItemModelInfo.GetLODMaterials(lodIndex);
MaterialPropertyBlock materialPropertyBlock =
vegetationItemModelInfo.GetLODMaterialPropertyBlock(lodIndex);
materialPropertyBlock.Clear();
if (vegetationItemModelInfo.ShaderControler != null &&
vegetationItemModelInfo.ShaderControler.Settings.SampleWind)
{
MeshRenderer meshRenderer = vegetationItemModelInfo.WindSamplerMeshRendererList[cameraIndex];
if (meshRenderer)
{
meshRenderer.GetPropertyBlock(materialPropertyBlock);
}
}
if (shadowCastingMode != ShadowCastingMode.ShadowsOnly)
{
if (lodFadeList.Length == matrixList.Length)
{
NativeSlice<Vector4> lodFadeSlice = new NativeSlice<Vector4>(lodFadeList, l * 1000, copyCount);
lodFadeSlice.CopyToFast(_renderLodFadeArray);
materialPropertyBlock.SetVectorArray(_unityLODFadeID, _renderLodFadeArray);
}
}
if (VegetationRenderSettings.EnableInstancedRenderingLayers)
{
materialPropertyBlock.SetFloatArray(UnityRenderingLayerID, _renderingLayerArray);
}
int submeshesToRender = Mathf.Min(mesh.subMeshCount, materials.Length);
for (int m = 0; m <= submeshesToRender - 1; m++)
{
Graphics.DrawMeshInstanced(mesh, m,
materials[m], _renderArray, copyCount,
materialPropertyBlock, shadowCastingMode, true, layer,
targetCamera,
LightProbeUsage.Off);
}
totalCount -= 1000;
}
}
// ReSharper disable once UnusedMember.Local
void OnDisable()
{
VegetationStudioManager.UnregisterVegetationSystem(this);
DisableEditorApi();
DisposeVegetationStudioCameras();
RemoveVegetationStudioCameraDelegates();
DisposeVegetationCells();
DisposeBillboardCells();
ClearVegetationItemModels();
DisposeComputeShaders();
VegetationCellSpawner.Dispose();
InitDone = false;
}
}
}