Exemplo n.º 1
0
        /// <summary>
        /// Computes the rule used for toggling renderer shadow casting.
        /// </summary>
        /// <param name="profile">Profile used for size and distance thresholds needed for the rule.</param>
        /// <param name="viewportSize">Diagonal viewport size of the renderer.</param>
        /// <param name="distanceToCamera">Distance from renderer to camera.</param>
        /// <param name="shadowMapTexelSize">Shadow map bounding box size in texels.</param>
        /// <returns>True if renderer should have shadow, false otherwise.</returns>
        internal static bool TestRendererShadowRule(CullingControllerProfile profile, float viewportSize, float distanceToCamera, float shadowMapTexelSize)
        {
            bool shouldHaveShadow = distanceToCamera < profile.shadowDistanceThreshold;

            shouldHaveShadow |= viewportSize > profile.shadowRendererSizeThreshold;
            shouldHaveShadow &= shadowMapTexelSize > profile.shadowMapProjectionSizeThreshold;
            return(shouldHaveShadow);
        }
        public float shadowMapProjectionSizeThreshold; //

        /// <summary>
        /// Performs a linear interpolation between the values of two CullingControllerProfiles.
        /// Used for controlling the settings panel slider.
        /// </summary>
        /// <param name="p1">Starting profile</param>
        /// <param name="p2">Ending profile</param>
        /// <param name="t">Time value for the linear interpolation.</param>
        /// <returns>A new CullingControllerProfile with the interpolated values.</returns>
        public static CullingControllerProfile Lerp(CullingControllerProfile p1, CullingControllerProfile p2, float t)
        {
            return(new CullingControllerProfile
            {
                visibleDistanceThreshold = Mathf.Lerp(p1.visibleDistanceThreshold, p2.visibleDistanceThreshold, t),
                shadowDistanceThreshold = Mathf.Lerp(p1.shadowDistanceThreshold, p2.shadowDistanceThreshold, t),
                emissiveSizeThreshold = Mathf.Lerp(p1.emissiveSizeThreshold, p2.emissiveSizeThreshold, t),
                opaqueSizeThreshold = Mathf.Lerp(p1.opaqueSizeThreshold, p2.opaqueSizeThreshold, t),
                shadowRendererSizeThreshold = Mathf.Lerp(p1.shadowRendererSizeThreshold, p2.shadowRendererSizeThreshold, t),
                shadowMapProjectionSizeThreshold = Mathf.Lerp(p1.shadowMapProjectionSizeThreshold, p2.shadowMapProjectionSizeThreshold, t)
            });
        }
Exemplo n.º 3
0
        /// <summary>
        /// Computes the rule used for toggling renderers visibility.
        /// </summary>
        /// <param name="profile">Profile used for size and distance thresholds needed for the rule.</param>
        /// <param name="viewportSize">Diagonal viewport size of the renderer.</param>
        /// <param name="distanceToCamera">Distance to camera of the renderer.</param>
        /// <param name="boundsContainsCamera">Renderer bounds contains camera?</param>
        /// <param name="isOpaque">Renderer is opaque?</param>
        /// <param name="isEmissive">Renderer is emissive?</param>
        /// <returns>True if renderer should be visible, false if otherwise.</returns>
        internal static bool TestRendererVisibleRule(CullingControllerProfile profile, float viewportSize, float distanceToCamera, bool boundsContainsCamera, bool isOpaque, bool isEmissive)
        {
            bool shouldBeVisible = distanceToCamera < profile.visibleDistanceThreshold || boundsContainsCamera;

            if (isEmissive)
            {
                shouldBeVisible |= viewportSize > profile.emissiveSizeThreshold;
            }

            if (isOpaque)
            {
                shouldBeVisible |= viewportSize > profile.opaqueSizeThreshold;
            }

            return(shouldBeVisible);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Process all sceneObject renderers with the parameters set by the given profile.
        /// </summary>
        /// <param name="profile">any CullingControllerProfile</param>
        /// <returns>IEnumerator to be yielded.</returns>
        internal IEnumerator ProcessProfile(CullingControllerProfile profile)
        {
            Renderer[] renderers;

            // If profile matches the skinned renderer profile in settings,
            // the skinned renderers are going to be used.
            if (profile == settings.rendererProfile)
            {
                renderers = objectsTracker.GetRenderers();
            }
            else
            {
                renderers = objectsTracker.GetSkinnedRenderers();
            }


            for (var i = 0; i < renderers.Length; i++)
            {
                if (timeBudgetCount > settings.maxTimeBudget)
                {
                    timeBudgetCount = 0;
                    yield return(null);
                }

                Renderer r = renderers[i];

                if (r == null)
                {
                    continue;
                }

                bool rendererIsInIgnoreLayer = ((1 << r.gameObject.layer) & settings.ignoredLayersMask) != 0;

                if (rendererIsInIgnoreLayer)
                {
                    SetCullingForRenderer(r, true, true);
                    continue;
                }


                float startTime = Time.realtimeSinceStartup;

                //NOTE(Brian): Need to retrieve positions every frame to take into account
                //             world repositioning.
                Vector3 playerPosition = CommonScriptableObjects.playerUnityPosition;

                Bounds bounds = r.GetSafeBounds();

                Vector3 boundingPoint        = bounds.ClosestPoint(playerPosition);
                float   distance             = Vector3.Distance(playerPosition, boundingPoint);
                bool    boundsContainsPlayer = bounds.Contains(playerPosition);
                float   boundsSize           = bounds.size.magnitude;
                float   viewportSize         = (boundsSize / distance) * Mathf.Rad2Deg;

                bool isEmissive = IsEmissive(r);
                bool isOpaque   = IsOpaque(r);

                float shadowTexelSize = ComputeShadowMapTexelSize(boundsSize, urpAsset.shadowDistance, urpAsset.mainLightShadowmapResolution);

                bool shouldBeVisible  = TestRendererVisibleRule(profile, viewportSize, distance, boundsContainsPlayer, isOpaque, isEmissive);
                bool shouldHaveShadow = TestRendererShadowRule(profile, viewportSize, distance, shadowTexelSize);

                if (r is SkinnedMeshRenderer skr)
                {
                    Material mat = skr.sharedMaterial;
                    bool     isAvatarRenderer = false;

                    if (mat != null && mat.shader != null)
                    {
                        isAvatarRenderer = mat.shader.name == "DCL/Toon Shader";
                    }

                    if (isAvatarRenderer)
                    {
                        shouldHaveShadow &= TestAvatarShadowRule(profile, distance);
                    }

                    skr.updateWhenOffscreen = TestSkinnedRendererOffscreenRule(settings, distance);
                }

                if (OnDataReport != null)
                {
                    if (!shouldBeVisible && !hiddenRenderers.Contains(r))
                    {
                        hiddenRenderers.Add(r);
                    }

                    if (shouldBeVisible && !shouldHaveShadow && !shadowlessRenderers.Contains(r))
                    {
                        shadowlessRenderers.Add(r);
                    }
                }

                SetCullingForRenderer(r, shouldBeVisible, shouldHaveShadow);
#if UNITY_EDITOR
                DrawDebugGizmos(shouldBeVisible, bounds, boundingPoint);
#endif
                timeBudgetCount += Time.realtimeSinceStartup - startTime;
            }
        }
Exemplo n.º 5
0
 internal static bool TestAvatarShadowRule(CullingControllerProfile profile, float avatarDistance)
 {
     return(avatarDistance < profile.maxShadowDistanceForAvatars);
 }