2025-06-23 19:18:41 +08:00
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using Unity.Mathematics;
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.Experimental.Rendering;
|
|
|
|
|
|
|
|
|
|
namespace X.Rendering.Feature
|
|
|
|
|
{
|
|
|
|
|
public class HizObjectsManager : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
public bool ShowDebug = false;
|
|
|
|
|
Texture2D centerTex;
|
|
|
|
|
Texture2D sizeTex;
|
|
|
|
|
|
|
|
|
|
private static HizObjectsManager intstance;
|
|
|
|
|
public static HizObjectsManager Instance => intstance;
|
|
|
|
|
|
|
|
|
|
private float4[] centers;
|
|
|
|
|
private float4[] extents;
|
|
|
|
|
|
|
|
|
|
private float3x2[] aabbs;
|
|
|
|
|
|
|
|
|
|
private List<MeshRenderer> renderers = new();
|
|
|
|
|
private bool[] cullResults;
|
|
|
|
|
private bool needUpdateAABB = true;
|
|
|
|
|
|
|
|
|
|
public int culledCnt = 0;
|
|
|
|
|
|
|
|
|
|
private void Awake()
|
|
|
|
|
{
|
|
|
|
|
intstance = new();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Start()
|
|
|
|
|
{
|
|
|
|
|
int texSize = 64;
|
|
|
|
|
centerTex = new Texture2D(texSize, texSize, TextureFormat.RGBAFloat, 0, true);
|
|
|
|
|
centerTex.filterMode = FilterMode.Point;
|
|
|
|
|
sizeTex = new Texture2D(texSize, texSize, TextureFormat.RGBAFloat, 0, true);
|
|
|
|
|
sizeTex.filterMode = FilterMode.Point;
|
|
|
|
|
Shader.SetGlobalTexture(HizShaderIds.ObjectAABBCenterId, centerTex);
|
|
|
|
|
Shader.SetGlobalTexture(HizShaderIds.ObjectAABBSizeId, sizeTex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Update()
|
|
|
|
|
{
|
|
|
|
|
if (needUpdateAABB)
|
|
|
|
|
{
|
|
|
|
|
needUpdateAABB = false;
|
|
|
|
|
UpdateAABB(centerTex, sizeTex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnDestroy()
|
|
|
|
|
{
|
|
|
|
|
Texture.DestroyImmediate(centerTex);
|
|
|
|
|
Texture.DestroyImmediate(sizeTex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void LateUpdate()
|
|
|
|
|
{
|
|
|
|
|
ApplyCull(HierarchicalZOcclusionCullFeature.GetCullResult());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Register(MeshRenderer renderer)
|
|
|
|
|
{
|
|
|
|
|
if (!renderers.Contains(renderer))
|
|
|
|
|
{
|
|
|
|
|
renderers.Add(renderer);
|
|
|
|
|
needUpdateAABB = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UnRegister(MeshRenderer renderer)
|
|
|
|
|
{
|
|
|
|
|
if(renderers.Remove(renderer))
|
|
|
|
|
{
|
|
|
|
|
needUpdateAABB = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UpdateAABB(ComputeBuffer aabbBuffer)
|
|
|
|
|
{
|
|
|
|
|
if (aabbBuffer == null || aabbs.Length != renderers.Count)
|
|
|
|
|
{
|
|
|
|
|
aabbs = new float3x2[renderers.Count];
|
|
|
|
|
}
|
|
|
|
|
for (int i = 0; i < renderers.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var rdr = renderers[i];
|
|
|
|
|
if (rdr != null)
|
|
|
|
|
{
|
|
|
|
|
Bounds bounds = rdr.bounds;
|
|
|
|
|
aabbs[i] = new float3x2(bounds.center, bounds.size);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
aabbs[i] = float3x2.zero;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
aabbBuffer.SetData(aabbs);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void UpdateAABB(Texture2D centerTex, Texture2D sizeTex)
|
|
|
|
|
{
|
|
|
|
|
if (centers == null || centers.Length != centerTex.width * centerTex.height)
|
|
|
|
|
{
|
|
|
|
|
centers = new float4[centerTex.width * centerTex.height];
|
|
|
|
|
extents = new float4[centerTex.width * centerTex.height];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (renderers.Count == 0)
|
|
|
|
|
{
|
|
|
|
|
foreach (var item in GameObject.FindObjectsOfType<MeshRenderer>())
|
|
|
|
|
{
|
|
|
|
|
if (item.gameObject.isStatic)
|
|
|
|
|
{
|
|
|
|
|
Register(item);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (cullResults == null || cullResults.Length != renderers.Count)
|
|
|
|
|
{
|
|
|
|
|
cullResults = new bool[renderers.Count];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int nullCnt = 0;
|
|
|
|
|
for (int i = 0; i < renderers.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var rdr = renderers[i];
|
|
|
|
|
if (rdr != null)
|
|
|
|
|
{
|
|
|
|
|
Bounds bounds = rdr.bounds;
|
|
|
|
|
centers[i] = new float4(bounds.center, 1);
|
|
|
|
|
extents[i] = new float4(bounds.extents, 1);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
nullCnt++;
|
|
|
|
|
centers[i] = float4.zero;
|
|
|
|
|
extents[i] = float4.zero;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nullCnt == renderers.Count)
|
|
|
|
|
{
|
|
|
|
|
renderers.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
centerTex.SetPixelData(centers, 0);
|
|
|
|
|
centerTex.Apply();
|
|
|
|
|
sizeTex.SetPixelData(extents, 0);
|
|
|
|
|
sizeTex.Apply();
|
|
|
|
|
Shader.SetGlobalTexture(HizShaderIds.ObjectAABBCenterId, centerTex);
|
|
|
|
|
Shader.SetGlobalTexture(HizShaderIds.ObjectAABBSizeId, sizeTex);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ApplyCull(CullResult cullResult)
|
|
|
|
|
{
|
|
|
|
|
if (cullResult.ReadDone)
|
|
|
|
|
{
|
|
|
|
|
culledCnt = 0;
|
|
|
|
|
for (var i = 0; i < renderers.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var rdr = renderers[i];
|
2025-06-24 21:26:55 +08:00
|
|
|
if (rdr && cullResult.ResultArray.IsCreated)
|
2025-06-23 19:18:41 +08:00
|
|
|
{
|
|
|
|
|
bool needCull = cullResult.ResultArray[i] > 0;
|
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
|
if (ShowDebug && rdr.GetComponent<CullDebug>() is CullDebug cullDebug && cullDebug)
|
|
|
|
|
{
|
|
|
|
|
cullDebug.Index = i;
|
|
|
|
|
cullDebug.IsCulled = needCull;
|
|
|
|
|
cullDebug.Position = centers[i].xyz;
|
|
|
|
|
cullDebug.Size = extents[i].xyz;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
if (needCull)
|
|
|
|
|
{
|
|
|
|
|
culledCnt++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (cullResults[i] != needCull)
|
|
|
|
|
{
|
|
|
|
|
if (needCull)
|
|
|
|
|
{
|
|
|
|
|
culledCnt++;
|
|
|
|
|
rdr.renderingLayerMask = 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
rdr.renderingLayerMask = 1;
|
|
|
|
|
}
|
|
|
|
|
cullResults[i] = needCull;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Debug.Log("frameCount: " + Time.frameCount + " Buffer index " + Time.frameCount % 3 + " : cullcount = " + culledCnt);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ResetRenderer();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ResetRenderer()
|
|
|
|
|
{
|
|
|
|
|
for (var i = 0; i < renderers.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var rdr = renderers[i];
|
|
|
|
|
if (rdr)
|
|
|
|
|
{
|
|
|
|
|
if (cullResults[i])
|
|
|
|
|
{
|
|
|
|
|
rdr.renderingLayerMask = 1;
|
|
|
|
|
cullResults[i] = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnDisable()
|
|
|
|
|
{
|
|
|
|
|
ResetRenderer();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|