using Unity.Burst; using Unity.Entities; using Unity.Mathematics; using Unity.Rendering; namespace GarmentButton.Culling { public partial struct CullingSystem : ISystem { [BurstCompile] public void OnCreate(ref SystemState state) { state.RequireForUpdate(); state.RequireForUpdate(); state.RequireForUpdate(); } [BurstCompile] public void OnUpdate(ref SystemState state) { var ecbSingleton = SystemAPI.GetSingleton() .CreateCommandBuffer(state.WorldUnmanaged).AsParallelWriter(); var cameraFrustumPlanes = SystemAPI.GetSingleton(); state.Dependency = new CullJob() { Planes = cameraFrustumPlanes, Ecb = ecbSingleton }.ScheduleParallel(state.Dependency); } } [BurstCompile] [WithAll(typeof(VisibleTag))] [WithOptions(EntityQueryOptions.IgnoreComponentEnabledState)] public partial struct CullJob : IJobEntity { public CameraFrustumPlanes Planes; public EntityCommandBuffer.ParallelWriter Ecb; [BurstCompile] private void Execute([EntityIndexInQuery] int sortKey, Entity e, in WorldRenderBounds wrb) { var aabb = wrb.Value; // Unity.Mathematics.AABB (Center, Extents) bool visible = AabbInsideFrustum(aabb.Center, aabb.Extents); Ecb.SetComponentEnabled(sortKey, e, visible); } [BurstCompile] private bool AabbInsideFrustum(float3 center, float3 extents) { return AabbInsidePlane(center, extents, Planes.P0) && AabbInsidePlane(center, extents, Planes.P1) && AabbInsidePlane(center, extents, Planes.P2) && AabbInsidePlane(center, extents, Planes.P3) && AabbInsidePlane(center, extents, Planes.P4) && AabbInsidePlane(center, extents, Planes.P5); } // [BurstCompile] private bool AabbInsidePlane(float3 c, float3 e, float4 plane) { float3 n = plane.xyz; float d = plane.w; // Project extents onto plane normal (abs(n) dot extents) float r = math.dot(math.abs(n), e); float s = math.dot(n, c) + d; // Outside if s + r < 0 return (s + r) >= 0f; } } }