Exemplo n.º 1
0
        bool Culling(ScriptableRenderContext context, Decal decal, ref RenderingData renderingData, out CullingResults cullingResults)
        {
            // Setup
            var camera     = renderingData.cameraData.camera;
            var localScale = decal.transform.lossyScale;

            cullingResults = new CullingResults();

            // Never draw in Preview
            if (camera.cameraType == CameraType.Preview)
            {
                return(false);
            }

            // Test for Decal behind Camera
            var maxRadius  = Mathf.Max(Mathf.Max(localScale.x * 0.5f, localScale.y * 0.5f), localScale.z) + kErrorMargin;
            var positionVS = camera.WorldToViewportPoint(decal.transform.position);

            if (positionVS.z < -maxRadius)
            {
                return(false);
            }

            // Get Decal bounds
            var boundsScale = new Vector3(maxRadius, maxRadius, maxRadius);
            var bounds      = new Bounds(decal.transform.position, boundsScale);

            // Test against frustum planes
            var planes = GeometryUtility.CalculateFrustumPlanes(camera);

            if (!GeometryUtility.TestPlanesAABB(planes, bounds))
            {
                return(false);
            }

            // Get CullingParameters
            var cullingParameters = new ScriptableCullingParameters();

            if (!camera.TryGetCullingParameters(out cullingParameters))
            {
                return(false);
            }

            // Set culling planes
            cullingParameters.cullingPlaneCount = 6;
            for (int i = 0; i < 6; ++i)
            {
                cullingParameters.SetCullingPlane(i, decal.clipPlanes[i]);
            }

            // Culling Results
            cullingResults = context.Cull(ref cullingParameters);
            return(true);
        }
Exemplo n.º 2
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);
        }
Exemplo n.º 3
0
    public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
    {
        var             camera = renderingData.cameraData.camera;
        SortingCriteria sortFlags;

        if (filterSettings.renderQueueRange == RenderQueueRange.opaque)
        {
            sortFlags = renderingData.cameraData.defaultOpaqueSortFlags;
        }
        else
        {
            sortFlags = SortingCriteria.CommonTransparent;
        }
        var drawSettings = CreateDrawingSettings(shaderTagIds, ref renderingData, sortFlags);

        CommandBuffer cmd = CommandBufferPool.Get("ClipSphere");

        cmd.EnableShaderKeyword("CLIP_SPHERE_ON");
        cmd.SetGlobalFloat("_ClipObjEdgeThickness", 0.01f);
        context.ExecuteCommandBuffer(cmd);
        cmd.Clear();

        var baseCameraMatrix = camera.worldToCameraMatrix;

        foreach (var proxy in ProxyNode.Instances)
        {
            if (!proxy.isActiveAndEnabled)
            {
                continue;
            }
            if (proxy.State == ProxyNode.ProxyState.Minimized)
            {
                continue;
            }

            foreach (var mark in proxy.Marks)
            {
                if (mark == null || !mark.isActiveAndEnabled)
                {
                    continue;
                }

                cmd.SetGlobalColor("_ClipObjEdgeColor", proxy.Color);
                cmd.SetGlobalVector("_ClipObjPosition", mark.transform.position);
                cmd.SetGlobalVector("_ClipObjScale", 0.5f * proxy.ProxyScaleFactor * mark.transform.localScale);
                var clipTransform = GetWarpTransform(proxy.transform, mark.transform);
                cmd.SetGlobalMatrix("_ClipTransform", clipTransform);
                cmd.SetGlobalMatrix("_ClipTransformInv", clipTransform.inverse);
                context.ExecuteCommandBuffer(cmd);

                OnProxyPass?.Invoke(this, GetProxyCameraPosition(proxy.transform, mark.transform));

                // Stupid hack, because the other versions crashed or didn't work
                var scp = new ScriptableCullingParameters();
                camera.TryGetCullingParameters(true, out scp);
                scp.cullingPlaneCount = 6;
                scp.SetCullingPlane(0, new Plane(new Vector3(1, 0, 0), mark.transform.position - new Vector3(1, 0, 0) * mark.transform.localScale.x));
                scp.SetCullingPlane(1, new Plane(new Vector3(-1, 0, 0), mark.transform.position + new Vector3(1, 0, 0) * mark.transform.localScale.x));
                scp.SetCullingPlane(2, new Plane(new Vector3(0, 1, 0), mark.transform.position - new Vector3(0, 1, 0) * mark.transform.localScale.y));
                scp.SetCullingPlane(3, new Plane(new Vector3(0, -1, 0), mark.transform.position + new Vector3(0, 1, 0) * mark.transform.localScale.y));
                scp.SetCullingPlane(4, new Plane(new Vector3(0, 0, 1), mark.transform.position - new Vector3(0, 0, 1) * mark.transform.localScale.z));
                scp.SetCullingPlane(5, new Plane(new Vector3(0, 0, -1), mark.transform.position + new Vector3(0, 0, 1) * mark.transform.localScale.z));
                var cullResults = context.Cull(ref scp);

                context.DrawRenderers(cullResults, ref drawSettings, ref filterSettings, ref renderStateBlock);
            }
        }

        cmd.SetGlobalMatrix("_ClipTransform", Matrix4x4.identity);
        cmd.DisableShaderKeyword("CLIP_SPHERE_ON");
        context.ExecuteCommandBuffer(cmd);
        CommandBufferPool.Release(cmd);
    }
Exemplo n.º 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;

            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);
        }