public static void DispatchCull(this ScriptableRenderContext RenderContext, FGPUScene GPUScene, ref ScriptableCullingParameters CullingParameters, ref FCullingData CullingData)
        {
            CullingData.CullState = false;
            if (GPUScene.MeshBatchs.IsCreated == false || CullingData.bRendererView != true)
            {
                return;
            }
            CullingData.CullState = true;

            CullingData.ViewFrustum = new NativeArray <FPlane>(6, Allocator.TempJob);
            for (int PlaneIndex = 0; PlaneIndex < 6; PlaneIndex++)
            {
                CullingData.ViewFrustum[PlaneIndex] = CullingParameters.GetCullingPlane(PlaneIndex);
            }

            CullingData.ViewMeshBatchs = new NativeList <int>(GPUScene.MeshBatchs.Length, Allocator.TempJob);
            CullingData.ViewMeshBatchs.Resize(GPUScene.MeshBatchs.Length, NativeArrayOptions.ClearMemory);

            FMeshBatchCullingJob MeshBatchCullingJob = new FMeshBatchCullingJob();

            {
                MeshBatchCullingJob.ViewFrustum    = CullingData.ViewFrustum;
                MeshBatchCullingJob.MeshBatchs     = GPUScene.MeshBatchs;
                MeshBatchCullingJob.ViewMeshBatchs = CullingData.ViewMeshBatchs;
            }
            MeshBatchCullingJob.Schedule(GPUScene.MeshBatchs.Length, 256).Complete();
        }
        public void SetupCulling(ref ScriptableCullingParameters cullingParameters, Camera camera)
        {
            Profiler.BeginSample("Cull 2D Lights");
            m_VisibleLights.Clear();
            foreach (var light in Light2DManager.lights)
            {
                if ((camera.cullingMask & (1 << light.gameObject.layer)) == 0)
                {
                    continue;
                }

#if UNITY_EDITOR
                if (!UnityEditor.SceneManagement.StageUtility.IsGameObjectRenderedByCamera(light.gameObject, camera))
                {
                    continue;
                }
#endif

                if (light.lightType == Light2D.LightType.Global)
                {
                    m_VisibleLights.Add(light);
                    continue;
                }

                Profiler.BeginSample("Test Planes");
                var position = light.boundingSphere.position;
                var culled   = false;
                for (var i = 0; i < cullingParameters.cullingPlaneCount; ++i)
                {
                    var plane = cullingParameters.GetCullingPlane(i);
                    // most of the time is spent getting world position
                    var distance = math.dot(position, plane.normal) + plane.distance;
                    if (distance < -light.boundingSphere.radius)
                    {
                        culled = true;
                        break;
                    }
                }
                Profiler.EndSample();
                if (culled)
                {
                    continue;
                }

                m_VisibleLights.Add(light);
            }

            // must be sorted here because light order could change
            m_VisibleLights.Sort((l1, l2) => l1.lightOrder - l2.lightOrder);
            Profiler.EndSample();
        }
Example #3
0
        private void SetUpBuffers()
        {
            RTBuffers.ResizeBufferIfNeed(this);

            for (int i = 0; i < 6; i++)
            {
                Plane p = cullParams.GetCullingPlane(i);

                frustumPlane[i]   = -p.normal;
                frustumPlane[i].w = p.distance;
            }

            PipelineContext.mainCmdBuffer.SetRenderTarget(RTBuffers.frameBuffer, RTBuffers.depthBuffer);
            PipelineContext.mainCmdBuffer.ClearRenderTarget(true, true, hostCamera.backgroundColor);

            PipelineContext.ExecuteMainCommandBuffer();
        }
