void RenderDirectionalCascadeShadowmap(ref ScriptableRenderContext context, ref CullResults cullResults, ref LightData lightData, ref ShadowData shadowData)
        {
            int shadowLightIndex = lightData.mainLightIndex;

            if (shadowLightIndex == -1)
            {
                return;
            }

            VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex];
            Light        light       = shadowLight.light;

            Debug.Assert(shadowLight.lightType == LightType.Directional);

            if (light.shadows == LightShadows.None)
            {
                return;
            }

            Bounds bounds;

            if (!cullResults.GetShadowCasterBounds(shadowLightIndex, out bounds))
            {
                return;
            }

            CommandBuffer cmd = CommandBufferPool.Get(k_RenderDirectionalShadowmapTag);

            using (new ProfilingSample(cmd, k_RenderDirectionalShadowmapTag))
            {
                m_ShadowCasterCascadesCount = shadowData.directionalLightCascadeCount;

                int   shadowResolution = LightweightShadowUtils.GetMaxTileResolutionInAtlas(shadowData.directionalShadowAtlasWidth, shadowData.directionalShadowAtlasHeight, m_ShadowCasterCascadesCount);
                float shadowNearPlane  = light.shadowNearPlane;

                Matrix4x4 view, proj;
                var       settings = new DrawShadowsSettings(cullResults, shadowLightIndex);

                m_DirectionalShadowmapTexture = RenderTexture.GetTemporary(shadowData.directionalShadowAtlasWidth,
                                                                           shadowData.directionalShadowAtlasHeight, k_ShadowmapBufferBits, m_ShadowmapFormat);
                m_DirectionalShadowmapTexture.filterMode = FilterMode.Bilinear;
                m_DirectionalShadowmapTexture.wrapMode   = TextureWrapMode.Clamp;
                SetRenderTarget(cmd, m_DirectionalShadowmapTexture, RenderBufferLoadAction.DontCare,
                                RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black, TextureDimension.Tex2D);

                bool success = false;
                for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex)
                {
                    success = LightweightShadowUtils.ExtractDirectionalLightMatrix(ref cullResults, ref shadowData, shadowLightIndex, cascadeIndex, shadowResolution, shadowNearPlane, out m_CascadeSplitDistances[cascadeIndex], out m_CascadeSlices[cascadeIndex], out view, out proj);
                    if (success)
                    {
                        settings.splitData.cullingSphere = m_CascadeSplitDistances[cascadeIndex];
                        LightweightShadowUtils.SetupShadowCasterConstants(cmd, ref shadowLight, proj, shadowResolution);
                        LightweightShadowUtils.RenderShadowSlice(cmd, ref context, ref m_CascadeSlices[cascadeIndex], ref settings, proj, view);
                    }
                }

                if (success)
                {
                    SetupDirectionalShadowReceiverConstants(cmd, ref shadowData, shadowLight);
                }
            }
            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);
        }
        void RenderLocalShadowmapAtlas(ref ScriptableRenderContext context, ref CullResults cullResults, ref LightData lightData, ref ShadowData shadowData)
        {
            List <int>          localLightIndices = lightData.visibleLocalLightIndices;
            List <VisibleLight> visibleLights     = lightData.visibleLights;

            int shadowCastingLightsCount = 0;
            int localLightsCount         = localLightIndices.Count;

            for (int i = 0; i < localLightsCount; ++i)
            {
                VisibleLight shadowLight = visibleLights[localLightIndices[i]];

                if (shadowLight.lightType == LightType.Spot && shadowLight.light.shadows != LightShadows.None)
                {
                    shadowCastingLightsCount++;
                }
            }

            if (shadowCastingLightsCount == 0)
            {
                return;
            }

            Matrix4x4 view, proj;
            Bounds    bounds;

            CommandBuffer cmd = CommandBufferPool.Get(k_RenderLocalShadows);

            using (new ProfilingSample(cmd, k_RenderLocalShadows))
            {
                // TODO: Add support to point light shadows. We make a simplification here that only works
                // for spot lights and with max spot shadows per pass.
                int atlasWidth      = shadowData.localShadowAtlasWidth;
                int atlasHeight     = shadowData.localShadowAtlasHeight;
                int sliceResolution = LightweightShadowUtils.GetMaxTileResolutionInAtlas(atlasWidth, atlasHeight, shadowCastingLightsCount);

                m_LocalShadowmapTexture = RenderTexture.GetTemporary(shadowData.localShadowAtlasWidth,
                                                                     shadowData.localShadowAtlasHeight, k_ShadowmapBufferBits, m_LocalShadowmapFormat);
                m_LocalShadowmapTexture.filterMode = FilterMode.Bilinear;
                m_LocalShadowmapTexture.wrapMode   = TextureWrapMode.Clamp;

                SetRenderTarget(cmd, m_LocalShadowmapTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store,
                                ClearFlag.Depth, Color.black, TextureDimension.Tex2D);

                for (int i = 0; i < localLightsCount; ++i)
                {
                    int          shadowLightIndex = localLightIndices[i];
                    VisibleLight shadowLight      = visibleLights[shadowLightIndex];
                    Light        light            = shadowLight.light;

                    // TODO: Add support to point light shadows
                    if (shadowLight.lightType != LightType.Spot || shadowLight.light.shadows == LightShadows.None)
                    {
                        continue;
                    }

                    if (!cullResults.GetShadowCasterBounds(shadowLightIndex, out bounds))
                    {
                        continue;
                    }

                    Matrix4x4 shadowTransform;
                    bool      success = LightweightShadowUtils.ExtractSpotLightMatrix(ref cullResults, ref shadowData,
                                                                                      shadowLightIndex, out shadowTransform, out view, out proj);

                    if (success)
                    {
                        // This way of computing the shadow slice only work for spots and with most 4 shadow casting lights per pass
                        // Change this when point lights are supported.
                        Debug.Assert(shadowCastingLightsCount <= 4 && shadowLight.lightType == LightType.Spot);

                        // TODO: We need to pass bias and scale list to shader to be able to support multiple
                        // shadow casting local lights.
                        m_LocalLightSlices[i].offsetX         = (i % 2) * sliceResolution;
                        m_LocalLightSlices[i].offsetY         = (i / 2) * sliceResolution;
                        m_LocalLightSlices[i].resolution      = sliceResolution;
                        m_LocalLightSlices[i].shadowTransform = shadowTransform;

                        m_LocalShadowStrength[i] = light.shadowStrength;

                        if (shadowCastingLightsCount > 1)
                        {
                            LightweightShadowUtils.ApplySliceTransform(ref m_LocalLightSlices[i], atlasWidth, atlasHeight);
                        }

                        var settings = new DrawShadowsSettings(cullResults, shadowLightIndex);
                        LightweightShadowUtils.SetupShadowCasterConstants(cmd, ref shadowLight, proj, sliceResolution);
                        LightweightShadowUtils.RenderShadowSlice(cmd, ref context, ref m_LocalLightSlices[i], ref settings, proj, view);
                    }
                }

                SetupLocalLightsShadowReceiverConstants(cmd, ref shadowData);
            }
            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);
        }
