267 lines
12 KiB
C#
267 lines
12 KiB
C#
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace Assets.ThoMagic.Renderer
|
|
{
|
|
public class ObjectData
|
|
{
|
|
public readonly GameObject GameObject;
|
|
public readonly HashSet<int> Owners = new HashSet<int>();
|
|
public readonly uint prefabId;
|
|
public float[] LodSizes;
|
|
public float[] LodTransitions;
|
|
public LOD[] LODs;
|
|
public Vector4[] lods = new Vector4[8];
|
|
public uint[] indirectArgsPerLodOffsets = new uint[8];
|
|
public uint[] indirectArgsPerLodCounts = new uint[8];
|
|
public uint[] indirectArgsPerLodWithShadowsCounts = new uint[8];
|
|
public List<int> indirectArgsPerSubmeshOffsets = new List<int>();
|
|
public uint lodCount = 1;
|
|
public uint fadeLods = 0;
|
|
public uint indirectArgsCount = 1;
|
|
public uint count = 0;
|
|
public IInstanceRenderSettings Settings;
|
|
|
|
public List<GraphicsBuffer.IndirectDrawIndexedArgs> indirectDrawIndexedArgs = new List<GraphicsBuffer.IndirectDrawIndexedArgs>();
|
|
|
|
public DrawGroup[] drawGroups;
|
|
public DrawGroup[] drawShadowGroups;
|
|
|
|
public int contentHashCache;
|
|
private bool _isDisposed;
|
|
|
|
public ObjectData(GameObject gameObject, IInstanceRenderSettings settings)
|
|
{
|
|
GameObject = gameObject;
|
|
Settings = settings;
|
|
|
|
var lodGroup = GameObject.GetComponent<LODGroup>();
|
|
|
|
LOD[] lodArray;
|
|
|
|
if (lodGroup == null)
|
|
lodArray = new LOD[1]
|
|
{
|
|
new LOD(0.0001f, GameObject.GetComponentsInChildren<MeshRenderer>())
|
|
};
|
|
else
|
|
lodArray = lodGroup.GetLODs();
|
|
|
|
LODs = lodArray;
|
|
|
|
LodSizes = new float[lodArray.Length];
|
|
LodTransitions = new float[lodArray.Length];
|
|
lodCount = (uint)lodArray.Length;
|
|
|
|
if (lodGroup != null && lodGroup.fadeMode == LODFadeMode.CrossFade)
|
|
fadeLods = 1;
|
|
|
|
for (int index = 0; index < lodArray.Length; ++index)
|
|
{
|
|
LodSizes[index] = CalculateBoundsForRenderers(lodArray[index].renderers);
|
|
LodTransitions[index] = lodArray[index].screenRelativeTransitionHeight;
|
|
}
|
|
|
|
if (RendererPool.prefabDataFreeSlot.Count > 0)
|
|
{
|
|
prefabId = RendererPool.prefabDataFreeSlot.Dequeue();
|
|
RendererPool.prefabData[(int)prefabId] = new PrefabData();
|
|
}
|
|
else
|
|
{
|
|
prefabId = (uint)RendererPool.prefabData.Count;
|
|
RendererPool.prefabData.Add(new PrefabData());
|
|
}
|
|
|
|
RendererPool.rebuildPrefabs = true;
|
|
|
|
indirectArgsCount = BuildRenderer(indirectDrawIndexedArgs);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (this._isDisposed)
|
|
return;
|
|
|
|
foreach (var drawGroup in drawGroups)
|
|
{
|
|
drawGroup?.Dispose();
|
|
}
|
|
|
|
foreach (var drawGroup in drawShadowGroups)
|
|
{
|
|
drawGroup?.Dispose();
|
|
}
|
|
|
|
this._isDisposed = true;
|
|
}
|
|
|
|
private uint BuildRenderer(List<GraphicsBuffer.IndirectDrawIndexedArgs> indirectDrawIndexedArgs)
|
|
{
|
|
uint indirectArgsCount = 0;
|
|
|
|
drawGroups = new DrawGroup[lodCount];
|
|
drawShadowGroups = new DrawGroup[lodCount];
|
|
|
|
for (int index = 0; index < lodCount; ++index)
|
|
{
|
|
uint indirectArgsPerLodCount = 0;
|
|
|
|
foreach (var renderer in LODs[index].renderers)
|
|
{
|
|
if (renderer != null)
|
|
{
|
|
if (renderer is MeshRenderer)
|
|
{
|
|
var meshFilter = renderer.GetComponent<MeshFilter>();
|
|
if (meshFilter != null)
|
|
{
|
|
var sharedMesh = meshFilter.sharedMesh;
|
|
var sharedMaterials = renderer.sharedMaterials;
|
|
|
|
if (sharedMesh != null && sharedMaterials != null && sharedMaterials.Length == sharedMesh.subMeshCount)
|
|
{
|
|
if (drawGroups[index] == null)
|
|
drawGroups[index] = new DrawGroup(index);
|
|
|
|
RenderParams renderParams1 = new RenderParams();
|
|
renderParams1.layer = renderer.gameObject.layer;
|
|
renderParams1.receiveShadows = renderer.receiveShadows;
|
|
renderParams1.rendererPriority = renderer.rendererPriority;
|
|
renderParams1.renderingLayerMask = renderer.renderingLayerMask;
|
|
renderParams1.shadowCastingMode = ShadowCastingMode.Off;
|
|
renderParams1.reflectionProbeUsage = renderer.reflectionProbeUsage;
|
|
renderParams1.motionVectorMode = renderer.motionVectorGenerationMode;
|
|
|
|
var count = drawGroups[index].Add(sharedMesh, sharedMaterials, Matrix4x4.identity, //renderer.transform.localToWorldMatrix,
|
|
indirectArgsCount, indirectDrawIndexedArgs, in renderParams1);
|
|
indirectArgsPerLodCount += count;
|
|
|
|
}
|
|
}
|
|
}
|
|
else if (renderer is BillboardRenderer billboardRenderer)
|
|
{
|
|
if (billboardRenderer.billboard != null && billboardRenderer.billboard.material != null)
|
|
{
|
|
if (drawGroups[index] == null)
|
|
drawGroups[index] = new DrawGroup(index);
|
|
|
|
RenderParams renderParams1 = new RenderParams();
|
|
renderParams1.layer = renderer.gameObject.layer;
|
|
renderParams1.receiveShadows = renderer.receiveShadows;
|
|
renderParams1.rendererPriority = renderer.rendererPriority;
|
|
renderParams1.renderingLayerMask = renderer.renderingLayerMask;
|
|
renderParams1.shadowCastingMode = ShadowCastingMode.Off;
|
|
renderParams1.reflectionProbeUsage = renderer.reflectionProbeUsage;
|
|
renderParams1.motionVectorMode = renderer.motionVectorGenerationMode;
|
|
|
|
var count = drawGroups[index].Add(billboardRenderer.billboard, billboardRenderer.material, renderer.transform.localToWorldMatrix,
|
|
indirectArgsCount, indirectDrawIndexedArgs, in renderParams1);
|
|
|
|
indirectArgsPerLodCount += count;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
indirectArgsPerLodCounts[index] = indirectArgsPerLodCount;
|
|
uint indirectArgsPerLodCountShadowOffset = indirectArgsPerLodCount;
|
|
|
|
foreach (var renderer in LODs[index].renderers)
|
|
{
|
|
if (renderer != null)
|
|
{
|
|
if (renderer is MeshRenderer)
|
|
{
|
|
var meshFilter = renderer.GetComponent<MeshFilter>();
|
|
if (meshFilter != null)
|
|
{
|
|
var sharedMesh = meshFilter.sharedMesh;
|
|
var sharedMaterials = renderer.sharedMaterials;
|
|
|
|
if (sharedMesh != null && sharedMaterials != null && sharedMaterials.Length == sharedMesh.subMeshCount)
|
|
{
|
|
if (renderer.shadowCastingMode > 0)
|
|
{
|
|
if (drawShadowGroups[index] == null)
|
|
drawShadowGroups[index] = new DrawGroup(index);
|
|
|
|
var renderParams1 = new RenderParams();
|
|
renderParams1.layer = renderer.gameObject.layer;
|
|
renderParams1.shadowCastingMode = ShadowCastingMode.ShadowsOnly;
|
|
renderParams1.renderingLayerMask = renderer.renderingLayerMask;
|
|
renderParams1.rendererPriority = renderer.rendererPriority;
|
|
|
|
indirectArgsPerLodCount += drawShadowGroups[index].Add(sharedMesh, sharedMaterials, Matrix4x4.identity, //renderer.transform.localToWorldMatrix,
|
|
indirectArgsPerLodCountShadowOffset + indirectArgsCount, indirectDrawIndexedArgs, in renderParams1);
|
|
}
|
|
else
|
|
{
|
|
//indirectArgsPerLodCount += (uint)sharedMesh.subMeshCount;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (renderer is BillboardRenderer billboardRenderer)
|
|
{
|
|
if (renderer.shadowCastingMode > 0)
|
|
{
|
|
if (billboardRenderer.billboard != null && billboardRenderer.billboard.material != null)
|
|
{
|
|
if (drawShadowGroups[index] == null)
|
|
drawShadowGroups[index] = new DrawGroup(index);
|
|
|
|
var renderParams1 = new RenderParams();
|
|
renderParams1.layer = renderer.gameObject.layer;
|
|
renderParams1.shadowCastingMode = ShadowCastingMode.ShadowsOnly;
|
|
renderParams1.renderingLayerMask = renderer.renderingLayerMask;
|
|
renderParams1.rendererPriority = renderer.rendererPriority;
|
|
|
|
indirectArgsPerLodCount += drawShadowGroups[index].Add(billboardRenderer.billboard, billboardRenderer.material, renderer.transform.localToWorldMatrix,
|
|
indirectArgsPerLodCountShadowOffset + indirectArgsCount, indirectDrawIndexedArgs, in renderParams1);
|
|
}
|
|
else
|
|
{
|
|
//indirectArgsPerLodCount += 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
indirectArgsPerLodWithShadowsCounts[index] = indirectArgsPerLodCount;
|
|
indirectArgsCount += indirectArgsPerLodCount;
|
|
}
|
|
|
|
return indirectArgsCount;
|
|
}
|
|
|
|
private static float CalculateBoundsForRenderers(UnityEngine.Renderer[] renderers)
|
|
{
|
|
Bounds bounds = new Bounds();
|
|
bool first = true;
|
|
foreach (var renderer in renderers)
|
|
{
|
|
if (renderer != null)
|
|
{
|
|
if (first)
|
|
{
|
|
bounds = renderer.bounds;
|
|
first = false;
|
|
}
|
|
else
|
|
bounds.Encapsulate(renderer.bounds);
|
|
}
|
|
}
|
|
return Mathf.Max(Mathf.Max(bounds.size.x, bounds.size.y), bounds.size.z);
|
|
}
|
|
|
|
public override int GetHashCode()
|
|
{
|
|
return GameObject.GetHashCode();
|
|
}
|
|
}
|
|
}
|