Example #4
0
        private bool StartCullingIfVisible(ScriptableRenderContext context, Camera cam)
        {
            if (m_frustumVertices == null)
            {
                return(false);
            }
            ScriptableCullingParameters cullingParameters = new ScriptableCullingParameters();

            if (!cam.TryGetCullingParameters(IsStereoEnabled(cam), out cullingParameters))
            {
                return(false);
            }
            if (m_temporaryData == null)
            {
                m_temporaryData = new TemporaryData();
            }
            uint  flags   = 0xff;
            ulong flags64 = 0;

            for (int i = 0; i < 8; ++i)
            {
                Vector3 v = m_temporaryData.m_vertices[i] = transform.TransformPoint(m_frustumVertices[i]);
                uint    f = 0;
                for (int j = 0; j < cullingParameters.cullingPlaneCount; ++j)
                {
                    Plane plane = cullingParameters.GetCullingPlane(j);
                    if (plane.GetDistanceToPoint(v) < 0)
                    {
                        f |= (1U << j);
                    }
                }
                flags   &= f;
                flags64 |= (((ulong)f) << (8 * i));
            }
            if (flags != 0)
            {
                // projector is not visible from the camera
                return(false);
            }
            if (!m_requiresCullingResult)
            {
                return(true);
            }
            uint cameraPlanes = 0;
            int  planeCount   = 0;

            // -x
            flags = (uint)((flags64 >> 0) & (flags64 >> 8) & (flags64 >> 32) & (flags64 >> 40)) & 0xFF;
            if (flags == 0)
            {
                m_temporaryData.m_clipPlanes[planeCount++] = new Plane(m_temporaryData.m_vertices[0], m_temporaryData.m_vertices[1], m_temporaryData.m_vertices[4]);
            }
            else
            {
                cameraPlanes |= flags;
            }
            // +x
            flags = (uint)((flags64 >> 16) & (flags64 >> 24) & (flags64 >> 48) & (flags64 >> 56)) & 0xFF;
            if (flags == 0)
            {
                m_temporaryData.m_clipPlanes[planeCount++] = new Plane(m_temporaryData.m_vertices[3], m_temporaryData.m_vertices[2], m_temporaryData.m_vertices[7]);
            }
            else
            {
                cameraPlanes |= flags;
            }
            // -y
            flags = (uint)((flags64 >> 0) & (flags64 >> 16) & (flags64 >> 32) & (flags64 >> 48)) & 0xFF;
            if (flags == 0)
            {
                m_temporaryData.m_clipPlanes[planeCount++] = new Plane(m_temporaryData.m_vertices[2], m_temporaryData.m_vertices[0], m_temporaryData.m_vertices[6]);
            }
            else
            {
                cameraPlanes |= flags;
            }
            // +y
            flags = (uint)((flags64 >> 8) & (flags64 >> 24) & (flags64 >> 40) & (flags64 >> 56)) & 0xFF;
            if (flags == 0)
            {
                m_temporaryData.m_clipPlanes[planeCount++] = new Plane(m_temporaryData.m_vertices[1], m_temporaryData.m_vertices[3], m_temporaryData.m_vertices[5]);
            }
            else
            {
                cameraPlanes |= flags;
            }
            // near
            flags = (uint)((flags64 >> 0) & (flags64 >> 8) & (flags64 >> 16) & (flags64 >> 24)) & 0xFF;
            if (flags == 0)
            {
                m_temporaryData.m_clipPlanes[planeCount++] = new Plane(m_temporaryData.m_vertices[0], m_temporaryData.m_vertices[2], m_temporaryData.m_vertices[1]);
            }
            else
            {
                cameraPlanes |= flags;
            }
            // far
            flags = (uint)((flags64 >> 32) & (flags64 >> 40) & (flags64 >> 48) & (flags64 >> 56)) & 0xFF;
            if (flags == 0)
            {
                m_temporaryData.m_clipPlanes[planeCount++] = new Plane(m_temporaryData.m_vertices[4], m_temporaryData.m_vertices[5], m_temporaryData.m_vertices[6]);
            }
            else
            {
                cameraPlanes |= flags;
            }
            int maxPlaneCount = ScriptableCullingParameters.maximumCullingPlaneCount;

            for (int i = 0; i < cullingParameters.cullingPlaneCount && planeCount < maxPlaneCount; ++i)
            {
                if ((cameraPlanes & (1U << i)) != 0)
                {
                    m_temporaryData.m_clipPlanes[planeCount++] = cullingParameters.GetCullingPlane(i);
                }
            }
            cullingParameters.cullingPlaneCount = planeCount;
            for (int i = 0; i < planeCount; ++i)
            {
                cullingParameters.SetCullingPlane(i, m_temporaryData.m_clipPlanes[i]);
            }
#if DEBUG
            // To avoid the error: Assertion failed on expression: 'params.cullingPlaneCount == kPlaneFrustumNum'
            cullingParameters.cullingPlaneCount = 6;
#endif
            cullingParameters.cullingOptions &= ~(CullingOptions.NeedsReflectionProbes | CullingOptions.ShadowCasters);
            CullingResults cullingResults = context.Cull(ref cullingParameters);
            m_cullingResults.Add(cam, cullingResults);
            return(true);
        }