Beispiel #3
0
        void RenderDirectionalCascadeShadowmap(ref ScriptableRenderContext context, ref CullResults cullResults, ref LightData lightData, ref ShadowData shadowData)
        {
            LightShadows shadowQuality    = LightShadows.None;
            int          shadowLightIndex = lightData.mainLightIndex;

            if (shadowLightIndex == -1)
            {
                return;
            }

            VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex];
            Light        light       = shadowLight.light;

            Debug.Assert(shadowLight.lightType == LightType.Directional);

            if (light.shadows == LightShadows.None)
            {
                return;
            }

            Bounds bounds;

            if (!cullResults.GetShadowCasterBounds(shadowLightIndex, out bounds))
            {
                return;
            }

            CommandBuffer cmd = CommandBufferPool.Get(k_RenderDirectionalShadowmapTag);

            using (new ProfilingSample(cmd, k_SetupRenderTargetTag))
            {
                m_ShadowCasterCascadesCount = shadowData.directionalLightCascadeCount;

                int   shadowResolution = LightweightShadowUtils.GetMaxTileResolutionInAtlas(shadowData.directionalShadowAtlasWidth, shadowData.directionalShadowAtlasHeight, m_ShadowCasterCascadesCount);
                float shadowNearPlane  = light.shadowNearPlane;

                Matrix4x4 view, proj;
                var       settings = new DrawShadowsSettings(cullResults, shadowLightIndex);

                m_DirectionalShadowmapTexture = RenderTexture.GetTemporary(shadowData.directionalShadowAtlasWidth,
                                                                           shadowData.directionalShadowAtlasHeight, k_ShadowmapBufferBits, m_ShadowmapFormat);
                m_DirectionalShadowmapTexture.filterMode = FilterMode.Bilinear;
                m_DirectionalShadowmapTexture.wrapMode   = TextureWrapMode.Clamp;
                SetRenderTarget(cmd, m_DirectionalShadowmapTexture, RenderBufferLoadAction.DontCare,
                                RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black);

                bool success = false;
                for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex)
                {
                    success = LightweightShadowUtils.ExtractDirectionalLightMatrix(ref cullResults, ref shadowData, shadowLightIndex, cascadeIndex, shadowResolution, shadowNearPlane, out m_CascadeSplitDistances[cascadeIndex], out m_CascadeSlices[cascadeIndex], out view, out proj);
                    if (success)
                    {
                        LightweightShadowUtils.SetupShadowCasterConstants(cmd, ref shadowLight, proj, shadowResolution);
                        LightweightShadowUtils.RenderShadowSlice(cmd, ref context, ref m_CascadeSlices[cascadeIndex], proj,
                                                                 view, settings);
                    }
                }

                if (success)
                {
                    shadowQuality = (shadowData.supportsSoftShadows) ? light.shadows : LightShadows.Hard;

                    // In order to avoid shader variants explosion we only do hard shadows when sampling shadowmap in the lit pass.
                    // GLES2 platform is forced to hard single cascade shadows.
                    if (!shadowData.requiresScreenSpaceShadowResolve)
                    {
                        shadowQuality = LightShadows.Hard;
                    }

                    SetupDirectionalShadowReceiverConstants(ref context, cmd, ref shadowData, shadowLight);
                }
            }
            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);

            // TODO: We should have RenderingData as a readonly but currently we need this to pass shadow rendering to litpass
            shadowData.renderedDirectionalShadowQuality = shadowQuality;
        }