1218 lines
48 KiB
C#
1218 lines
48 KiB
C#
|
using System;
|
|||
|
using AwesomeTechnologies.Shaders;
|
|||
|
using System.Collections.Generic;
|
|||
|
using AwesomeTechnologies.Utility;
|
|||
|
using Unity.Collections;
|
|||
|
using UnityEngine;
|
|||
|
using UnityEngine.AI;
|
|||
|
using UnityEngine.Rendering;
|
|||
|
using Object = UnityEngine.Object;
|
|||
|
|
|||
|
namespace AwesomeTechnologies.VegetationSystem
|
|||
|
{
|
|||
|
public class CameraComputeBuffers
|
|||
|
{
|
|||
|
public ComputeBuffer MergeBuffer;
|
|||
|
public ComputeBuffer VisibleBufferLOD0;
|
|||
|
public ComputeBuffer VisibleBufferLOD1;
|
|||
|
public ComputeBuffer VisibleBufferLOD2;
|
|||
|
public ComputeBuffer VisibleBufferLOD3;
|
|||
|
|
|||
|
public ComputeBuffer ShadowBufferLOD0;
|
|||
|
public ComputeBuffer ShadowBufferLOD1;
|
|||
|
public ComputeBuffer ShadowBufferLOD2;
|
|||
|
public ComputeBuffer ShadowBufferLOD3;
|
|||
|
|
|||
|
private readonly uint[] _args = {0, 0, 0, 0, 0};
|
|||
|
public readonly List<ComputeBuffer> ArgsBufferMergedLOD0List = new List<ComputeBuffer>();
|
|||
|
public readonly List<ComputeBuffer> ArgsBufferMergedLOD1List = new List<ComputeBuffer>();
|
|||
|
public readonly List<ComputeBuffer> ArgsBufferMergedLOD2List = new List<ComputeBuffer>();
|
|||
|
public readonly List<ComputeBuffer> ArgsBufferMergedLOD3List = new List<ComputeBuffer>();
|
|||
|
|
|||
|
public readonly List<ComputeBuffer> ShadowArgsBufferMergedLOD0List = new List<ComputeBuffer>();
|
|||
|
public readonly List<ComputeBuffer> ShadowArgsBufferMergedLOD1List = new List<ComputeBuffer>();
|
|||
|
public readonly List<ComputeBuffer> ShadowArgsBufferMergedLOD2List = new List<ComputeBuffer>();
|
|||
|
public readonly List<ComputeBuffer> ShadowArgsBufferMergedLOD3List = new List<ComputeBuffer>();
|
|||
|
|
|||
|
public CameraComputeBuffers(Mesh vegetationMeshLod0, Mesh vegetationMeshLod1, Mesh vegetationMeshLod2,
|
|||
|
Mesh vegetationMeshLod3)
|
|||
|
{
|
|||
|
MergeBuffer = new ComputeBuffer(5000, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
MergeBuffer.SetCounterValue(0);
|
|||
|
|
|||
|
VisibleBufferLOD0 = new ComputeBuffer(5000, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
VisibleBufferLOD0.SetCounterValue(0);
|
|||
|
|
|||
|
VisibleBufferLOD1 = new ComputeBuffer(5000, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
VisibleBufferLOD1.SetCounterValue(0);
|
|||
|
|
|||
|
VisibleBufferLOD2 = new ComputeBuffer(5000, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
VisibleBufferLOD2.SetCounterValue(0);
|
|||
|
|
|||
|
VisibleBufferLOD3 = new ComputeBuffer(5000, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
VisibleBufferLOD3.SetCounterValue(0);
|
|||
|
|
|||
|
ShadowBufferLOD0 = new ComputeBuffer(5000, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
ShadowBufferLOD0.SetCounterValue(0);
|
|||
|
|
|||
|
ShadowBufferLOD1 = new ComputeBuffer(5000, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
ShadowBufferLOD1.SetCounterValue(0);
|
|||
|
|
|||
|
ShadowBufferLOD2 = new ComputeBuffer(5000, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
ShadowBufferLOD2.SetCounterValue(0);
|
|||
|
|
|||
|
ShadowBufferLOD3 = new ComputeBuffer(5000, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
ShadowBufferLOD3.SetCounterValue(0);
|
|||
|
|
|||
|
|
|||
|
for (int i = 0; i <= vegetationMeshLod0.subMeshCount - 1; i++)
|
|||
|
{
|
|||
|
_args[0] = vegetationMeshLod0.GetIndexCount(i);
|
|||
|
_args[2] = vegetationMeshLod0.GetIndexStart(i);
|
|||
|
|
|||
|
ComputeBuffer argsBufferMergedLod0 =
|
|||
|
new ComputeBuffer(1, _args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
|
|||
|
argsBufferMergedLod0.SetData(_args);
|
|||
|
ArgsBufferMergedLOD0List.Add(argsBufferMergedLod0);
|
|||
|
|
|||
|
ComputeBuffer shadowArgsBufferMergedLod0 =
|
|||
|
new ComputeBuffer(1, _args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
|
|||
|
shadowArgsBufferMergedLod0.SetData(_args);
|
|||
|
ShadowArgsBufferMergedLOD0List.Add(shadowArgsBufferMergedLod0);
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i <= vegetationMeshLod1.subMeshCount - 1; i++)
|
|||
|
{
|
|||
|
_args[0] = vegetationMeshLod1.GetIndexCount(i);
|
|||
|
_args[2] = vegetationMeshLod1.GetIndexStart(i);
|
|||
|
|
|||
|
ComputeBuffer argsBufferMergedLod1 =
|
|||
|
new ComputeBuffer(1, _args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
|
|||
|
argsBufferMergedLod1.SetData(_args);
|
|||
|
ArgsBufferMergedLOD1List.Add(argsBufferMergedLod1);
|
|||
|
|
|||
|
ComputeBuffer shadowArgsBufferMergedLod1 =
|
|||
|
new ComputeBuffer(1, _args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
|
|||
|
shadowArgsBufferMergedLod1.SetData(_args);
|
|||
|
ShadowArgsBufferMergedLOD1List.Add(shadowArgsBufferMergedLod1);
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i <= vegetationMeshLod2.subMeshCount - 1; i++)
|
|||
|
{
|
|||
|
_args[0] = vegetationMeshLod2.GetIndexCount(i);
|
|||
|
_args[2] = vegetationMeshLod2.GetIndexStart(i);
|
|||
|
|
|||
|
ComputeBuffer argsBufferMergedLod2 =
|
|||
|
new ComputeBuffer(1, _args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
|
|||
|
argsBufferMergedLod2.SetData(_args);
|
|||
|
ArgsBufferMergedLOD2List.Add(argsBufferMergedLod2);
|
|||
|
|
|||
|
ComputeBuffer shadowArgsBufferMergedLod2 =
|
|||
|
new ComputeBuffer(1, _args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
|
|||
|
shadowArgsBufferMergedLod2.SetData(_args);
|
|||
|
ShadowArgsBufferMergedLOD2List.Add(shadowArgsBufferMergedLod2);
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i <= vegetationMeshLod3.subMeshCount - 1; i++)
|
|||
|
{
|
|||
|
_args[0] = vegetationMeshLod3.GetIndexCount(i);
|
|||
|
_args[2] = vegetationMeshLod3.GetIndexStart(i);
|
|||
|
|
|||
|
ComputeBuffer argsBufferMergedLod3 =
|
|||
|
new ComputeBuffer(1, _args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
|
|||
|
argsBufferMergedLod3.SetData(_args);
|
|||
|
ArgsBufferMergedLOD3List.Add(argsBufferMergedLod3);
|
|||
|
|
|||
|
ComputeBuffer shadowArgsBufferMergedLod3 =
|
|||
|
new ComputeBuffer(1, _args.Length * sizeof(uint), ComputeBufferType.IndirectArguments);
|
|||
|
shadowArgsBufferMergedLod3.SetData(_args);
|
|||
|
ShadowArgsBufferMergedLOD3List.Add(shadowArgsBufferMergedLod3);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void UpdateComputeBufferSize(int newInstanceCount)
|
|||
|
{
|
|||
|
MergeBuffer?.Release();
|
|||
|
MergeBuffer = null;
|
|||
|
|
|||
|
VisibleBufferLOD0?.Release();
|
|||
|
VisibleBufferLOD0 = null;
|
|||
|
|
|||
|
VisibleBufferLOD1?.Release();
|
|||
|
VisibleBufferLOD1 = null;
|
|||
|
|
|||
|
VisibleBufferLOD2?.Release();
|
|||
|
VisibleBufferLOD2 = null;
|
|||
|
|
|||
|
VisibleBufferLOD3?.Release();
|
|||
|
VisibleBufferLOD3 = null;
|
|||
|
|
|||
|
ShadowBufferLOD0?.Release();
|
|||
|
ShadowBufferLOD0 = null;
|
|||
|
|
|||
|
ShadowBufferLOD1?.Release();
|
|||
|
ShadowBufferLOD1 = null;
|
|||
|
|
|||
|
ShadowBufferLOD2?.Release();
|
|||
|
ShadowBufferLOD2 = null;
|
|||
|
|
|||
|
ShadowBufferLOD3?.Release();
|
|||
|
ShadowBufferLOD3 = null;
|
|||
|
|
|||
|
MergeBuffer = new ComputeBuffer(newInstanceCount, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
MergeBuffer.SetCounterValue(0);
|
|||
|
|
|||
|
VisibleBufferLOD0 = new ComputeBuffer(newInstanceCount, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
VisibleBufferLOD0.SetCounterValue(0);
|
|||
|
|
|||
|
VisibleBufferLOD1 = new ComputeBuffer(newInstanceCount, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
VisibleBufferLOD1.SetCounterValue(0);
|
|||
|
|
|||
|
VisibleBufferLOD2 = new ComputeBuffer(newInstanceCount, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
VisibleBufferLOD2.SetCounterValue(0);
|
|||
|
|
|||
|
VisibleBufferLOD3 = new ComputeBuffer(newInstanceCount, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
VisibleBufferLOD3.SetCounterValue(0);
|
|||
|
|
|||
|
ShadowBufferLOD0 = new ComputeBuffer(newInstanceCount, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
ShadowBufferLOD0.SetCounterValue(0);
|
|||
|
|
|||
|
ShadowBufferLOD1 = new ComputeBuffer(newInstanceCount, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
ShadowBufferLOD1.SetCounterValue(0);
|
|||
|
|
|||
|
ShadowBufferLOD2 = new ComputeBuffer(newInstanceCount, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
ShadowBufferLOD2.SetCounterValue(0);
|
|||
|
|
|||
|
ShadowBufferLOD3 = new ComputeBuffer(newInstanceCount, (16 * 4 * 2) + 16, ComputeBufferType.Append);
|
|||
|
ShadowBufferLOD3.SetCounterValue(0);
|
|||
|
}
|
|||
|
|
|||
|
public void DestroyComputeBuffers()
|
|||
|
{
|
|||
|
MergeBuffer?.Release();
|
|||
|
MergeBuffer = null;
|
|||
|
|
|||
|
VisibleBufferLOD0?.Release();
|
|||
|
VisibleBufferLOD0 = null;
|
|||
|
|
|||
|
VisibleBufferLOD1?.Release();
|
|||
|
VisibleBufferLOD1 = null;
|
|||
|
|
|||
|
VisibleBufferLOD2?.Release();
|
|||
|
VisibleBufferLOD2 = null;
|
|||
|
|
|||
|
VisibleBufferLOD3?.Release();
|
|||
|
VisibleBufferLOD3 = null;
|
|||
|
|
|||
|
ShadowBufferLOD0?.Release();
|
|||
|
ShadowBufferLOD0 = null;
|
|||
|
|
|||
|
ShadowBufferLOD1?.Release();
|
|||
|
ShadowBufferLOD1 = null;
|
|||
|
|
|||
|
ShadowBufferLOD2?.Release();
|
|||
|
ShadowBufferLOD2 = null;
|
|||
|
|
|||
|
ShadowBufferLOD3?.Release();
|
|||
|
ShadowBufferLOD3 = null;
|
|||
|
|
|||
|
ReleaseArgsBuffers();
|
|||
|
}
|
|||
|
|
|||
|
void ReleaseArgsBuffers()
|
|||
|
{
|
|||
|
for (var i = 0; i <= ArgsBufferMergedLOD0List.Count - 1; i++)
|
|||
|
{
|
|||
|
if (ArgsBufferMergedLOD0List[i] != null) ArgsBufferMergedLOD0List[i].Release();
|
|||
|
}
|
|||
|
|
|||
|
for (var i = 0; i <= ArgsBufferMergedLOD1List.Count - 1; i++)
|
|||
|
{
|
|||
|
if (ArgsBufferMergedLOD1List[i] != null) ArgsBufferMergedLOD1List[i].Release();
|
|||
|
}
|
|||
|
|
|||
|
for (var i = 0; i <= ArgsBufferMergedLOD2List.Count - 1; i++)
|
|||
|
{
|
|||
|
if (ArgsBufferMergedLOD2List[i] != null) ArgsBufferMergedLOD2List[i].Release();
|
|||
|
}
|
|||
|
|
|||
|
for (var i = 0; i <= ArgsBufferMergedLOD3List.Count - 1; i++)
|
|||
|
{
|
|||
|
if (ArgsBufferMergedLOD3List[i] != null) ArgsBufferMergedLOD3List[i].Release();
|
|||
|
}
|
|||
|
|
|||
|
for (var i = 0; i <= ShadowArgsBufferMergedLOD0List.Count - 1; i++)
|
|||
|
{
|
|||
|
if (ShadowArgsBufferMergedLOD0List[i] != null) ShadowArgsBufferMergedLOD0List[i].Release();
|
|||
|
}
|
|||
|
|
|||
|
for (var i = 0; i <= ShadowArgsBufferMergedLOD1List.Count - 1; i++)
|
|||
|
{
|
|||
|
if (ShadowArgsBufferMergedLOD1List[i] != null) ShadowArgsBufferMergedLOD1List[i].Release();
|
|||
|
}
|
|||
|
|
|||
|
for (var i = 0; i <= ShadowArgsBufferMergedLOD2List.Count - 1; i++)
|
|||
|
{
|
|||
|
if (ShadowArgsBufferMergedLOD2List[i] != null) ShadowArgsBufferMergedLOD2List[i].Release();
|
|||
|
}
|
|||
|
|
|||
|
for (var i = 0; i <= ShadowArgsBufferMergedLOD3List.Count - 1; i++)
|
|||
|
{
|
|||
|
if (ShadowArgsBufferMergedLOD3List[i] != null) ShadowArgsBufferMergedLOD3List[i].Release();
|
|||
|
}
|
|||
|
|
|||
|
ArgsBufferMergedLOD0List.Clear();
|
|||
|
ArgsBufferMergedLOD1List.Clear();
|
|||
|
ArgsBufferMergedLOD2List.Clear();
|
|||
|
ArgsBufferMergedLOD3List.Clear();
|
|||
|
|
|||
|
ShadowArgsBufferMergedLOD0List.Clear();
|
|||
|
ShadowArgsBufferMergedLOD1List.Clear();
|
|||
|
ShadowArgsBufferMergedLOD2List.Clear();
|
|||
|
ShadowArgsBufferMergedLOD3List.Clear();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class VegetationItemModelInfo
|
|||
|
{
|
|||
|
public GameObject VegetationModel;
|
|||
|
|
|||
|
public Mesh VegetationMeshLod0;
|
|||
|
public Mesh VegetationMeshLod1;
|
|||
|
public Mesh VegetationMeshLod2;
|
|||
|
public Mesh VegetationMeshLod3;
|
|||
|
|
|||
|
public float LOD1Distance;
|
|||
|
public float LOD2Distance;
|
|||
|
public float LOD3Distance;
|
|||
|
public int LODCount;
|
|||
|
|
|||
|
public bool LODFadePercentage;
|
|||
|
public bool LODFadeCrossfade;
|
|||
|
|
|||
|
public int DistanceBand;
|
|||
|
|
|||
|
public Material[] VegetationMaterialsLOD0;
|
|||
|
public Material[] VegetationMaterialsLOD1;
|
|||
|
public Material[] VegetationMaterialsLOD2;
|
|||
|
public Material[] VegetationMaterialsLOD3;
|
|||
|
public MeshRenderer VegetationRendererLOD0;
|
|||
|
public MeshRenderer VegetationRendererLOD1;
|
|||
|
public MeshRenderer VegetationRendererLOD2;
|
|||
|
public MeshRenderer VegetationRendererLOD3;
|
|||
|
public MaterialPropertyBlock VegetationMaterialPropertyBlockLOD0;
|
|||
|
public MaterialPropertyBlock VegetationMaterialPropertyBlockLOD1;
|
|||
|
public MaterialPropertyBlock VegetationMaterialPropertyBlockLOD2;
|
|||
|
public MaterialPropertyBlock VegetationMaterialPropertyBlockLOD3;
|
|||
|
public MaterialPropertyBlock VegetationMaterialPropertyBlockShadowsLOD0;
|
|||
|
public MaterialPropertyBlock VegetationMaterialPropertyBlockShadowsLOD1;
|
|||
|
public MaterialPropertyBlock VegetationMaterialPropertyBlockShadowsLOD2;
|
|||
|
public MaterialPropertyBlock VegetationMaterialPropertyBlockShadowsLOD3;
|
|||
|
public VegetationItemInfoPro VegetationItemInfo;
|
|||
|
public EnvironmentSettings EnvironmentSettings;
|
|||
|
public VegetationRenderSettings VegetationRenderSettings;
|
|||
|
public float BoundingSphereRadius;
|
|||
|
|
|||
|
public GameObject SelectedVegetationModelLOD0;
|
|||
|
public GameObject SelectedVegetationModelLOD1;
|
|||
|
public GameObject SelectedVegetationModelLOD2;
|
|||
|
public GameObject SelectedVegetationModelLOD3;
|
|||
|
|
|||
|
public Material BillboardMaterial;
|
|||
|
|
|||
|
|
|||
|
//TODO update these automatic when new cameras is added or removed
|
|||
|
public List<MeshRenderer> WindSamplerMeshRendererList = new List<MeshRenderer>();
|
|||
|
public readonly List<CameraComputeBuffers> CameraComputeBufferList = new List<CameraComputeBuffers>();
|
|||
|
|
|||
|
public readonly List<MaterialPropertyBlock> CameraBillboardMaterialPropertyBlockList =
|
|||
|
new List<MaterialPropertyBlock>();
|
|||
|
|
|||
|
//public NativeArray<float> DistanceFalloffCurveArray;
|
|||
|
|
|||
|
public NativeArray<float> HeightRuleCurveArray;
|
|||
|
public NativeArray<float> SteepnessRuleCurveArray;
|
|||
|
|
|||
|
private float _maxVegetationSize;
|
|||
|
|
|||
|
[NonSerialized] public IShaderController ShaderControler;
|
|||
|
|
|||
|
public VegetationItemModelInfo(VegetationItemInfoPro vegetationItemInfo,
|
|||
|
EnvironmentSettings environmentSettings, List<GameObject> windSamplerList, int cameraCount,
|
|||
|
VegetationRenderSettings vegetationRenderSettings)
|
|||
|
{
|
|||
|
EnvironmentSettings = environmentSettings;
|
|||
|
VegetationRenderSettings = vegetationRenderSettings;
|
|||
|
VegetationItemInfo = vegetationItemInfo;
|
|||
|
VegetationModel = vegetationItemInfo.VegetationPrefab;
|
|||
|
|
|||
|
if (vegetationItemInfo.PrefabType == VegetationPrefabType.Texture)
|
|||
|
{
|
|||
|
VegetationModel = Resources.Load<GameObject>("DefaultGrassPatch");
|
|||
|
}
|
|||
|
|
|||
|
if (VegetationModel == null)
|
|||
|
{
|
|||
|
VegetationModel = Resources.Load("MissingVegetationItemCube") as GameObject;
|
|||
|
Debug.LogError("The vegetation prefab of item: " + vegetationItemInfo.Name +
|
|||
|
" is missing. Please replace or delete VegetationItem.");
|
|||
|
}
|
|||
|
|
|||
|
DistanceBand = vegetationItemInfo.GetDistanceBand();
|
|||
|
|
|||
|
#if UNITY_EDITOR
|
|||
|
MaterialUtility.EnableMaterialInstancing(VegetationModel);
|
|||
|
#endif
|
|||
|
SelectedVegetationModelLOD0 = MeshUtils.SelectMeshObject(VegetationModel, LODLevel.LOD0);
|
|||
|
SelectedVegetationModelLOD1 = MeshUtils.SelectMeshObject(VegetationModel, LODLevel.LOD1);
|
|||
|
SelectedVegetationModelLOD2 = MeshUtils.SelectMeshObject(VegetationModel, LODLevel.LOD2);
|
|||
|
SelectedVegetationModelLOD3 = MeshUtils.SelectMeshObject(VegetationModel, LODLevel.LOD3);
|
|||
|
|
|||
|
ShaderControler = ShaderSelector.GetShaderControler(vegetationItemInfo.ShaderName);
|
|||
|
if (ShaderControler != null) ShaderControler.Settings = vegetationItemInfo.ShaderControllerSettings;
|
|||
|
LODCount = MeshUtils.GetLODCount(VegetationModel, ShaderControler);
|
|||
|
|
|||
|
CreateCameraWindSamplerItems(windSamplerList);
|
|||
|
|
|||
|
if (ShaderControler != null)
|
|||
|
{
|
|||
|
LODFadePercentage = ShaderControler.Settings.LODFadePercentage;
|
|||
|
LODFadeCrossfade = ShaderControler.Settings.LODFadeCrossfade;
|
|||
|
}
|
|||
|
|
|||
|
VegetationMeshLod0 = GetVegetationMesh(VegetationModel, LODLevel.LOD0);
|
|||
|
VegetationMeshLod1 = GetVegetationMesh(VegetationModel, LODLevel.LOD1);
|
|||
|
VegetationMeshLod2 = GetVegetationMesh(VegetationModel, LODLevel.LOD2);
|
|||
|
VegetationMeshLod3 = GetVegetationMesh(VegetationModel, LODLevel.LOD3);
|
|||
|
|
|||
|
VegetationRendererLOD0 = SelectedVegetationModelLOD0.GetComponentInChildren<MeshRenderer>();
|
|||
|
VegetationMaterialsLOD0 = CreateMaterials(VegetationRendererLOD0.sharedMaterials, 0);
|
|||
|
|
|||
|
VegetationRendererLOD1 = SelectedVegetationModelLOD1.GetComponentInChildren<MeshRenderer>();
|
|||
|
VegetationMaterialsLOD1 = CreateMaterials(VegetationRendererLOD1.sharedMaterials, 1);
|
|||
|
|
|||
|
VegetationRendererLOD2 = SelectedVegetationModelLOD2.GetComponentInChildren<MeshRenderer>();
|
|||
|
VegetationMaterialsLOD2 = CreateMaterials(VegetationRendererLOD2.sharedMaterials, 2);
|
|||
|
|
|||
|
VegetationRendererLOD3 = SelectedVegetationModelLOD3.GetComponentInChildren<MeshRenderer>();
|
|||
|
VegetationMaterialsLOD3 = CreateMaterials(VegetationRendererLOD3.sharedMaterials, 3);
|
|||
|
|
|||
|
if (vegetationItemInfo.PrefabType == VegetationPrefabType.Texture)
|
|||
|
{
|
|||
|
#if UNITY_2019_3_OR_NEWER
|
|||
|
Shader grassShader = Shader.Find("AwesomeTechnologies/Release/Grass/Grass");
|
|||
|
MaterialUtility.ChangeShader(VegetationMaterialsLOD0, grassShader);
|
|||
|
MaterialUtility.ChangeShader(VegetationMaterialsLOD1, grassShader);
|
|||
|
MaterialUtility.ChangeShader(VegetationMaterialsLOD2, grassShader);
|
|||
|
MaterialUtility.ChangeShader(VegetationMaterialsLOD3, grassShader);
|
|||
|
#endif
|
|||
|
|
|||
|
SetGrassTexture(VegetationMaterialsLOD0, vegetationItemInfo.VegetationTexture);
|
|||
|
SetGrassTexture(VegetationMaterialsLOD1, vegetationItemInfo.VegetationTexture);
|
|||
|
SetGrassTexture(VegetationMaterialsLOD2, vegetationItemInfo.VegetationTexture);
|
|||
|
SetGrassTexture(VegetationMaterialsLOD3, vegetationItemInfo.VegetationTexture);
|
|||
|
}
|
|||
|
|
|||
|
VegetationMaterialPropertyBlockLOD0 = new MaterialPropertyBlock();
|
|||
|
VegetationRendererLOD0.GetPropertyBlock(VegetationMaterialPropertyBlockLOD0);
|
|||
|
if (VegetationMaterialPropertyBlockLOD0 == null)
|
|||
|
VegetationMaterialPropertyBlockLOD0 = new MaterialPropertyBlock();
|
|||
|
|
|||
|
VegetationMaterialPropertyBlockLOD1 = new MaterialPropertyBlock();
|
|||
|
VegetationRendererLOD1.GetPropertyBlock(VegetationMaterialPropertyBlockLOD1);
|
|||
|
if (VegetationMaterialPropertyBlockLOD1 == null)
|
|||
|
VegetationMaterialPropertyBlockLOD1 = new MaterialPropertyBlock();
|
|||
|
|
|||
|
VegetationMaterialPropertyBlockLOD2 = new MaterialPropertyBlock();
|
|||
|
VegetationRendererLOD2.GetPropertyBlock(VegetationMaterialPropertyBlockLOD2);
|
|||
|
if (VegetationMaterialPropertyBlockLOD2 == null)
|
|||
|
VegetationMaterialPropertyBlockLOD2 = new MaterialPropertyBlock();
|
|||
|
|
|||
|
VegetationMaterialPropertyBlockLOD3 = new MaterialPropertyBlock();
|
|||
|
VegetationRendererLOD3.GetPropertyBlock(VegetationMaterialPropertyBlockLOD3);
|
|||
|
if (VegetationMaterialPropertyBlockLOD3 == null)
|
|||
|
VegetationMaterialPropertyBlockLOD3 = new MaterialPropertyBlock();
|
|||
|
|
|||
|
VegetationMaterialPropertyBlockShadowsLOD0 = new MaterialPropertyBlock();
|
|||
|
VegetationRendererLOD0.GetPropertyBlock(VegetationMaterialPropertyBlockShadowsLOD0);
|
|||
|
if (VegetationMaterialPropertyBlockShadowsLOD0 == null)
|
|||
|
VegetationMaterialPropertyBlockShadowsLOD0 = new MaterialPropertyBlock();
|
|||
|
|
|||
|
VegetationMaterialPropertyBlockShadowsLOD1 = new MaterialPropertyBlock();
|
|||
|
VegetationRendererLOD1.GetPropertyBlock(VegetationMaterialPropertyBlockShadowsLOD1);
|
|||
|
if (VegetationMaterialPropertyBlockShadowsLOD1 == null)
|
|||
|
VegetationMaterialPropertyBlockShadowsLOD1 = new MaterialPropertyBlock();
|
|||
|
|
|||
|
VegetationMaterialPropertyBlockShadowsLOD2 = new MaterialPropertyBlock();
|
|||
|
VegetationRendererLOD2.GetPropertyBlock(VegetationMaterialPropertyBlockShadowsLOD2);
|
|||
|
if (VegetationMaterialPropertyBlockShadowsLOD2 == null)
|
|||
|
VegetationMaterialPropertyBlockShadowsLOD2 = new MaterialPropertyBlock();
|
|||
|
|
|||
|
VegetationMaterialPropertyBlockShadowsLOD3 = new MaterialPropertyBlock();
|
|||
|
VegetationRendererLOD3.GetPropertyBlock(VegetationMaterialPropertyBlockShadowsLOD3);
|
|||
|
if (VegetationMaterialPropertyBlockShadowsLOD3 == null)
|
|||
|
VegetationMaterialPropertyBlockShadowsLOD3 = new MaterialPropertyBlock();
|
|||
|
|
|||
|
LOD1Distance = GetLODDistance(VegetationModel, 0);
|
|||
|
LOD2Distance = GetLODDistance(VegetationModel, 1);
|
|||
|
LOD3Distance = GetLODDistance(VegetationModel, 2);
|
|||
|
|
|||
|
vegetationItemInfo.Bounds = MeshUtils.CalculateBoundsInstantiate(VegetationModel);
|
|||
|
|
|||
|
float maxScaleMultiplier = Mathf.Max(new float[]
|
|||
|
{
|
|||
|
vegetationItemInfo.ScaleMultiplier.x, vegetationItemInfo.ScaleMultiplier.y,
|
|||
|
vegetationItemInfo.ScaleMultiplier.z
|
|||
|
});
|
|||
|
BoundingSphereRadius = (vegetationItemInfo.Bounds.extents.magnitude * VegetationItemInfo.MaxScale *
|
|||
|
VegetationItemInfo.YScale * maxScaleMultiplier) + 5;
|
|||
|
|
|||
|
|
|||
|
CreateCameraBuffers(cameraCount);
|
|||
|
|
|||
|
HeightRuleCurveArray = new NativeArray<float>(4096, Allocator.Persistent);
|
|||
|
UpdateHeightRuleCurve();
|
|||
|
|
|||
|
|
|||
|
SteepnessRuleCurveArray = new NativeArray<float>(4096, Allocator.Persistent);
|
|||
|
UpdateSteepnessRuleCurve();
|
|||
|
|
|||
|
//DistanceFalloffCurveArray = new NativeArray<float>(256, Allocator.Persistent);
|
|||
|
//UpdateDistanceFalloutCurve();
|
|||
|
|
|||
|
if (vegetationItemInfo.VegetationType == VegetationType.Tree)
|
|||
|
{
|
|||
|
CreateBillboardMaterial();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void CreateCameraWindSamplerItems(List<GameObject> windSamplerList)
|
|||
|
{
|
|||
|
if (ShaderControler != null && ShaderControler.Settings.SampleWind)
|
|||
|
{
|
|||
|
for (int i = 0; i <= windSamplerList.Count - 1; i++)
|
|||
|
{
|
|||
|
GameObject windSampleItem = Object.Instantiate(SelectedVegetationModelLOD0);
|
|||
|
windSampleItem.hideFlags = HideFlags.HideAndDontSave;
|
|||
|
windSampleItem.name = "VegetationSystemRenderer";
|
|||
|
windSampleItem.transform.SetParent(windSamplerList[i].transform);
|
|||
|
windSampleItem.transform.localPosition = new Vector3(0, 0, 3);
|
|||
|
windSampleItem.transform.localRotation = Quaternion.identity;
|
|||
|
CleanVegetationObject(windSampleItem);
|
|||
|
MeshRenderer meshRenderer = windSampleItem.GetComponentInChildren<MeshRenderer>();
|
|||
|
WindSamplerMeshRendererList.Add(meshRenderer);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void CreateCameraBuffers(int cameraCount)
|
|||
|
{
|
|||
|
DisposeCameraBuffers();
|
|||
|
CameraBillboardMaterialPropertyBlockList.Clear();
|
|||
|
|
|||
|
for (int i = 0; i <= cameraCount - 1; i++)
|
|||
|
{
|
|||
|
CameraComputeBuffers cameraComputeBuffers = new CameraComputeBuffers(VegetationMeshLod0,
|
|||
|
VegetationMeshLod1, VegetationMeshLod2, VegetationMeshLod3);
|
|||
|
CameraComputeBufferList.Add(cameraComputeBuffers);
|
|||
|
|
|||
|
CameraBillboardMaterialPropertyBlockList.Add(new MaterialPropertyBlock());
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public bool BillboardLODFadeCrossfade;
|
|||
|
|
|||
|
void SetGrassTexture(Material[] materials, Texture2D texture)
|
|||
|
{
|
|||
|
for (int i = 0; i <= materials.Length - 1; i++)
|
|||
|
{
|
|||
|
materials[i].SetTexture("_MainTex", texture);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void UpdateBillboardMaterial()
|
|||
|
{
|
|||
|
if (!BillboardMaterial) return;
|
|||
|
|
|||
|
BillboardMaterial.SetFloat("_Cutoff", VegetationItemInfo.BillboardCutoff);
|
|||
|
|
|||
|
if (ShaderControler != null)
|
|||
|
{
|
|||
|
BillboardLODFadeCrossfade = ShaderControler.Settings.LODFadeCrossfade;
|
|||
|
}
|
|||
|
|
|||
|
if (ShaderControler != null && ShaderControler.Settings.DynamicHUE)
|
|||
|
{
|
|||
|
Color hueColor = ShaderControler.Settings.GetColorPropertyValue("FoliageHue");
|
|||
|
BillboardMaterial.SetColor("_HueVariation", hueColor);
|
|||
|
BillboardMaterial.EnableKeyword("AT_HUE_VARIATION_ON");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
BillboardMaterial.SetColor("_HueVariation", new Color(1f, 0.5f, 0f, 25f / 256f));
|
|||
|
BillboardMaterial.DisableKeyword("AT_HUE_VARIATION_ON");
|
|||
|
}
|
|||
|
|
|||
|
BillboardMaterial.EnableKeyword("LOD_FADE_CROSSFADE");
|
|||
|
|
|||
|
BillboardMaterial.SetColor("_Color", VegetationItemInfo.BillboardTintColor);
|
|||
|
BillboardMaterial.SetFloat("_Brightness", VegetationItemInfo.BillboardBrightness);
|
|||
|
BillboardMaterial.SetFloat("_SnowAmount", Mathf.Clamp01(EnvironmentSettings.SnowAmount));
|
|||
|
BillboardMaterial.SetColor("_SnowColor", EnvironmentSettings.BillboardSnowColor);
|
|||
|
BillboardMaterial.SetFloat("_SnowBlendFactor", EnvironmentSettings.SnowBlendFactor);
|
|||
|
BillboardMaterial.SetFloat("_SnowBrightness", EnvironmentSettings.SnowBrightness);
|
|||
|
BillboardMaterial.SetFloat("_BillboardWindSpeed", VegetationItemInfo.BillboardWindSpeed);
|
|||
|
BillboardMaterial.SetFloat("_Smoothness", VegetationItemInfo.BillboardSmoothness);
|
|||
|
BillboardMaterial.SetFloat("_NormalStrength", VegetationItemInfo.BillboardNormalStrength);
|
|||
|
BillboardMaterial.SetFloat("_ShadowOffset", VegetationItemInfo.BillboardShadowOffset);
|
|||
|
|
|||
|
var boundsSize = Mathf.Max(VegetationItemInfo.Bounds.extents.x, VegetationItemInfo.Bounds.extents.y,
|
|||
|
VegetationItemInfo.Bounds.extents.z);
|
|||
|
BillboardMaterial.SetFloat("_DepthBoundsSize", boundsSize * 2);
|
|||
|
|
|||
|
BillboardMaterial.SetFloat("_FadeDistance", VegetationItemInfo.BillboardFadeDistance);
|
|||
|
|
|||
|
if (VegetationItemInfo.UseBillboardFade)
|
|||
|
{
|
|||
|
BillboardMaterial.SetInt("_UseFade", 1);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
BillboardMaterial.SetInt("_UseFade", 0);
|
|||
|
}
|
|||
|
|
|||
|
if (VegetationItemInfo.BillboardRenderMode == BillboardRenderMode.Standard)
|
|||
|
{
|
|||
|
BillboardMaterial.SetFloat("_Metallic", VegetationItemInfo.BillboardMetallic);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
BillboardMaterial.SetFloat("_Specular", VegetationItemInfo.BillboardSpecular);
|
|||
|
}
|
|||
|
|
|||
|
BillboardMaterial.SetFloat("_Occlusion", VegetationItemInfo.BillboardOcclusion);
|
|||
|
|
|||
|
if (VegetationRenderSettings.ShowLODDebug)
|
|||
|
{
|
|||
|
BillboardMaterial.SetColor("_LODDebugColor", GetLODColor(4));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
BillboardMaterial.SetColor("_LODDebugColor", Color.white);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void CreateBillboardMaterial()
|
|||
|
{
|
|||
|
#if UNITY_2019_3_OR_NEWER
|
|||
|
|
|||
|
if (VegetationItemInfo.BillboardRenderMode == BillboardRenderMode.Standard)
|
|||
|
{
|
|||
|
BillboardMaterial =
|
|||
|
new Material(Shader.Find("AwesomeTechnologies/Release/Billboards/BillboardsMetallic"))
|
|||
|
{
|
|||
|
enableInstancing = true, hideFlags = HideFlags.DontSave
|
|||
|
};
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
BillboardMaterial =
|
|||
|
new Material(Shader.Find("AwesomeTechnologies/Release/Billboards/BetterShaders_GroupBillboards"))
|
|||
|
{
|
|||
|
enableInstancing = true, hideFlags = HideFlags.DontSave
|
|||
|
};
|
|||
|
}
|
|||
|
#else
|
|||
|
if (VegetationItemInfo.BillboardRenderMode == BillboardRenderMode.Standard)
|
|||
|
{
|
|||
|
BillboardMaterial = new Material(Shader.Find("AwesomeTechnologies/Billboards/GroupBillboards")) {
|
|||
|
enableInstancing = true, hideFlags = HideFlags.DontSave
|
|||
|
};
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
BillboardMaterial =
|
|||
|
new Material(Shader.Find("AwesomeTechnologies/Billboards/GroupBillboardsSpecular")) {
|
|||
|
enableInstancing = true, hideFlags = HideFlags.DontSave
|
|||
|
};
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
BillboardMaterial.SetTexture("_MainTex", VegetationItemInfo.BillboardTexture);
|
|||
|
//BillboardMaterial.SetTexture("_AOTex", VegetationItemInfo.BillboardAoTexture);
|
|||
|
BillboardMaterial.SetTexture("_Bump", VegetationItemInfo.BillboardNormalTexture);
|
|||
|
BillboardMaterial.SetInt("_InRow",
|
|||
|
BillboardAtlasRenderer.GetBillboardQualityColumnCount(VegetationItemInfo
|
|||
|
.BillboardQuality));
|
|||
|
BillboardMaterial.SetInt("_InCol",
|
|||
|
BillboardAtlasRenderer.GetBillboardQualityRowCount(VegetationItemInfo
|
|||
|
.BillboardQuality));
|
|||
|
BillboardMaterial.SetInt("_CullDistance", 340);
|
|||
|
BillboardMaterial.SetInt("_FarCullDistance", 5000);
|
|||
|
|
|||
|
// if (Application.isPlaying)
|
|||
|
// {
|
|||
|
// BillboardMaterial.EnableKeyword("AT_CAMERA_SHADER");
|
|||
|
// BillboardMaterial.DisableKeyword("AT_CAMERA_MATERIAL");
|
|||
|
// }
|
|||
|
// else
|
|||
|
// {
|
|||
|
// BillboardMaterial.DisableKeyword("AT_CAMERA_SHADER");
|
|||
|
// BillboardMaterial.EnableKeyword("AT_CAMERA_MATERIAL");
|
|||
|
// }
|
|||
|
|
|||
|
if (ShaderControler != null && ShaderControler.Settings.DynamicHUE)
|
|||
|
{
|
|||
|
BillboardMaterial.EnableKeyword("AT_HUE_VARIATION_ON");
|
|||
|
BillboardMaterial.DisableKeyword("AT_HUE_VARIATION_OFF");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
BillboardMaterial.DisableKeyword("AT_HUE_VARIATION_ON");
|
|||
|
BillboardMaterial.EnableKeyword("AT_HUE_VARIATION_OFF");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (ShaderControler != null)
|
|||
|
{
|
|||
|
if (ShaderControler.Settings.BillboardSnow)
|
|||
|
{
|
|||
|
BillboardMaterial.EnableKeyword("USE_SNOW");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
BillboardMaterial.DisableKeyword("USE_SNOW");
|
|||
|
}
|
|||
|
|
|||
|
if (ShaderControler.Settings.BillboardHDWind)
|
|||
|
{
|
|||
|
BillboardMaterial.EnableKeyword("USE_HDWIND");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
BillboardMaterial.DisableKeyword("USE_HDWIND");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (VegetationItemInfo.OverrideShaderController)
|
|||
|
{
|
|||
|
if (VegetationItemInfo.UseBillboardSnow)
|
|||
|
{
|
|||
|
BillboardMaterial.EnableKeyword("USE_SNOW");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
BillboardMaterial.DisableKeyword("USE_SNOW");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (VegetationItemInfo.OverrideShaderController)
|
|||
|
{
|
|||
|
if (VegetationItemInfo.UseBillboardWind)
|
|||
|
{
|
|||
|
BillboardMaterial.EnableKeyword("USE_HDWIND");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
BillboardMaterial.DisableKeyword("USE_HDWIND");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
UpdateBillboardMaterial();
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
void DisposeCameraBuffers()
|
|||
|
{
|
|||
|
for (int i = 0; i <= CameraComputeBufferList.Count - 1; i++)
|
|||
|
{
|
|||
|
CameraComputeBufferList[i].DestroyComputeBuffers();
|
|||
|
}
|
|||
|
|
|||
|
CameraComputeBufferList.Clear();
|
|||
|
}
|
|||
|
|
|||
|
public void Dispose()
|
|||
|
{
|
|||
|
DestroyMaterials(VegetationMaterialsLOD0);
|
|||
|
DestroyMaterials(VegetationMaterialsLOD1);
|
|||
|
DestroyMaterials(VegetationMaterialsLOD2);
|
|||
|
DestroyMaterials(VegetationMaterialsLOD3);
|
|||
|
|
|||
|
DisposeCameraBuffers();
|
|||
|
|
|||
|
//if (DistanceFalloffCurveArray.IsCreated) DistanceFalloffCurveArray.Dispose();
|
|||
|
|
|||
|
if (HeightRuleCurveArray.IsCreated) HeightRuleCurveArray.Dispose();
|
|||
|
if (SteepnessRuleCurveArray.IsCreated) SteepnessRuleCurveArray.Dispose();
|
|||
|
}
|
|||
|
|
|||
|
//public void UpdateDistanceFalloutCurve()
|
|||
|
//{
|
|||
|
// float[] curveArray = VegetationItemInfo.DistanceFallofffAnimationCurve.GenerateCurveArray();
|
|||
|
// DistanceFalloffCurveArray.CopyFrom(curveArray);
|
|||
|
//}
|
|||
|
|
|||
|
public void UpdateHeightRuleCurve()
|
|||
|
{
|
|||
|
float[] curveArray = VegetationItemInfo.HeightRuleCurve.GenerateCurveArray(4096);
|
|||
|
HeightRuleCurveArray.CopyFrom(curveArray);
|
|||
|
}
|
|||
|
|
|||
|
public void UpdateSteepnessRuleCurve()
|
|||
|
{
|
|||
|
float[] curveArray = VegetationItemInfo.SteepnessRuleCurve.GenerateCurveArray(4096);
|
|||
|
SteepnessRuleCurveArray.CopyFrom(curveArray);
|
|||
|
}
|
|||
|
|
|||
|
private static void DestroyMaterials(Material[] materials)
|
|||
|
{
|
|||
|
for (int i = 0; i <= materials.Length - 1; i++)
|
|||
|
{
|
|||
|
if (Application.isPlaying)
|
|||
|
{
|
|||
|
Object.Destroy(materials[i]);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Object.DestroyImmediate(materials[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static Mesh GetVegetationMesh(GameObject rootVegetationModel, LODLevel lodLevel)
|
|||
|
{
|
|||
|
GameObject selectedVegetationModel = MeshUtils.SelectMeshObject(rootVegetationModel, lodLevel);
|
|||
|
MeshFilter vegetationMeshFilter = selectedVegetationModel.GetComponentInChildren<MeshFilter>();
|
|||
|
|
|||
|
if (vegetationMeshFilter.sharedMesh)
|
|||
|
{
|
|||
|
return vegetationMeshFilter.sharedMesh;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
return new Mesh();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
private static float GetLODDistance(GameObject rootVegetationModel, int lodIndex)
|
|||
|
{
|
|||
|
LODGroup lodGroup = rootVegetationModel.GetComponentInChildren<LODGroup>();
|
|||
|
if (lodGroup)
|
|||
|
{
|
|||
|
LOD[] lods = lodGroup.GetLODs();
|
|||
|
if (lodIndex >= 0 && lodIndex < lods.Length)
|
|||
|
{
|
|||
|
return (lodGroup.size / lods[lodIndex].screenRelativeTransitionHeight);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
private Material[] CreateMaterials(Material[] sharedMaterials, int lodIndex)
|
|||
|
{
|
|||
|
Material[] materials = new Material[sharedMaterials.Length];
|
|||
|
for (int i = 0; i <= sharedMaterials.Length - 1; i++)
|
|||
|
{
|
|||
|
if (sharedMaterials[i])
|
|||
|
{
|
|||
|
materials[i] = new Material(sharedMaterials[i]);
|
|||
|
if (materials[i].shader.name == "Hidden/Nature/Tree Creator Leaves Optimized")
|
|||
|
{
|
|||
|
materials[i].shader = Shader.Find("Nature/Tree Creator Leaves");
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
materials[i] = new Material(Shader.Find("Standard")) {enableInstancing = true};
|
|||
|
}
|
|||
|
|
|||
|
RefreshMaterial(materials[i], lodIndex);
|
|||
|
}
|
|||
|
|
|||
|
return materials;
|
|||
|
}
|
|||
|
|
|||
|
private void RefreshMaterial(Material material, int lodIndex)
|
|||
|
{
|
|||
|
if (material.HasProperty("_CullFarStart"))
|
|||
|
{
|
|||
|
material.SetFloat("_CullFarStart", 100000f);
|
|||
|
}
|
|||
|
|
|||
|
material.enableInstancing = true;
|
|||
|
// if (LODFadePercentage)
|
|||
|
// {
|
|||
|
// if (lodIndex < LODCount - 1)
|
|||
|
// {
|
|||
|
// material.DisableKeyword("LOD_FADE_CROSSFADE");
|
|||
|
// material.EnableKeyword("LOD_FADE_PERCENTAGE");
|
|||
|
// }
|
|||
|
// }
|
|||
|
|
|||
|
// if (LODFadeCrossfade)
|
|||
|
// {
|
|||
|
// //if (lodIndex == LODCount - 1)
|
|||
|
// {
|
|||
|
// material.EnableKeyword("LOD_FADE_CROSSFADE");
|
|||
|
// material.DisableKeyword("LOD_FADE_PERCENTAGE");
|
|||
|
// }
|
|||
|
// }
|
|||
|
//
|
|||
|
// if (!LODFadePercentage && !LODFadeCrossfade)
|
|||
|
// {
|
|||
|
// material.DisableKeyword("LOD_FADE_CROSSFADE");
|
|||
|
// material.DisableKeyword("LOD_FADE_PERCENTAGE");
|
|||
|
// }
|
|||
|
|
|||
|
if (VegetationItemInfo.VegetationRenderMode == VegetationRenderMode.Normal)
|
|||
|
{
|
|||
|
material.DisableKeyword("LOD_FADE_CROSSFADE");
|
|||
|
material.DisableKeyword("LOD_FADE_PERCENTAGE");
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
if (VegetationItemInfo.EnableCrossFade)
|
|||
|
{
|
|||
|
#if USING_HDR
|
|||
|
if (VegetationItemInfo.VegetationRenderMode == VegetationRenderMode.InstancedIndirect)
|
|||
|
{
|
|||
|
material.EnableKeyword("LOD_FADE_CROSSFADE");
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
material.DisableKeyword("LOD_FADE_CROSSFADE");
|
|||
|
}
|
|||
|
#else
|
|||
|
|
|||
|
material.EnableKeyword("LOD_FADE_CROSSFADE");
|
|||
|
#endif
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
material.DisableKeyword("LOD_FADE_CROSSFADE");
|
|||
|
}
|
|||
|
|
|||
|
if (material.HasProperty("_LODDebugColor"))
|
|||
|
{
|
|||
|
if (VegetationRenderSettings.ShowLODDebug)
|
|||
|
{
|
|||
|
material.SetColor("_LODDebugColor", GetLODColor(lodIndex));
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
material.SetColor("_LODDebugColor", Color.white);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
ShaderControler?.UpdateMaterial(material, EnvironmentSettings);
|
|||
|
}
|
|||
|
|
|||
|
Color GetLODColor(int lodIndex)
|
|||
|
{
|
|||
|
switch (lodIndex)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
return Color.green;
|
|||
|
case 1:
|
|||
|
return Color.red;
|
|||
|
case 2:
|
|||
|
return Color.blue;
|
|||
|
case 3:
|
|||
|
return Color.cyan;
|
|||
|
case 4:
|
|||
|
return Color.yellow;
|
|||
|
}
|
|||
|
|
|||
|
return Color.white;
|
|||
|
}
|
|||
|
|
|||
|
public void RefreshMaterials()
|
|||
|
{
|
|||
|
for (int i = 0; i <= VegetationMaterialsLOD0.Length - 1; i++)
|
|||
|
{
|
|||
|
RefreshMaterial(VegetationMaterialsLOD0[i], 0);
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i <= VegetationMaterialsLOD1.Length - 1; i++)
|
|||
|
{
|
|||
|
RefreshMaterial(VegetationMaterialsLOD1[i], 1);
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i <= VegetationMaterialsLOD2.Length - 1; i++)
|
|||
|
{
|
|||
|
RefreshMaterial(VegetationMaterialsLOD2[i], 2);
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i <= VegetationMaterialsLOD3.Length - 1; i++)
|
|||
|
{
|
|||
|
RefreshMaterial(VegetationMaterialsLOD3[i], 3);
|
|||
|
}
|
|||
|
|
|||
|
UpdateBillboardMaterial();
|
|||
|
}
|
|||
|
|
|||
|
//public ComputeBuffer MergeBuffer;
|
|||
|
//public ComputeBuffer VisibleBufferLOD0;
|
|||
|
//public ComputeBuffer VisibleBufferLOD1;
|
|||
|
//public ComputeBuffer VisibleBufferLOD2;
|
|||
|
//public ComputeBuffer VisibleBufferLOD3;
|
|||
|
//private readonly uint[] _args = { 0, 0, 0, 0, 0 };
|
|||
|
//public List<ComputeBuffer> ArgsBufferMergedLOD0List = new List<ComputeBuffer>();
|
|||
|
//public List<ComputeBuffer> ArgsBufferMergedLOD1List = new List<ComputeBuffer>();
|
|||
|
//public List<ComputeBuffer> ArgsBufferMergedLOD2List = new List<ComputeBuffer>();
|
|||
|
//public List<ComputeBuffer> ArgsBufferMergedLOD3List = new List<ComputeBuffer>();
|
|||
|
|
|||
|
public Mesh GetLODMesh(int lodIndex)
|
|||
|
{
|
|||
|
switch (lodIndex)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
return VegetationMeshLod0;
|
|||
|
case 1:
|
|||
|
return VegetationMeshLod1;
|
|||
|
case 2:
|
|||
|
return VegetationMeshLod2;
|
|||
|
case 3:
|
|||
|
return VegetationMeshLod3;
|
|||
|
}
|
|||
|
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
public Material[] GetLODMaterials(int lodIndex)
|
|||
|
{
|
|||
|
switch (lodIndex)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
return VegetationMaterialsLOD0;
|
|||
|
case 1:
|
|||
|
return VegetationMaterialsLOD1;
|
|||
|
case 2:
|
|||
|
return VegetationMaterialsLOD2;
|
|||
|
case 3:
|
|||
|
return VegetationMaterialsLOD3;
|
|||
|
}
|
|||
|
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
public MaterialPropertyBlock GetLODMaterialPropertyBlock(int lodIndex)
|
|||
|
{
|
|||
|
switch (lodIndex)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
return VegetationMaterialPropertyBlockLOD0;
|
|||
|
case 1:
|
|||
|
return VegetationMaterialPropertyBlockLOD1;
|
|||
|
case 2:
|
|||
|
return VegetationMaterialPropertyBlockLOD2;
|
|||
|
case 3:
|
|||
|
return VegetationMaterialPropertyBlockLOD3;
|
|||
|
}
|
|||
|
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
public ComputeBuffer GetLODVisibleBuffer(int lodIndex, int cameraIndex, bool shadows)
|
|||
|
{
|
|||
|
if (shadows)
|
|||
|
{
|
|||
|
switch (lodIndex)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
return CameraComputeBufferList[cameraIndex].ShadowBufferLOD0;
|
|||
|
case 1:
|
|||
|
return CameraComputeBufferList[cameraIndex].ShadowBufferLOD1;
|
|||
|
case 2:
|
|||
|
return CameraComputeBufferList[cameraIndex].ShadowBufferLOD2;
|
|||
|
case 3:
|
|||
|
return CameraComputeBufferList[cameraIndex].ShadowBufferLOD3;
|
|||
|
}
|
|||
|
|
|||
|
return null;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
switch (lodIndex)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
return CameraComputeBufferList[cameraIndex].VisibleBufferLOD0;
|
|||
|
case 1:
|
|||
|
return CameraComputeBufferList[cameraIndex].VisibleBufferLOD1;
|
|||
|
case 2:
|
|||
|
return CameraComputeBufferList[cameraIndex].VisibleBufferLOD2;
|
|||
|
case 3:
|
|||
|
return CameraComputeBufferList[cameraIndex].VisibleBufferLOD3;
|
|||
|
}
|
|||
|
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public List<ComputeBuffer> GetLODArgsBufferList(int lodIndex, int cameraIndex, bool shadows)
|
|||
|
{
|
|||
|
if (shadows)
|
|||
|
{
|
|||
|
switch (lodIndex)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
return CameraComputeBufferList[cameraIndex].ShadowArgsBufferMergedLOD0List;
|
|||
|
case 1:
|
|||
|
return CameraComputeBufferList[cameraIndex].ShadowArgsBufferMergedLOD1List;
|
|||
|
case 2:
|
|||
|
return CameraComputeBufferList[cameraIndex].ShadowArgsBufferMergedLOD2List;
|
|||
|
case 3:
|
|||
|
return CameraComputeBufferList[cameraIndex].ShadowArgsBufferMergedLOD3List;
|
|||
|
}
|
|||
|
|
|||
|
return null;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
switch (lodIndex)
|
|||
|
{
|
|||
|
case 0:
|
|||
|
return CameraComputeBufferList[cameraIndex].ArgsBufferMergedLOD0List;
|
|||
|
case 1:
|
|||
|
return CameraComputeBufferList[cameraIndex].ArgsBufferMergedLOD1List;
|
|||
|
case 2:
|
|||
|
return CameraComputeBufferList[cameraIndex].ArgsBufferMergedLOD2List;
|
|||
|
case 3:
|
|||
|
return CameraComputeBufferList[cameraIndex].ArgsBufferMergedLOD3List;
|
|||
|
}
|
|||
|
|
|||
|
return null;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void CleanVegetationObject(GameObject go)
|
|||
|
{
|
|||
|
Mesh emptyMesh = new Mesh {bounds = new Bounds(new Vector3(0, 0, 0), new Vector3(2, 2, 2))};
|
|||
|
|
|||
|
MeshFilter[] meshFilters = go.GetComponentsInChildren<MeshFilter>();
|
|||
|
for (int i = 0; i <= meshFilters.Length - 1; i++)
|
|||
|
{
|
|||
|
meshFilters[i].sharedMesh = emptyMesh;
|
|||
|
}
|
|||
|
|
|||
|
Rigidbody[] rigidbodies = go.GetComponentsInChildren<Rigidbody>();
|
|||
|
for (int i = 0; i <= rigidbodies.Length - 1; i++)
|
|||
|
{
|
|||
|
if (Application.isPlaying)
|
|||
|
{
|
|||
|
Object.Destroy(rigidbodies[i]);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Object.DestroyImmediate(rigidbodies[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Collider[] colliders = go.GetComponentsInChildren<Collider>();
|
|||
|
for (int i = 0; i <= colliders.Length - 1; i++)
|
|||
|
{
|
|||
|
if (Application.isPlaying)
|
|||
|
{
|
|||
|
Object.Destroy(colliders[i]);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Object.DestroyImmediate(colliders[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BillboardRenderer[] billboardAtlasRenderers = go.GetComponentsInChildren<BillboardRenderer>();
|
|||
|
for (int i = 0; i <= billboardAtlasRenderers.Length - 1; i++)
|
|||
|
{
|
|||
|
if (Application.isPlaying)
|
|||
|
{
|
|||
|
Object.Destroy(billboardAtlasRenderers[i]);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Object.DestroyImmediate(billboardAtlasRenderers[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
NavMeshObstacle[] navMeshObstacles = go.GetComponentsInChildren<NavMeshObstacle>();
|
|||
|
for (int i = 0; i <= navMeshObstacles.Length - 1; i++)
|
|||
|
{
|
|||
|
if (Application.isPlaying)
|
|||
|
{
|
|||
|
Object.Destroy(navMeshObstacles[i]);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Object.DestroyImmediate(navMeshObstacles[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
Transform[] transforms = go.GetComponentsInChildren<Transform>();
|
|||
|
for (int i = 0; i <= transforms.Length - 1; i++)
|
|||
|
{
|
|||
|
if (transforms[i].name.Contains("Billboard"))
|
|||
|
{
|
|||
|
if (Application.isPlaying)
|
|||
|
{
|
|||
|
Object.Destroy(transforms[i].gameObject);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Object.DestroyImmediate(transforms[i].gameObject);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
transforms = go.GetComponentsInChildren<Transform>();
|
|||
|
for (int i = 0; i <= transforms.Length - 1; i++)
|
|||
|
{
|
|||
|
if (transforms[i].name.Contains("CollisionObject"))
|
|||
|
{
|
|||
|
if (Application.isPlaying)
|
|||
|
{
|
|||
|
Object.Destroy(transforms[i].gameObject);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Object.DestroyImmediate(transforms[i].gameObject);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
LODGroup[] lodgroups = go.GetComponentsInChildren<LODGroup>();
|
|||
|
for (int i = 0; i <= lodgroups.Length - 1; i++)
|
|||
|
{
|
|||
|
if (Application.isPlaying)
|
|||
|
{
|
|||
|
Object.Destroy(lodgroups[i]);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
Object.DestroyImmediate(lodgroups[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
MeshRenderer[] meshRenderers = go.GetComponentsInChildren<MeshRenderer>();
|
|||
|
for (int i = 0; i <= meshRenderers.Length - 1; i++)
|
|||
|
{
|
|||
|
meshRenderers[i].shadowCastingMode = ShadowCastingMode.Off;
|
|||
|
meshRenderers[i].receiveShadows = false;
|
|||
|
meshRenderers[i].lightProbeUsage = LightProbeUsage.Off;
|
|||
|
|
|||
|
if (meshRenderers[i].sharedMaterials.Length > 1)
|
|||
|
{
|
|||
|
Material[] materials = new Material[1];
|
|||
|
materials[0] =
|
|||
|
Resources.Load("WindSampler",
|
|||
|
typeof(Material)) as
|
|||
|
Material; //_windSamplerMaterial;//meshRenderers[i].sharedMaterials[0]; //_windSamplerMaterial;//
|
|||
|
meshRenderers[i].sharedMaterials = materials;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|