Example #5
0
        private bool StartCullingIfVisible(ScriptableRenderContext context, Camera cam)
        {
            if (m_frustumVertices == null)
            {
                return(false);
            }
            ScriptableCullingParameters cullingParameters = new ScriptableCullingParameters();

            if (!cam.TryGetCullingParameters(IsStereoEnabled(cam), out cullingParameters))
            {
                return(false);
            }
            if (m_temporaryData == null)
            {
                m_temporaryData = new TemporaryData();
            }
            uint  flags   = 0xff;
            ulong flags64 = 0;

            for (int i = 0; i < 8; ++i)
            {
                Vector3 v = m_temporaryData.m_vertices[i] = transform.TransformPoint(m_frustumVertices[i]);
                uint    f = 0;
                for (int j = 0; j < cullingParameters.cullingPlaneCount; ++j)
                {
                    Plane plane = cullingParameters.GetCullingPlane(j);
                    if (plane.GetDistanceToPoint(v) < 0)
                    {
                        f |= (1U << j);
                    }
                }
                flags   &= f;
                flags64 |= (((ulong)f) << (8 * i));
            }
            if (flags != 0)
            {
                // projector is not visible from the camera
                return(false);
            }
            if (!m_requiresCullingResult)
            {
                return(true);
            }
            uint cameraPlanes = 0;
            int  planeCount   = 0;

            // -x
            flags = (uint)((flags64 >> 0) & (flags64 >> 8) & (flags64 >> 32) & (flags64 >> 40)) & 0xFF;
            if (flags == 0)
            {
                m_temporaryData.m_clipPlanes[planeCount++] = new Plane(m_temporaryData.m_vertices[0], m_temporaryData.m_vertices[1], m_temporaryData.m_vertices[4]);
            }
            else
            {
                cameraPlanes |= flags;
            }
            // +x
            flags = (uint)((flags64 >> 16) & (flags64 >> 24) & (flags64 >> 48) & (flags64 >> 56)) & 0xFF;
            if (flags == 0)
            {
                m_temporaryData.m_clipPlanes[planeCount++] = new Plane(m_temporaryData.m_vertices[3], m_temporaryData.m_vertices[2], m_temporaryData.m_vertices[7]);
            }
            else
            {
                cameraPlanes |= flags;
            }
            // -y
            flags = (uint)((flags64 >> 0) & (flags64 >> 16) & (flags64 >> 32) & (flags64 >> 48)) & 0xFF;
            if (flags == 0)
            {
                m_temporaryData.m_clipPlanes[planeCount++] = new Plane(m_temporaryData.m_vertices[2], m_temporaryData.m_vertices[0], m_temporaryData.m_vertices[6]);
            }
            else
            {
                cameraPlanes |= flags;
            }
            // +y
            flags = (uint)((flags64 >> 8) & (flags64 >> 24) & (flags64 >> 40) & (flags64 >> 56)) & 0xFF;
            if (flags == 0)
            {
                m_temporaryData.m_clipPlanes[planeCount++] = new Plane(m_temporaryData.m_vertices[1], m_temporaryData.m_vertices[3], m_temporaryData.m_vertices[5]);
            }
            else
            {
                cameraPlanes |= flags;
            }
            // near
            flags = (uint)((flags64 >> 0) & (flags64 >> 8) & (flags64 >> 16) & (flags64 >> 24)) & 0xFF;
            if (flags == 0)
            {
                m_temporaryData.m_clipPlanes[planeCount++] = new Plane(m_temporaryData.m_vertices[0], m_temporaryData.m_vertices[2], m_temporaryData.m_vertices[1]);
            }
            else
            {
                cameraPlanes |= flags;
            }
            // far
            flags = (uint)((flags64 >> 32) & (flags64 >> 40) & (flags64 >> 48) & (flags64 >> 56)) & 0xFF;
            if (flags == 0)
            {
                m_temporaryData.m_clipPlanes[planeCount++] = new Plane(m_temporaryData.m_vertices[4], m_temporaryData.m_vertices[5], m_temporaryData.m_vertices[6]);
            }
            else
            {
                cameraPlanes |= flags;
            }
            int maxPlaneCount = ScriptableCullingParameters.maximumCullingPlaneCount;

            Debug.Assert(cullingParameters.cullingPlaneCount == 6);
            const int farPlaneIndex     = 5;
            uint      addedCameraPlanes = 0;

            for (int i = 0; i < cullingParameters.cullingPlaneCount && planeCount < maxPlaneCount; ++i)
            {
                if ((cameraPlanes & (1U << i)) != 0)
                {
                    addedCameraPlanes |= 1U << i;
                    m_temporaryData.m_clipPlanes[planeCount++] = cullingParameters.GetCullingPlane(i);
                }
            }
            if (farPlaneIndex < planeCount)
            {
                // keep the camera far clip plane unchanged so that Layer Culling Distances can be handled correctly.
                if ((addedCameraPlanes & (1U << farPlaneIndex)) != 0)
                {
                    // already have the camera far clip plane in m_temporaryData.m_clipPlanes[planeCount - 1]
                    int currentFarPlaneIndex = planeCount - 1;
                    // we need the following lines between #else and #endif if farPlaneIndex != 5
#if true
                    Debug.Assert(farPlaneIndex == cullingParameters.cullingPlaneCount - 1);
#else
                    uint cameraPlaneFlags = addedCameraPlanes >> (farPlaneIndex + 1);
                    while (cameraPlaneFlags != 0)
                    {
                        if ((cameraPlaneFlags & 1U) == 1U)
                        {
                            --currentFarPlaneIndex;
                        }
                    }
#endif
                    if (currentFarPlaneIndex != farPlaneIndex)
                    {
                        Plane farPlane = m_temporaryData.m_clipPlanes[currentFarPlaneIndex];
                        m_temporaryData.m_clipPlanes[currentFarPlaneIndex] = m_temporaryData.m_clipPlanes[farPlaneIndex];
                        m_temporaryData.m_clipPlanes[farPlaneIndex]        = farPlane;
                    }
                }
                else
                {
                    // check if we really need to care abount Layer Culling Distances
                    bool    useLayerCullingDistances = false;
                    Vector3 cameraForward            = cam.transform.forward;
                    float   defaultCullingDistance   = cam.farClipPlane + Vector3.Dot(cameraForward, cam.transform.position);
                    defaultCullingDistance *= 0.9999f;
                    float maxCullingDistance = Vector3.Dot(m_temporaryData.m_vertices[0], cameraForward);
                    for (int i = 1; i < 8; ++i)
                    {
                        maxCullingDistance = Mathf.Max(maxCullingDistance, Vector3.Dot(m_temporaryData.m_vertices[i], cameraForward));
                    }
                    maxCullingDistance = Mathf.Min(maxCullingDistance, defaultCullingDistance);
                    int layerMask = cam.cullingMask & ~projector.ignoreLayers;
                    for (int i = 0, endi = ScriptableCullingParameters.layerCount; i < endi && layerMask != 0; ++i, layerMask >>= 1)
                    {
                        if ((layerMask & 1) != 0)
                        {
                            float layerCullingDistance = cullingParameters.GetLayerCullingDistance(i);
                            if (layerCullingDistance < maxCullingDistance)
                            {
                                useLayerCullingDistances = true;
                                break;
                            }
                        }
                    }
                    if (useLayerCullingDistances)
                    {
                        // we need to care about Layer Culling Distances. so keep far plane unchanged
                        // otherwise, projector might be drawn on invisible objects.
                        if (planeCount < ScriptableCullingParameters.maximumCullingPlaneCount)
                        {
                            m_temporaryData.m_clipPlanes[planeCount++] = m_temporaryData.m_clipPlanes[farPlaneIndex];
                        }
                        else
                        {
                            m_temporaryData.m_clipPlanes[planeCount - 1] = m_temporaryData.m_clipPlanes[farPlaneIndex];
                        }
                        m_temporaryData.m_clipPlanes[farPlaneIndex] = cullingParameters.GetCullingPlane(farPlaneIndex);
                    }
                    else
                    {
                        // we don't need to care abount Layer Culling Distances, but need to SetCullingDistance
                        // so that culling can work correctly.
                        Vector3 farPlaneNormal = m_temporaryData.m_clipPlanes[farPlaneIndex].normal;
                        float   maxDistance    = Vector3.Dot(farPlaneNormal, m_temporaryData.m_vertices[0]);
                        for (int i = 1; i < 8; ++i)
                        {
                            maxDistance = Mathf.Min(maxDistance, Vector3.Dot(m_temporaryData.m_vertices[i], farPlaneNormal));
                        }
                        maxDistance = -maxDistance;
                        for (int i = 0, endi = ScriptableCullingParameters.layerCount; i < endi; ++i)
                        {
                            cullingParameters.SetLayerCullingDistance(i, maxDistance);
                        }
                    }
                }
            }
#if DEBUG
            // make sure that farPlaneIndex is correct.
            Plane farClipPlane    = cullingParameters.GetCullingPlane(farPlaneIndex);
            float farClipDistance = farClipPlane.GetDistanceToPoint(cam.transform.position);
            float error           = Mathf.Abs(farClipDistance - cam.farClipPlane);
            float dirError        = Vector3.Dot(farClipPlane.normal, cam.transform.forward) + 1.0f;
            for (int i = 0; i < 6; ++i)
            {
                if (i != farPlaneIndex)
                {
                    Plane plane = cullingParameters.GetCullingPlane(i);
                    Debug.Assert(error < Mathf.Abs(cam.farClipPlane - plane.GetDistanceToPoint(cam.transform.position)));
                    Debug.Assert(dirError < Vector3.Dot(plane.normal, cam.transform.forward) + 1.0f);
                }
            }
            // To avoid the error: Assertion failed on expression: 'params.cullingPlaneCount == kPlaneFrustumNum'
            while (planeCount < 6)
            {
                m_temporaryData.m_clipPlanes[planeCount] = cullingParameters.GetCullingPlane(planeCount);
                ++planeCount;
            }
            planeCount = 6;
#endif
            cullingParameters.cullingPlaneCount = planeCount;
            for (int i = 0; i < planeCount; ++i)
            {
                cullingParameters.SetCullingPlane(i, m_temporaryData.m_clipPlanes[i]);
            }
            cullingParameters.cullingOptions &= ~(CullingOptions.NeedsReflectionProbes | CullingOptions.ShadowCasters);
            if (terrainsToBeFilteredWithRenderFlags != null && 0 < terrainsToBeFilteredWithRenderFlags.Length)
            {
                if (m_originalTerrainRenderFlags == null || m_originalTerrainRenderFlags.Length < terrainsToBeFilteredWithRenderFlags.Length)
                {
                    m_originalTerrainRenderFlags = new TerrainRenderFlags[terrainsToBeFilteredWithRenderFlags.Length];
                }
                for (int i = 0; i < terrainsToBeFilteredWithRenderFlags.Length; ++i)
                {
                    if (terrainsToBeFilteredWithRenderFlags[i] != null)
                    {
                        m_originalTerrainRenderFlags[i] = terrainsToBeFilteredWithRenderFlags[i].editorRenderFlags;
                        terrainsToBeFilteredWithRenderFlags[i].editorRenderFlags &= terrainRenderFlags;
                    }
                }
            }
            CullingResults cullingResults = context.Cull(ref cullingParameters);
            if (terrainsToBeFilteredWithRenderFlags != null && 0 < terrainsToBeFilteredWithRenderFlags.Length)
            {
                for (int i = 0; i < terrainsToBeFilteredWithRenderFlags.Length; ++i)
                {
                    if (terrainsToBeFilteredWithRenderFlags[i] != null)
                    {
                        terrainsToBeFilteredWithRenderFlags[i].editorRenderFlags = m_originalTerrainRenderFlags[i];
                    }
                }
            }
            m_cullingResults.Add(cam, cullingResults);
            return(true);
        }