Пример #1
0
    // 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();
            }
        }
    }