// Update is called once per frame void Update() { var ProjMatrix = Camera.main.projectionMatrix; var ViewMatrix = Camera.main.worldToCameraMatrix; var ViewProjMatrix = ProjMatrix * ViewMatrix; var Row3 = ViewProjMatrix.GetRow(3); var Row0 = ViewProjMatrix.GetRow(0); var Row1 = ViewProjMatrix.GetRow(1); var Row2 = ViewProjMatrix.GetRow(2); var PlaneL = NormalizePlane(Row3 + Row0); var PlaneR = NormalizePlane(Row3 - Row0); var PlaneT = NormalizePlane(Row3 - Row1); var PlaneB = NormalizePlane(Row3 + Row1); var PlaneN = NormalizePlane(Row3 + Row2); var PlaneF = NormalizePlane(Row3 - Row2); var PointNTL = PointFrom3Planes(PlaneN, PlaneT, PlaneL); var PointNTR = PointFrom3Planes(PlaneN, PlaneT, PlaneR); var PointNBL = PointFrom3Planes(PlaneN, PlaneB, PlaneL); var PointNBR = PointFrom3Planes(PlaneN, PlaneB, PlaneR); DebugDrawCross(PointNTL, RayDirFromPlanes(PlaneT, PlaneL), 0.3f); DebugDrawCross(PointNTR, RayDirFromPlanes(PlaneR, PlaneT), 0.3f); DebugDrawCross(PointNBL, RayDirFromPlanes(PlaneL, PlaneB), 0.3f); DebugDrawCross(PointNBR, RayDirFromPlanes(PlaneB, PlaneR), 0.3f); var PointFTL = PointFrom3Planes(PlaneF, PlaneT, PlaneL); var PointFTR = PointFrom3Planes(PlaneF, PlaneT, PlaneR); var PointFBL = PointFrom3Planes(PlaneF, PlaneB, PlaneL); var PointFBR = PointFrom3Planes(PlaneF, PlaneB, PlaneR); var FrustumAABBMin = Vector3.Min(Vector3.Min(Vector3.Min(PointFTL, PointFTR), Vector3.Min(PointFBL, PointFBR)), Vector3.Min(Vector3.Min(PointNTL, PointNTR), Vector3.Min(PointNBL, PointNBR))); var FrustumAABBMax = Vector3.Max(Vector3.Max(Vector3.Max(PointFTL, PointFTR), Vector3.Max(PointFBL, PointFBR)), Vector3.Max(Vector3.Max(PointNTL, PointNTR), Vector3.Max(PointNBL, PointNBR))); DebugDrawCross(PointFTL, -RayDirFromPlanes(PlaneT, PlaneL), 1.3f); DebugDrawCross(PointFTR, -RayDirFromPlanes(PlaneR, PlaneT), 1.3f); DebugDrawCross(PointFBL, -RayDirFromPlanes(PlaneL, PlaneB), 1.3f); DebugDrawCross(PointFBR, -RayDirFromPlanes(PlaneB, PlaneR), 1.3f); FrustumData.Array[0] = PlaneL; FrustumData.Array[1] = PlaneR; FrustumData.Array[2] = PlaneT; FrustumData.Array[3] = PlaneB; FrustumData.Array[4] = PlaneN; FrustumData.Array[5] = PlaneF; FrustumData.Array[6] = new Vector4(FrustumAABBMin.x, FrustumAABBMax.x, FrustumAABBMin.y, FrustumAABBMax.y); FrustumData.Array[7] = new Vector4(FrustumAABBMin.z, FrustumAABBMax.z, FrustumAABBMin.z, FrustumAABBMax.z); int NumSoAPackets = (NumMeshTranforms + 3) >> 2; NumMeshTranforms = NumSoAPackets << 2; if (PrevNumMeshTransforms != NumMeshTranforms) { Debug.Log("Re-allocate AABB data because of size change."); VisibilityMask.Reserve((NumSoAPackets + 1) >> 1); VisibilityMaskForParallel = new byte[NumSoAPackets]; BoxesMinMaxAoSoA.Reserve(NumSoAPackets * 6); Debug.Log("Native" + BoxesMinMaxAoSoANative); if (BoxesMinMaxAoSoANative.IsCreated) { BoxesMinMaxAoSoANative.Dispose(); } BoxesMinMaxAoSoANative = new NativeArray <Vector4>(BoxesMinMaxAoSoA.Array, Allocator.Persistent); MeshTransforms = new Matrix4x4[NumMeshTranforms]; RandomizeBoxes = true; } PrevNumMeshTransforms = NumMeshTranforms; if (RandomizeBoxes) { UnityEngine.Random.InitState((int)(Time.time * 1000.0f)); for (int i = 0; i < NumSoAPackets; ++i) { var c0 = RandomCenter(); var e0 = RandomExtent(); var c1 = RandomCenter(); var e1 = RandomExtent(); var c2 = RandomCenter(); var e2 = RandomExtent(); var c3 = RandomCenter(); var e3 = RandomExtent(); BoxesMinMaxAoSoA.Array[i * 6 + 0] = new Vector4(c0[0] - e0[0], c1[0] - e1[0], c2[0] - e2[0], c3[0] - e3[0]); BoxesMinMaxAoSoA.Array[i * 6 + 1] = new Vector4(c0[0] + e0[0], c1[0] + e1[0], c2[0] + e2[0], c3[0] + e3[0]); BoxesMinMaxAoSoA.Array[i * 6 + 2] = new Vector4(c0[1] - e0[1], c1[1] - e1[1], c2[1] - e2[1], c3[1] - e3[1]); BoxesMinMaxAoSoA.Array[i * 6 + 3] = new Vector4(c0[1] + e0[1], c1[1] + e1[1], c2[1] + e2[1], c3[1] + e3[1]); BoxesMinMaxAoSoA.Array[i * 6 + 4] = new Vector4(c0[2] - e0[2], c1[2] - e1[2], c2[2] - e2[2], c3[2] - e3[2]); BoxesMinMaxAoSoA.Array[i * 6 + 5] = new Vector4(c0[2] + e0[2], c1[2] + e1[2], c2[2] + e2[2], c3[2] + e3[2]); } BoxesMinMaxAoSoANative.CopyFrom(BoxesMinMaxAoSoA.Array); RandomizeBoxes = false; } if (CullingJobType == JobType.ReferenceSerialOnly || CullingJobType == JobType.NativePluginSerialOnly) { CullingJobParallel = false; } if (CullingJobType == JobType.ReferenceSerialOnly) { UnityEngine.Profiling.Profiler.BeginSample("CullBoxesAoSoA_Default"); CullBoxesAoSoA_Default( ref VisibilityMask.Array, ref BoxesMinMaxAoSoA.Array, ref FrustumData.Array, FrustumAABBMax, FrustumAABBMin, TestFrustumCorners); UnityEngine.Profiling.Profiler.EndSample(); } else if (CullingJobType == JobType.NativePluginSerialOnly) { UnityEngine.Profiling.Profiler.BeginSample("UnityNativePlugin_CountCulledBoxesAoSoA"); UnityNativePlugin_CountCulledBoxesAoSoA( VisibilityMask.Address(), BoxesMinMaxAoSoA.Address(), FrustumData.Address(), NumSoAPackets); UnityEngine.Profiling.Profiler.EndSample(); } else { if (CullingJobParallel) { UnityEngine.Profiling.Profiler.BeginSample("BeginCullBoxesAoSoA_Parallel"); if (CullingJobType == JobType.MathematicsBurstOptimized) { ParallelCullingJob = new CullingJob_Parallel(); CullingJobHandle = ParallelCullingJob.Run(ref BoxesMinMaxAoSoANative, ref FrustumData.Array, TestFrustumCorners); } else { ParallelCullingJobNoBurst = new CullingJob_ParallelNoBurst(); CullingJobHandle = ParallelCullingJobNoBurst.Run(ref BoxesMinMaxAoSoANative, ref FrustumData.Array, TestFrustumCorners); } UnityEngine.Profiling.Profiler.EndSample(); } else { UnityEngine.Profiling.Profiler.BeginSample("BeginCullBoxesAoSoA_Serial"); if (CullingJobType == JobType.MathematicsBurstOptimized) { SerialCullingJob = new CullingJob_Serial(); CullingJobHandle = SerialCullingJob.Run(ref BoxesMinMaxAoSoANative, ref FrustumData.Array, TestFrustumCorners); } else { SerialCullingJobNoBurst = new CullingJob_SerialNoBurst(); CullingJobHandle = SerialCullingJobNoBurst.Run(ref BoxesMinMaxAoSoANative, ref FrustumData.Array, TestFrustumCorners); } UnityEngine.Profiling.Profiler.EndSample(); } } }