private void RenderCascadedShadows(ScriptableRenderContext context)
    {
        float tileSize = shadowMapSize / 2;

        cascadedShadowMap = SetShadowRenderTarget();
        shadowBuffer.BeginSample("Render Main Shadows");

        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();
        Light shadowLight = cull.visibleLights[0].light;

        shadowBuffer.SetGlobalFloat(
            shadowBiasID, shadowLight.shadowBias);
        var shadowSettings = new DrawShadowsSettings(cull, 0);
        var tileMatrix     = Matrix4x4.identity;

        tileMatrix.m00 = tileMatrix.m11 = 0.5f;

        for (int i = 0; i < shadowCascades; i++)
        {
            Matrix4x4       viewMatrix, projectionMatrix;
            ShadowSplitData splitData;
            cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(
                0, i, shadowCascades, shadowCascadeSplit, (int)tileSize
                , shadowLight.shadowNearPlane,
                out viewMatrix, out projectionMatrix, out splitData);

            Vector2 tileOffset = ConfigureShadowTile(i, 2, tileSize);
            shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
            context.ExecuteCommandBuffer(shadowBuffer);
            shadowBuffer.Clear();

            cascadeCullingSpheres[i] = shadowSettings.splitData.cullingSphere = splitData.cullingSphere;
            //储存半径平方 用于比较
            cascadeCullingSpheres[i].w *= splitData.cullingSphere.w;
            context.DrawShadows(ref shadowSettings);
            CalculateWorldToShadowMatrix(ref viewMatrix, ref projectionMatrix
                                         , out worldToShadowCascadeMatrices[i]);
            tileMatrix.m03 = tileOffset.x * 0.5f;
            tileMatrix.m13 = tileOffset.y * 0.5f;
            worldToShadowCascadeMatrices[i] = tileMatrix * worldToShadowCascadeMatrices[i];
        }

        shadowBuffer.DisableScissorRect();
        shadowBuffer.SetGlobalTexture(cascadedShadowMapID, cascadedShadowMap);
        shadowBuffer.SetGlobalVectorArray(cascadeCullingSpheresID, cascadeCullingSpheres);
        shadowBuffer.SetGlobalMatrixArray(worldToShadowCascadeMatricesID, worldToShadowCascadeMatrices);
        float invShadowMapSize = 1f / shadowMapSize;

        shadowBuffer.SetGlobalVector(cascadedShadowMapSizedID
                                     , new Vector4(invShadowMapSize, invShadowMapSize, shadowMapSize, shadowMapSize));
        shadowBuffer.SetGlobalFloat(cascadedShadowStrengthID, shadowLight.shadowStrength);
        bool hard = shadowLight.shadows == LightShadows.Hard;

        CoreUtils.SetKeyword(shadowBuffer, cascadedShadowsHardKeyword, hard);
        CoreUtils.SetKeyword(shadowBuffer, cascadedShadowsSoftKeyword, !hard);
        shadowBuffer.EndSample("Render Main Shadows");
        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();
    }
        public static bool ExtractDirectionalLightMatrix(ref CullResults cullResults, ref ShadowData shadowData, int shadowLightIndex, int cascadeIndex, int shadowResolution, float shadowNearPlane, out Vector4 cascadeSplitDistance, out ShadowSliceData shadowSliceData, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix)
        {
            ShadowSplitData splitData;
            bool            success = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex,
                                                                                                       cascadeIndex, shadowData.directionalLightCascadeCount, shadowData.directionalLightCascades, shadowResolution, shadowNearPlane, out viewMatrix, out projMatrix,
                                                                                                       out splitData);

            float cullingSphereRadius = splitData.cullingSphere.w;

            cascadeSplitDistance   = splitData.cullingSphere;
            cascadeSplitDistance.w = cullingSphereRadius * cullingSphereRadius;

            shadowSliceData.offsetX         = (cascadeIndex % 2) * shadowResolution;
            shadowSliceData.offsetY         = (cascadeIndex / 2) * shadowResolution;
            shadowSliceData.resolution      = shadowResolution;
            shadowSliceData.shadowTransform = GetShadowTransform(projMatrix, viewMatrix);

            // If we have shadow cascades baked into the atlas we bake cascade transform
            // in each shadow matrix to save shader ALU and L/S
            if (shadowData.directionalLightCascadeCount > 1)
            {
                ApplySliceTransform(ref shadowSliceData, shadowData.directionalShadowAtlasWidth, shadowData.directionalShadowAtlasHeight);
            }

            return(success);
        }
    private void shadow_pass(ref CullResults cull, ref ScriptableRenderContext context)
    {
        int     shadowLightIndex            = 0;
        int     cascadeIdx                  = 0;
        int     m_ShadowCasterCascadesCount = 1;
        Vector3 directionalLightCascades    = new Vector3(1.0f, 0.0f, 0.0f);
        int     shadowNearPlaneOffset       = 0;

        Matrix4x4 view;
        Matrix4x4 proj;

        foreach (var light in cull.visibleLights)
        {
            if (light.lightType == LightType.Directional)
            {
                DrawShadowsSettings sss = new DrawShadowsSettings(cull, shadowLightIndex);

                var success = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex,
                                                                                        cascadeIdx, m_ShadowCasterCascadesCount, directionalLightCascades,
                                                                                        shadowResolution, shadowNearPlaneOffset, out view, out proj,
                                                                                        out sss.splitData);

                //view 光源的视空间
                //proj 光源的裁剪空间
                if (success)
                {
                    cmd.Clear();
                    cmd.name = "clear shadow map";
                    cmd.SetRenderTarget(_ScreenSpaceShadowMapId);
                    cmd.ClearRenderTarget(true, true, Color.black);
                    context.ExecuteCommandBuffer(cmd);


                    cmd.Clear();
                    cmd.name = "create shadow map";
                    cmd.SetViewport(new Rect(0, 0, shadowResolution, shadowResolution));
                    cmd.SetViewProjectionMatrices(view, proj);
                    context.ExecuteCommandBuffer(cmd);

                    context.DrawShadows(ref sss);
                    context.ExecuteCommandBuffer(cmd);
                }

                cmd.Clear();
                if (SystemInfo.usesReversedZBuffer)
                {
                    //Debug.Log("usesReversedZBuffer ");
                }
                cmd.SetGlobalMatrix(_mId, proj * view);
                context.ExecuteCommandBuffer(cmd);
            }

            shadowLightIndex++;
        }
    }
 public static Matrix4x4 ExtractDirectionalLightMatrix(VisibleLight vl, uint cascadeIdx, int cascadeCount, Vector3 splitRatio, float nearPlaneOffset, uint width, uint height, out Matrix4x4 view, out Matrix4x4 proj, out Vector4 lightDir, out ShadowSplitData splitData, CullResults cullResults, int lightIndex)
 {
     Debug.Assert(width == height, "Currently the cascaded shadow mapping code requires square cascades.");
     splitData = new ShadowSplitData();
     splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity);
     splitData.cullingPlaneCount = 0;
     // get lightDir
     lightDir = vl.light.transform.forward;
     // TODO: At some point this logic should be moved to C#, then the parameters cullResults and lightIndex can be removed as well
     //       For directional lights shadow data is extracted from the cullResults, so that needs to be somehow provided here.
     //       Check ScriptableShadowsUtility.cpp ComputeDirectionalShadowMatricesAndCullingPrimitives(...) for details.
     cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, (int)cascadeIdx, cascadeCount, splitRatio, (int)width, nearPlaneOffset, out view, out proj, out splitData);
     // and the compound
     return(proj * view);
 }
Example #5
0
        public static bool ExtractDirectionalLightMatrix(ref CullResults cullResults, ref ShadowData shadowData,
                                                         int shadowLightIndex, int cascadeIndex, int shadowResolution, float shadowNearPlane, float shadowFarPlane,
                                                         out Vector4 cascadeSplitDistance, out ShadowSliceData shadowSliceData, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix)
        {
            ShadowSplitData splitData;
            Vector3         splitRotio = Vector3.one;

            if (shadowNearPlane > 1f)
            {
                float r = Mathf.Pow(shadowFarPlane / shadowNearPlane, 1f / shadowData.directionalLightCascadeCount);
                splitRotio = new Vector3(shadowNearPlane * r, shadowNearPlane * r * r, shadowNearPlane * r * r * r) / shadowFarPlane;
            }
            else
            {
                if (shadowData.directionalLightCascadeCount == 1)
                {
                    splitRotio = new Vector3(1f, 0f, 0f);
                }
                else if (shadowData.directionalLightCascadeCount == 2)
                {
                    splitRotio = new Vector3(0.25f, 1f, 0f);
                }
                else
                {
                    splitRotio = new Vector3(0.067f, 0.2f, 0.467f);
                }
            }
            bool success = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex, cascadeIndex,
                                                                                            shadowData.directionalLightCascadeCount, splitRotio, shadowResolution, shadowNearPlane, out viewMatrix, out projMatrix, out splitData);

            cascadeSplitDistance            = splitData.cullingSphere;
            shadowSliceData.offsetX         = (cascadeIndex % 2) * shadowResolution;
            shadowSliceData.offsetY         = (cascadeIndex / 2) * shadowResolution;
            shadowSliceData.resolution      = shadowResolution;
            shadowSliceData.shadowTransform = GetShadowTransform(projMatrix, viewMatrix);

            if (shadowData.directionalLightCascadeCount > 1)
            {
                ApplySliceTransform(ref shadowSliceData, shadowData.directionalShadowAltasRes, shadowData.directionalShadowAltasRes);
            }

            return(success);
        }
        public static Matrix4x4 ExtractDirectionalLightMatrix(VisibleLight vl, uint cascadeIdx, int cascadeCount, float[] splitRatio, float nearPlaneOffset, uint width, uint height, out Matrix4x4 view, out Matrix4x4 proj, out Matrix4x4 deviceProj, out Matrix4x4 vpinverse, out Vector4 lightDir, out ShadowSplitData splitData, CullResults cullResults, int lightIndex)
        {
            Debug.Assert(width == height, "Currently the cascaded shadow mapping code requires square cascades.");
            splitData = new ShadowSplitData();
            splitData.cullingSphere.Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity);
            splitData.cullingPlaneCount = 0;
            // get lightDir
            lightDir = vl.light.transform.forward;
            // TODO: At some point this logic should be moved to C#, then the parameters cullResults and lightIndex can be removed as well
            //       For directional lights shadow data is extracted from the cullResults, so that needs to be somehow provided here.
            //       Check ScriptableShadowsUtility.cpp ComputeDirectionalShadowMatricesAndCullingPrimitives(...) for details.
            Vector3 ratios = new Vector3();

            for (int i = 0, cnt = splitRatio.Length < 3 ? splitRatio.Length : 3; i < cnt; i++)
            {
                ratios[i] = splitRatio[i];
            }
            cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, (int)cascadeIdx, cascadeCount, ratios, (int)width, nearPlaneOffset, out view, out proj, out splitData);
            // and the compound (deviceProj will potentially inverse-Z)
            deviceProj = GL.GetGPUProjectionMatrix(proj, false);
            InvertOrthographic(ref deviceProj, ref view, out vpinverse);
            return(deviceProj * view);
        }
Example #7
0
    void RenderShadows(ScriptableRenderContext context)
    {
        int split;   //split to N*N tiles

        if (shadowTileCount <= 1)
        {
            split = 1;
        }
        else if (shadowTileCount <= 4)
        {
            split = 2;
        }
        else if (shadowTileCount <= 9)
        {
            split = 3;
        }
        else
        {
            split = 4;
        }

        float tileSize  = shadowMapSize / split;  //maximum light = 16
        float tileScale = 1f / split;

        globalShadowData.x = tileScale;

        shadowMap = SetShadowRenderTarget();

        shadowBuffer.BeginSample("Render Shadows");

        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();

        int  tileIndex   = 0;
        bool hardShadows = false;
        bool softShadows = false;

        for (int i = mainLightExists ? 1 : 0; i < cull.visibleLights.Count; i++)
        {
            if (i == maxVisibleLights)
            {
                break;
            }
            //shadowStrength <=0 indicates the light needs no shadowmap
            if (shadowData[i].x <= 0f)
            {
                continue;
            }

            //render shadowMap for light i
            Matrix4x4       viewMatrix, projectionMatrix;
            ShadowSplitData splitData;

            bool validShadows;
            if (shadowData[i].z > 0f)
            {
                validShadows =
                    cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(
                        i, 0, 1, Vector3.right, (int)tileSize,
                        cull.visibleLights[i].light.shadowNearPlane,
                        out viewMatrix, out projectionMatrix, out splitData);
            }
            else
            {
                validShadows = cull.ComputeSpotShadowMatricesAndCullingPrimitives(
                    i, out viewMatrix, out projectionMatrix, out splitData);
            }

            if (!validShadows)
            {
                shadowData[i].x = 0f;
                continue;
            }


            Vector2 tileOffset = ConfigureShadowTile(tileIndex, split, tileSize);
            shadowData[i].z = tileOffset.x * tileScale;
            shadowData[i].w = tileOffset.y * tileScale;

            shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);

            shadowBuffer.SetGlobalFloat(
                shadowBiasId, cull.visibleLights[i].light.shadowBias
                ); // shadow bias

            context.ExecuteCommandBuffer(shadowBuffer);
            shadowBuffer.Clear();

            var shadowSettings = new DrawShadowsSettings(cull, i);
            shadowSettings.splitData.cullingSphere = splitData.cullingSphere;
            context.DrawShadows(ref shadowSettings);

            CalculateWorldToShadowMatrix(ref viewMatrix, ref projectionMatrix,
                                         out worldToShadowMatrices[i]);

            tileIndex += 1;

            //for generate shader keyword of all soft/all hard shadows
            if (shadowData[i].y <= 0f)
            {
                hardShadows = true;
            }
            else
            {
                softShadows = true;
            }
        }

        shadowBuffer.DisableScissorRect();

        //sample shadowMap
        shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap);

        shadowBuffer.SetGlobalMatrixArray(worldToShadowMatricesId, worldToShadowMatrices);
        //_ShadowData , including shadow strength
        shadowBuffer.SetGlobalVectorArray(shadowDataId, shadowData);


        //soft shadows, tent filter inputs
        float invShadowMapSize = 1f / shadowMapSize;

        shadowBuffer.SetGlobalVector(
            shadowMapSizeId, new Vector4(
                invShadowMapSize, invShadowMapSize, shadowMapSize, shadowMapSize
                )
            );

        CoreUtils.SetKeyword(shadowBuffer, shadowsHardKeyword, hardShadows);
        CoreUtils.SetKeyword(shadowBuffer, shadowsSoftKeyword, softShadows);

        shadowBuffer.EndSample("Render Shadows");
        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();
    }
Example #8
0
    void RenderShadows(ScriptableRenderContext context)
    {
        int split;

        if (shadowTileCount <= 1)
        {
            split = 1;
        }
        else if (shadowTileCount <= 4)
        {
            split = 2;
        }
        else if (shadowTileCount <= 9)
        {
            split = 3;
        }
        else
        {
            split = 4;
        }

        float tileSize  = shadowMapSize / split;
        float tileScale = 1f / split;

        Rect tileViewport = new Rect(0f, 0f, tileSize, tileSize);

        shadowMap = RenderTexture.GetTemporary(shadowMapSize, shadowMapSize, 16, RenderTextureFormat.Shadowmap);

        shadowMap.filterMode = FilterMode.Bilinear;
        shadowMap.wrapMode   = TextureWrapMode.Clamp;

        CoreUtils.SetRenderTarget(shadowBuffer, shadowMap, RenderBufferLoadAction.DontCare,
                                  RenderBufferStoreAction.Store,
                                  ClearFlag.Depth);

        shadowBuffer.BeginSample("Render Shadows");
        shadowBuffer.SetGlobalVector(globalShadowDataId, new Vector4(tileScale, shadowDistance * shadowDistance));
        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();

        int  tileIndex   = 0;
        bool hardShadows = false;
        bool softShadows = false;

        for (int i = 0; i < cull.visibleLights.Count; ++i)
        {
            if (i == maxVisibleLights)
            {
                break;
            }

            if (shadowData[i].x <= 0f)
            {
                continue;
            }

            Matrix4x4       viewMatrix, projectionMatrix;
            ShadowSplitData splitData;
            bool            validShadow;
            if (shadowData[i].z > 0f)
            {
                validShadow = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(
                    i, 0, 1, Vector3.right, (int)tileSize,
                    cull.visibleLights[i].light.shadowNearPlane,
                    out viewMatrix, out projectionMatrix, out splitData);
            }
            else
            {
                validShadow = cull.ComputeSpotShadowMatricesAndCullingPrimitives(i, out viewMatrix, out projectionMatrix, out splitData);
            }
            if (!validShadow)
            {
                shadowData[i].x = 0f;
                continue;
            }
            float tileOffsetX = i % split;
            float tileOffsetY = i / split;
            tileViewport.x  = tileOffsetX * tileSize;
            tileViewport.y  = tileOffsetY * tileSize;
            shadowData[i].z = tileOffsetX * tileScale;
            shadowData[i].w = tileOffsetY * tileScale;

            shadowBuffer.SetViewport(tileViewport);
            shadowBuffer.EnableScissorRect(new Rect(
                                               tileViewport.x + 4f, tileViewport.y + 4f,
                                               tileSize - 8f, tileSize - 8f
                                               ));

            shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
            shadowBuffer.SetGlobalFloat(
                shadowBiasId, cull.visibleLights[i].light.shadowBias
                );
            shadowBuffer.SetGlobalVectorArray(shadowDataId, shadowData);
            context.ExecuteCommandBuffer(shadowBuffer);
            shadowBuffer.Clear();

            var shadowSettings = new DrawShadowsSettings(cull, i);
            shadowSettings.splitData.cullingSphere = splitData.cullingSphere;
            context.DrawShadows(ref shadowSettings);

            if (SystemInfo.usesReversedZBuffer)
            {
                projectionMatrix.m20 = -projectionMatrix.m20;
                projectionMatrix.m21 = -projectionMatrix.m21;
                projectionMatrix.m22 = -projectionMatrix.m22;
                projectionMatrix.m23 = -projectionMatrix.m23;
            }
            var scaleOffset = Matrix4x4.TRS(Vector3.one * 0.5f, Quaternion.identity, Vector3.one * 0.5f);
            worldToShadowMatrices[i] = scaleOffset * (projectionMatrix * viewMatrix);

            //if (split > 1)
            //{
            //    var tileMatrix = Matrix4x4.identity;
            //    tileMatrix.m00 = tileMatrix.m11 = tileScale;
            //    tileMatrix.m03 = tileOffsetX * tileScale;
            //    tileMatrix.m13 = tileOffsetY * tileScale;

            //    worldToShadowMatrices[i] = tileMatrix * worldToShadowMatrices[i];
            //}
            shadowBuffer.SetGlobalMatrixArray(worldToShadowMatricesId, worldToShadowMatrices);

            tileIndex += 1;

            if (shadowData[i].y <= 0f)
            {
                hardShadows = true;
            }
            else
            {
                softShadows = true;
            }
        }

        shadowBuffer.DisableScissorRect();
        shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap);

        float invShadowMapSize = 1f / shadowMapSize;

        shadowBuffer.SetGlobalVector(
            shadowMapSizeId, new Vector4(
                invShadowMapSize, invShadowMapSize, shadowMapSize, shadowMapSize
                )
            );

        CoreUtils.SetKeyword(shadowBuffer, shadowsSoftKeyword, softShadows);

        CoreUtils.SetKeyword(shadowBuffer, shadowsHardKeyword, hardShadows);

        shadowBuffer.EndSample("Render Shadows");
        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();
    }
        private bool RenderDirectionalCascadeShadowmap(ref CullResults cullResults, ref LightData lightData, ref ScriptableRenderContext context)
        {
            int shadowLightIndex = lightData.mainLightIndex;

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

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

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

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

            CommandBuffer cmd = CommandBufferPool.Get("Prepare Directional Shadowmap");

            m_ShadowCasterCascadesCount = m_ShadowSettings.directionalLightCascadeCount;

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

            Bounds bounds;

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

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

            m_DirectionalShadowmapTexture            = RenderTexture.GetTemporary(m_DirectionalShadowmapDescriptor);
            m_DirectionalShadowmapTexture.filterMode = FilterMode.Bilinear;
            m_DirectionalShadowmapTexture.wrapMode   = TextureWrapMode.Clamp;

            CoreUtils.SetRenderTarget(cmd, m_DirectionalShadowmapTexture, ClearFlag.Depth);

            bool success = false;

            for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex)
            {
                success = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex,
                                                                                           cascadeIndex, m_ShadowCasterCascadesCount, m_ShadowSettings.directionalLightCascades, shadowResolution, shadowNearPlane, out view, out proj,
                                                                                           out settings.splitData);

                float cullingSphereRadius = settings.splitData.cullingSphere.w;
                m_CascadeSplitDistances[cascadeIndex] = settings.splitData.cullingSphere;
                m_CascadeSplitRadii[cascadeIndex]     = cullingSphereRadius * cullingSphereRadius;

                if (!success)
                {
                    break;
                }

                m_CascadeSlices[cascadeIndex].offsetX         = (cascadeIndex % 2) * shadowResolution;
                m_CascadeSlices[cascadeIndex].offsetY         = (cascadeIndex / 2) * shadowResolution;
                m_CascadeSlices[cascadeIndex].resolution      = shadowResolution;
                m_CascadeSlices[cascadeIndex].shadowTransform = GetShadowTransform(proj, view);

                // If we have shadow cascades baked into the atlas we bake cascade transform
                // in each shadow matrix to save shader ALU and L/S
                if (m_ShadowCasterCascadesCount > 1)
                {
                    ApplySliceTransform(ref m_CascadeSlices[cascadeIndex], m_ShadowSettings.directionalShadowAtlasWidth, m_ShadowSettings.directionalShadowAtlasHeight);
                }

                SetupShadowCasterConstants(cmd, ref shadowLight, proj, shadowResolution);
                RenderShadowSlice(cmd, ref context, ref m_CascadeSlices[cascadeIndex], proj, view, settings);
            }

            if (success)
            {
                m_DirectionalShadowmapQuality = (m_ShadowSettings.directionalShadowQuality != LightShadows.Soft) ? LightShadows.Hard : light.shadows;

                // 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 (!m_ShadowSettings.screenSpace)
                {
                    m_DirectionalShadowmapQuality = LightShadows.Hard;
                }

                SetupDirectionalShadowReceiverConstants(cmd, shadowLight, ref context);
            }

            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);
            return(success);
        }
Example #10
0
        private bool RenderShadows(ref CullResults cullResults, ref VisibleLight shadowLight, int shadowLightIndex, ref ScriptableRenderContext context)
        {
            m_ShadowCasterCascadesCount = m_ShadowSettings.directionalLightCascadeCount;

            if (shadowLight.lightType == LightType.Spot)
            {
                m_ShadowCasterCascadesCount = 1;
            }

            int shadowResolution = GetMaxTileResolutionInAtlas(m_ShadowSettings.shadowAtlasWidth, m_ShadowSettings.shadowAtlasHeight, m_ShadowCasterCascadesCount);

            Bounds bounds;

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

            var setRenderTargetCommandBuffer = CommandBufferPool.Get();

            setRenderTargetCommandBuffer.name = "Render packed shadows";
            setRenderTargetCommandBuffer.GetTemporaryRT(m_ShadowMapProperty, m_ShadowSettings.shadowAtlasWidth,
                                                        m_ShadowSettings.shadowAtlasHeight, kShadowDepthBufferBits, FilterMode.Bilinear, RenderTextureFormat.Depth);
            setRenderTargetCommandBuffer.SetRenderTarget(m_ShadowMapRTID);
            setRenderTargetCommandBuffer.ClearRenderTarget(true, true, Color.black);
            context.ExecuteCommandBuffer(setRenderTargetCommandBuffer);
            CommandBufferPool.Release(setRenderTargetCommandBuffer);

            float   shadowNearPlane = m_Asset.ShadowNearOffset;
            Vector3 splitRatio      = m_ShadowSettings.directionalLightCascades;

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

            if (shadowLight.lightType == LightType.Spot)
            {
                needRendering = cullResults.ComputeSpotShadowMatricesAndCullingPrimitives(shadowLightIndex, out view, out proj,
                                                                                          out settings.splitData);

                if (!needRendering)
                {
                    return(false);
                }

                SetupShadowSliceTransform(0, shadowResolution, proj, view);
                RenderShadowSlice(ref context, 0, proj, view, settings);
            }
            else if (shadowLight.lightType == LightType.Directional)
            {
                for (int cascadeIdx = 0; cascadeIdx < m_ShadowCasterCascadesCount; ++cascadeIdx)
                {
                    needRendering = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex,
                                                                                                     cascadeIdx, m_ShadowCasterCascadesCount, splitRatio, shadowResolution, shadowNearPlane, out view, out proj,
                                                                                                     out settings.splitData);

                    m_DirectionalShadowSplitDistances[cascadeIdx]    = settings.splitData.cullingSphere;
                    m_DirectionalShadowSplitDistances[cascadeIdx].w *= settings.splitData.cullingSphere.w;

                    if (!needRendering)
                    {
                        return(false);
                    }

                    SetupShadowSliceTransform(cascadeIdx, shadowResolution, proj, view);
                    RenderShadowSlice(ref context, cascadeIdx, proj, view, settings);
                }
            }
            else
            {
                Debug.LogWarning("Only spot and directional shadow casters are supported in lightweight pipeline");
                return(false);
            }

            return(true);
        }
Example #11
0
    //Starts Rendering Part
    public static void Render(ScriptableRenderContext context, IEnumerable <Camera> cameras)
    {
        //For shadowmapping, the matrices from the light's point of view
        Matrix4x4 view             = Matrix4x4.identity;
        Matrix4x4 proj             = Matrix4x4.identity;
        bool      successShadowMap = false;

        foreach (Camera camera in cameras)
        {
            bool isSceneViewCam = camera.cameraType == CameraType.SceneView;
            //************************** UGUI Geometry on scene view *************************
            #if UNITY_EDITOR
            if (isSceneViewCam)
            {
                ScriptableRenderContext.EmitWorldGeometryForSceneView(camera);
            }
            #endif

            //************************** Culling ****************************************
            ScriptableCullingParameters cullingParams;
            if (!CullResults.GetCullingParameters(camera, out cullingParams))
            {
                continue;
            }
            CullResults cull = new CullResults();
            CullResults.Cull(ref cullingParams, context, ref cull);

            //************************** Lighting Variables *****************************
            CommandBuffer cmdLighting = new CommandBuffer();
            cmdLighting.name = "(" + camera.name + ")" + "Lighting variable";
            int   mainLightIndex = -1;
            Light mainLight      = null;

            Vector4[] lightPositions = new Vector4[8];
            Vector4[] lightColors    = new Vector4[8];
            Vector4[] lightAttn      = new Vector4[8];
            Vector4[] lightSpotDir   = new Vector4[8];

            //Initialise values
            for (int i = 0; i < 8; i++)
            {
                lightPositions[i] = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
                lightColors[i]    = Color.black;
                lightAttn[i]      = new Vector4(0.0f, 1.0f, 0.0f, 1.0f);
                lightSpotDir[i]   = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
            }

            for (int i = 0; i < cull.visibleLights.Count; i++)
            {
                VisibleLight light = cull.visibleLights[i];

                if (mainLightIndex == -1) //Directional light
                {
                    if (light.lightType == LightType.Directional)
                    {
                        Vector4 dir = light.localToWorld.GetColumn(2);
                        lightPositions[0] = new Vector4(-dir.x, -dir.y, -dir.z, 0);
                        lightColors[0]    = light.light.color;

                        float lightRangeSqr                 = light.range * light.range;
                        float fadeStartDistanceSqr          = 0.8f * 0.8f * lightRangeSqr;
                        float fadeRangeSqr                  = (fadeStartDistanceSqr - lightRangeSqr);
                        float oneOverFadeRangeSqr           = 1.0f / fadeRangeSqr;
                        float lightRangeSqrOverFadeRangeSqr = -lightRangeSqr / fadeRangeSqr;
                        float quadAtten = 25.0f / lightRangeSqr;
                        lightAttn[0] = new Vector4(quadAtten, oneOverFadeRangeSqr, lightRangeSqrOverFadeRangeSqr, 1.0f);

                        cmdLighting.SetGlobalVector("_LightColor0", lightColors[0]);
                        cmdLighting.SetGlobalVector("_WorldSpaceLightPos0", lightPositions[0]);

                        mainLight      = light.light;
                        mainLightIndex = i;
                    }
                }
                else
                {
                    continue;//so far just do only 1 directional light
                }
            }

            cmdLighting.SetGlobalVectorArray("unity_LightPosition", lightPositions);
            cmdLighting.SetGlobalVectorArray("unity_LightColor", lightColors);
            cmdLighting.SetGlobalVectorArray("unity_LightAtten", lightAttn);
            cmdLighting.SetGlobalVectorArray("unity_SpotDirection", lightSpotDir);

            context.ExecuteCommandBuffer(cmdLighting);
            cmdLighting.Release();

            //************************** Draw Settings ************************************
            FilterRenderersSettings filterSettings = new FilterRenderersSettings(true);

            DrawRendererSettings drawSettingsDefault = new DrawRendererSettings(camera, passNameDefault);
            drawSettingsDefault.rendererConfiguration = renderConfig;
            drawSettingsDefault.flags = DrawRendererFlags.EnableDynamicBatching;
            drawSettingsDefault.SetShaderPassName(5, m_UnlitPassName);

            DrawRendererSettings drawSettingsBase = new DrawRendererSettings(camera, passNameBase);
            drawSettingsBase.flags = DrawRendererFlags.EnableDynamicBatching;
            drawSettingsBase.rendererConfiguration = renderConfig;

            DrawRendererSettings drawSettingsAdd = new DrawRendererSettings(camera, passNameAdd);
            drawSettingsAdd.flags = DrawRendererFlags.EnableDynamicBatching;
            drawSettingsAdd.rendererConfiguration = renderConfig;

            DrawRendererSettings drawSettingsDepth = new DrawRendererSettings(camera, passNameShadow);
            drawSettingsDepth.flags = DrawRendererFlags.EnableDynamicBatching;
            //drawSettingsBase.rendererConfiguration = renderConfig;

            //************************** Set TempRT ************************************
            CommandBuffer cmdTempId = new CommandBuffer();
            cmdTempId.name = "(" + camera.name + ")" + "Setup TempRT";

            //Depth
            RenderTextureDescriptor depthRTDesc = new RenderTextureDescriptor(camera.pixelWidth, camera.pixelHeight);
            depthRTDesc.colorFormat     = m_DepthFormat;
            depthRTDesc.depthBufferBits = depthBufferBits;
            cmdTempId.GetTemporaryRT(m_DepthRTid, depthRTDesc, FilterMode.Bilinear);

            //Color
            RenderTextureDescriptor colorRTDesc = new RenderTextureDescriptor(camera.pixelWidth, camera.pixelHeight);
            colorRTDesc.colorFormat       = m_ColorFormat;
            colorRTDesc.depthBufferBits   = depthBufferBits; //have depth because we don't want to ruin the _CameraDepthTexture
            colorRTDesc.sRGB              = true;
            colorRTDesc.msaaSamples       = 1;
            colorRTDesc.enableRandomWrite = false;
            cmdTempId.GetTemporaryRT(m_ColorRTid, colorRTDesc, FilterMode.Bilinear);

            //Shadow
            RenderTextureDescriptor shadowRTDesc = new RenderTextureDescriptor(m_ShadowRes, m_ShadowRes);
            shadowRTDesc.colorFormat       = m_ShadowFormat;
            shadowRTDesc.depthBufferBits   = depthBufferBits; //have depth because it is also a depth texture
            shadowRTDesc.msaaSamples       = 1;
            shadowRTDesc.enableRandomWrite = false;
            cmdTempId.GetTemporaryRT(m_ShadowMapLightid, shadowRTDesc, FilterMode.Bilinear);//depth per light

            //ScreenSpaceShadowMap
            RenderTextureDescriptor shadowMapRTDesc = new RenderTextureDescriptor(camera.pixelWidth, camera.pixelHeight);
            shadowMapRTDesc.colorFormat       = m_ShadowMapFormat;
            shadowMapRTDesc.depthBufferBits   = 0;
            shadowMapRTDesc.msaaSamples       = 1;
            shadowMapRTDesc.enableRandomWrite = false;
            cmdTempId.GetTemporaryRT(m_ShadowMapid, shadowMapRTDesc, FilterMode.Bilinear);//screen space shadow

            context.ExecuteCommandBuffer(cmdTempId);
            cmdTempId.Release();

            //************************** Do shadow? ************************************
            Bounds bounds;
            bool   doShadow = cull.GetShadowCasterBounds(mainLightIndex, out bounds);

            //************************** Shadow Mapping ************************************
            if (doShadow && !isSceneViewCam)
            {
                DrawShadowsSettings shadowSettings = new DrawShadowsSettings(cull, mainLightIndex);

                successShadowMap = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(mainLightIndex,
                                                                                             0, 1, new Vector3(1, 0, 0),
                                                                                             m_ShadowRes, mainLight.shadowNearPlane, out view, out proj,
                                                                                             out shadowSettings.splitData);

                CommandBuffer cmdShadow = new CommandBuffer();
                cmdShadow.name = "(" + camera.name + ")" + "Shadow Mapping";

                cmdShadow.SetRenderTarget(m_ShadowMapLight);
                cmdShadow.ClearRenderTarget(true, true, Color.black);

                //Change the view to light's point of view
                cmdShadow.SetViewport(new Rect(0, 0, m_ShadowRes, m_ShadowRes));
                cmdShadow.EnableScissorRect(new Rect(4, 4, m_ShadowRes - 8, m_ShadowRes - 8));
                cmdShadow.SetViewProjectionMatrices(view, proj);

                context.ExecuteCommandBuffer(cmdShadow);
                cmdShadow.Clear();

                //Render Shadowmap
                context.DrawShadows(ref shadowSettings);

                cmdShadow.DisableScissorRect();
                cmdShadow.SetGlobalTexture(m_ShadowMapLightid, m_ShadowMapLight);
                context.ExecuteCommandBuffer(cmdShadow);
                cmdShadow.Clear();
                cmdShadow.Release();
            }

            //************************** Camera Parameters ************************************
            context.SetupCameraProperties(camera);

            //************************** Depth (for CameraDepthTexture) ************************************
            CommandBuffer cmdDepthOpaque = new CommandBuffer();
            cmdDepthOpaque.name = "(" + camera.name + ")" + "Make CameraDepthTexture";

            cmdDepthOpaque.SetRenderTarget(m_DepthRT);
            cmdDepthOpaque.ClearRenderTarget(true, true, Color.black);
            context.ExecuteCommandBuffer(cmdDepthOpaque);
            cmdDepthOpaque.Clear();

            filterSettings.renderQueueRange = RenderQueueRange.opaque;
            drawSettingsDepth.sorting.flags = SortFlags.CommonOpaque;
            context.DrawRenderers(cull.visibleRenderers, ref drawSettingsDepth, filterSettings);

            cmdDepthOpaque.SetGlobalTexture(m_DepthRTid, m_DepthRT);
            context.ExecuteCommandBuffer(cmdDepthOpaque);
            cmdDepthOpaque.Release();

            //************************** Screen Space Shadow ************************************
            if (doShadow)
            {
                CommandBuffer cmdShadow2 = new CommandBuffer();
                cmdShadow2.name = "(" + camera.name + ")" + "Screen Space Shadow";

                //Bias
                if (mainLight != null)
                {
                    float sign = (SystemInfo.usesReversedZBuffer) ? 1.0f : -1.0f;
                    if (isSceneViewCam)
                    {
                        sign = -sign * 0.01f;
                    }
                    float bias = mainLight.shadowBias * proj.m22 * sign;

                    cmdShadow2.SetGlobalFloat("_ShadowBias", bias);
                }

                //Shadow Transform
                if (successShadowMap)
                {
                    cmdShadow2.EnableShaderKeyword("SHADOWS_SCREEN");
                    cmdShadow2.EnableShaderKeyword("LIGHTMAP_SHADOW_MIXING");

                    if (SystemInfo.usesReversedZBuffer)
                    {
                        proj.m20 = -proj.m20;
                        proj.m21 = -proj.m21;
                        proj.m22 = -proj.m22;
                        proj.m23 = -proj.m23;
                    }

                    Matrix4x4 WorldToShadow = proj * view;

                    float f = 0.5f;

                    var textureScaleAndBias = Matrix4x4.identity;
                    textureScaleAndBias.m00 = f;
                    textureScaleAndBias.m11 = f;
                    textureScaleAndBias.m22 = f;
                    textureScaleAndBias.m03 = f;
                    textureScaleAndBias.m23 = f;
                    textureScaleAndBias.m13 = f;

                    WorldToShadow = textureScaleAndBias * WorldToShadow;

                    cmdShadow2.SetGlobalMatrix("_WorldToShadow", WorldToShadow);
                    cmdShadow2.SetGlobalFloat("_ShadowStrength", mainLight.shadowStrength);
                }

                //Render the screen-space shadow
                cmdShadow2.Blit(m_ShadowMap, m_ShadowMap, m_ScreenSpaceShadowsMaterial);
                cmdShadow2.SetGlobalTexture(m_ShadowMapid, m_ShadowMap);

                context.ExecuteCommandBuffer(cmdShadow2);
                cmdShadow2.Release();
            }

            //************************** Clear ************************************
            CommandBuffer cmd = new CommandBuffer();
            cmd.name = "(" + camera.name + ")" + "Clear Flag";

            cmd.SetRenderTarget(m_ColorRT);
            ClearFlag(cmd, camera, camera.backgroundColor);

            context.ExecuteCommandBuffer(cmd);
            cmd.Release();

            //************************** Skybox ************************************
            if (camera.clearFlags == CameraClearFlags.Skybox)
            {
                context.DrawSkybox(camera);
            }

            //************************** Opaque ************************************
            filterSettings.renderQueueRange = RenderQueueRange.opaque;

            // DEFAULT pass, draw shaders without a pass name
            drawSettingsDefault.sorting.flags = SortFlags.CommonOpaque;
            context.DrawRenderers(cull.visibleRenderers, ref drawSettingsDefault, filterSettings);

            // BASE pass
            drawSettingsBase.sorting.flags = SortFlags.CommonOpaque;
            context.DrawRenderers(cull.visibleRenderers, ref drawSettingsBase, filterSettings);

            // ADD pass
            drawSettingsAdd.sorting.flags = SortFlags.CommonOpaque;
            context.DrawRenderers(cull.visibleRenderers, ref drawSettingsAdd, filterSettings);

            //************************** Blit to Camera Target ************************************
            // so that reflection probes will work + screen view buttons
            CommandBuffer cmdColorOpaque = new CommandBuffer();
            cmdColorOpaque.name = "(" + camera.name + ")" + "After opaque";

            //This blit is necessary for Windows...It makes sure the Z is correct for transparent objects
            cmdColorOpaque.Blit(m_ColorRT, BuiltinRenderTextureType.CameraTarget);
            cmdColorOpaque.SetRenderTarget(m_ColorRT);

            //"Grab" pass
            cmdColorOpaque.SetGlobalTexture(m_GrabOpaqueRTid, m_ColorRT);

            context.ExecuteCommandBuffer(cmdColorOpaque);
            cmdColorOpaque.Release();

            //************************** Transparent ************************************
            filterSettings.renderQueueRange = RenderQueueRange.transparent;

            // DEFAULT pass
            drawSettingsDefault.sorting.flags = SortFlags.CommonTransparent;
            context.DrawRenderers(cull.visibleRenderers, ref drawSettingsDefault, filterSettings);

            // BASE pass
            drawSettingsBase.sorting.flags = SortFlags.CommonTransparent;
            context.DrawRenderers(cull.visibleRenderers, ref drawSettingsBase, filterSettings);

            //************************** Blit to Camera Target ************************************
            // so that reflection probes will work + screen view buttons
            CommandBuffer cmdColor = new CommandBuffer();
            cmdColor.name = "(" + camera.name + ")" + "After transparent";
            cmdColor.Blit(m_ColorRT, BuiltinRenderTextureType.CameraTarget);
            cmdColor.SetRenderTarget(m_ColorRT);
            context.ExecuteCommandBuffer(cmdColor);
            cmdColor.Release();

            //************************** Post-processing ************************************
            m_CameraPostProcessLayer = camera.GetComponent <PostProcessLayer>();
            if (m_CameraPostProcessLayer != null && m_CameraPostProcessLayer.enabled)
            {
                CommandBuffer cmdpp = new CommandBuffer();
                cmdpp.name = "(" + camera.name + ")" + "Post-processing";

                m_PostProcessRenderContext.Reset();
                m_PostProcessRenderContext.camera       = camera;
                m_PostProcessRenderContext.source       = m_ColorRT;
                m_PostProcessRenderContext.sourceFormat = m_ColorFormat;
                m_PostProcessRenderContext.destination  = BuiltinRenderTextureType.CameraTarget;
                m_PostProcessRenderContext.command      = cmdpp;
                m_PostProcessRenderContext.flip         = camera.targetTexture == null;
                m_CameraPostProcessLayer.Render(m_PostProcessRenderContext);

                //Target is already CameraTarget

                context.ExecuteCommandBuffer(cmdpp);
                cmdpp.Release();
            }

            //************************** Scene View Fix ************************************
            #if UNITY_EDITOR
            if (isSceneViewCam)     //Copy depth to backbuffer's depth buffer
            {
                CommandBuffer cmdSceneDepth = new CommandBuffer();
                cmdSceneDepth.name = "(" + camera.name + ")" + "Copy Depth to CameraTarget";
                cmdSceneDepth.Blit(m_DepthRT, BuiltinRenderTextureType.CameraTarget, m_CopyDepthMaterial);
                context.ExecuteCommandBuffer(cmdSceneDepth);
                cmdSceneDepth.Release();
            }
            #endif

            //************************** Clean Up ************************************
            CommandBuffer cmdclean = new CommandBuffer();
            cmdclean.name = "(" + camera.name + ")" + "Clean Up";
            cmdclean.ReleaseTemporaryRT(m_ColorRTid);
            cmdclean.ReleaseTemporaryRT(m_DepthRTid);
            cmdclean.ReleaseTemporaryRT(m_ShadowMapid);
            cmdclean.ReleaseTemporaryRT(m_ShadowMapLightid);
            context.ExecuteCommandBuffer(cmdclean);
            cmdclean.Release();

            context.Submit();
        }
    }
Example #12
0
    void RenderShadows(ScriptableRenderContext context)
    {
        int split;

        if (shadowTileCount <= 1)
        {
            split = 1;
        }
        else if (shadowTileCount <= 4)
        {
            split = 2;
        }
        else if (shadowTileCount <= 9)
        {
            split = 3;
        }
        else
        {
            split = 4;
        }
        float tileSize  = shadowMapSize / split;
        float tileScale = 1f / split;

        shadowMap = SetShadowRenderTarget();
        shadowBuffer.BeginSample("Render Shadows");
        shadowBuffer.SetGlobalVector(globalShadowDataId, new Vector4(tileScale, shadowDistance * shadowDistance));
        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();

        bool softShadows = false;
        bool hardShadows = false;
        int  tileIndex   = 0;

        for (int i = mainLightExists ? 1 : 0; i < cull.visibleLights.Count; i++)
        {
            if (i == MAX_VISIBLE_LIGHTS)
            {
                break;
            }

            if (shadowData[i].x <= 0f)
            {
                continue;
            }

            Matrix4x4       viewMatrix, projectionMatrix;
            ShadowSplitData splitData;

            bool validShadows = false;
            if (shadowData[i].z > 0f)
            {
                validShadows = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(i, 0, 1, Vector3.right, (int)tileSize, cull.visibleLights[i].light.shadowNearPlane, out viewMatrix, out projectionMatrix, out splitData);
            }
            else
            {
                validShadows = cull.ComputeSpotShadowMatricesAndCullingPrimitives(i, out viewMatrix, out projectionMatrix, out splitData);
            }
            if (!validShadows)
            {
                shadowData[i].x = 0f;
                continue;
            }

            Vector2 tileOffset = ConfigureShadowTile(tileIndex, split, tileSize);
            shadowData[i].z = tileOffset.x * tileScale;
            shadowData[i].w = tileOffset.x * tileScale;

            shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);

            context.ExecuteCommandBuffer(shadowBuffer);
            shadowBuffer.Clear();

            var shadowSettings = new DrawShadowsSettings(cull, i);
            shadowSettings.splitData.cullingSphere = splitData.cullingSphere;
            context.DrawShadows(ref shadowSettings);

            CalculateWorldToShadowMatrix(ref viewMatrix, ref projectionMatrix, out worldToShadowMatrices[i]);

            if (shadowData[i].y <= 0f)
            {
                hardShadows = true;
            }
            else
            {
                softShadows = true;
            }

            shadowBuffer.SetGlobalFloat(shadowBiasId, cull.visibleLights[i].light.shadowBias);

            tileIndex += 1;
        }

        CoreUtils.SetKeyword(shadowBuffer, shadowsHardKeyword, hardShadows);
        CoreUtils.SetKeyword(shadowBuffer, shadowsSoftKeyword, softShadows);

        shadowBuffer.SetGlobalMatrixArray(worldToShadowMatricesId, worldToShadowMatrices);

        shadowBuffer.SetGlobalVectorArray(shadowDataId, shadowData);

        float invShadowMapSize = 1f / shadowMapSize;

        shadowBuffer.SetGlobalVector(shadowMapSizeId, new Vector4(invShadowMapSize, invShadowMapSize, shadowMapSize, shadowMapSize));

        shadowBuffer.DisableScissorRect();

        shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap);

        shadowBuffer.EndSample("Render Shadows");
        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();
    }
Example #13
0
    // 绘制ShadowMap
    void RenderShadows(ScriptableRenderContext context)
    {
        // 计算阴影图集的划分尺度
        int split;

        if (shadowTileCount <= 1)
        {
            split = 1;
        }
        else if (shadowTileCount <= 4)
        {
            split = 2;
        }
        else if (shadowTileCount <= 9)
        {
            split = 3;
        }
        else
        {
            split = 4;
        }

        // 子图集的大小
        float tileSize  = shadowMapSize / split;
        float tileScale = 1f / split;

        shadowMap = SetShadowRenderTarget();

        shadowBuffer.BeginSample("HY Render Shadows");

        // 设置全局变量
        shadowBuffer.SetGlobalVector(globalShadowDataId, new Vector4(tileScale, shadowDistance * shadowDistance));

        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();

        int tileIndex = 0;

        bool hardShadows = false;
        bool softShadows = false;

        // 如果存在主光,需要跳过
        for (int i = mainLightExists ? 1 : 0; i < cull.visibleLights.Count; i++)
        {
            if (i == maxVisibleLights)
            {
                break;
            }

            // 强度不为正,直接跳过
            if (shadowData[i].x <= 0f)
            {
                continue;
            }

            // 获取灯的视矩阵和投影矩阵
            Matrix4x4       viewMatrix, projectionMatrix;
            ShadowSplitData splitData;
            bool            validShadows;
            if (shadowData[i].z > 0f)
            {
                validShadows = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(
                    i, 0, 1, Vector3.right, (int)tileSize,
                    cull.visibleLights[i].light.shadowNearPlane,
                    out viewMatrix, out projectionMatrix, out splitData);
            }
            else
            {
                validShadows = cull.ComputeSpotShadowMatricesAndCullingPrimitives(i, out viewMatrix, out projectionMatrix, out splitData);
            }
            if (!validShadows)
            {
                // 获取矩阵失败则强度置0
                shadowData[i].x = 0f;
                continue;
            }

            Vector2 tileOffset = ConfigureShadowTile(tileIndex, split, tileSize);
            // 存储地图集的偏移
            shadowData[i].z = tileOffset.x * tileScale;
            shadowData[i].w = tileOffset.y * tileScale;

            // 设置灯的视矩阵和投影矩阵
            shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
            // 设置阴影偏移
            shadowBuffer.SetGlobalFloat(shadowBiasId, cull.visibleLights[i].light.shadowBias);
            context.ExecuteCommandBuffer(shadowBuffer);
            shadowBuffer.Clear();

            // 绘制阴影
            var shadowSettings = new DrawShadowsSettings(cull, i);
            // 设置方向光的剔除球,其他光不受影响
            shadowSettings.splitData.cullingSphere = splitData.cullingSphere;
            context.DrawShadows(ref shadowSettings);

            CalculateWorldToShadowMatrix(ref viewMatrix, ref projectionMatrix, out worldToShadowMatrices[i]);

            tileIndex += 1;

            if (shadowData[i].y <= 0f)
            {
                hardShadows = true;
            }
            else
            {
                softShadows = true;
            }
        }

        // 关闭裁剪
        shadowBuffer.DisableScissorRect();

        // 设置ShadowMap
        shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap);

        // 设置世界空间到阴影空间的转换矩阵
        shadowBuffer.SetGlobalMatrixArray(worldToShadowMatricesId, worldToShadowMatrices);

        // 设置阴影数据
        shadowBuffer.SetGlobalVectorArray(shadowDataId, shadowData);

        // 设置阴影纹理大小
        float invShadowMapSize = 1f / shadowMapSize;

        shadowBuffer.SetGlobalVector(shadowMapSizeId, new Vector4(invShadowMapSize, invShadowMapSize, shadowMapSize, shadowMapSize));

        // 设置阴影关键字
        CoreUtils.SetKeyword(shadowBuffer, shadowsHardKeyword, hardShadows);
        CoreUtils.SetKeyword(shadowBuffer, shadowsSoftKeyword, softShadows);

        shadowBuffer.EndSample("HY Render Shadows");
        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();
    }
        private bool RenderShadows(ref CullResults cullResults, ref VisibleLight shadowLight, int shadowLightIndex, ref ScriptableRenderContext context, Color backgroundColor)
        {
            m_ShadowCasterCascadesCount = m_ShadowSettings.directionalLightCascadeCount;

            if (shadowLight.lightType == UnityEngine.LightType.Spot)
            {
                m_ShadowCasterCascadesCount = 1;
            }

            int shadowResolution = GetMaxTileResolutionInAtlas(m_ShadowSettings.shadowAtlasWidth, m_ShadowSettings.shadowAtlasHeight, m_ShadowCasterCascadesCount);

            Bounds bounds;

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

            float shadowNearPlane = m_Asset.ShadowNearOffset;

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

            var cmd = CommandBufferPool.Get("Prepare Shadowmap");
            RenderTextureDescriptor shadowmapDescriptor = new RenderTextureDescriptor(m_ShadowSettings.shadowAtlasWidth,
                                                                                      m_ShadowSettings.shadowAtlasHeight, m_ShadowSettings.shadowmapTextureFormat, kShadowBufferBits);

            shadowmapDescriptor.shadowSamplingMode = ShadowSamplingMode.CompareDepths;
            m_ShadowMapRT            = RenderTexture.GetTemporary(shadowmapDescriptor);
            m_ShadowMapRT.filterMode = FilterMode.Bilinear;
            m_ShadowMapRT.wrapMode   = TextureWrapMode.Clamp;

            // LightweightPipeline.SetRenderTarget is meant to be used with camera targets, not shadowmaps
            CoreUtils.SetRenderTarget(cmd, m_ShadowMapRT, ClearFlag.Depth, CoreUtils.ConvertSRGBToActiveColorSpace(backgroundColor));

            if (shadowLight.lightType == UnityEngine.LightType.Spot)
            {
                success = cullResults.ComputeSpotShadowMatricesAndCullingPrimitives(shadowLightIndex, out view, out proj,
                                                                                    out settings.splitData);

                if (success)
                {
                    SetupShadowCasterConstants(cmd, ref shadowLight, proj, shadowResolution);
                    SetupShadowSliceTransform(0, shadowResolution, proj, view);
                    RenderShadowSlice(cmd, ref context, 0, proj, view, settings);
                }
            }
            else if (shadowLight.lightType == UnityEngine.LightType.Directional)
            {
                for (int cascadeIdx = 0; cascadeIdx < m_ShadowCasterCascadesCount; ++cascadeIdx)
                {
                    success = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex,
                                                                                               cascadeIdx, m_ShadowCasterCascadesCount, m_ShadowSettings.directionalLightCascades, shadowResolution, shadowNearPlane, out view, out proj,
                                                                                               out settings.splitData);

                    float cullingSphereRadius = settings.splitData.cullingSphere.w;
                    m_DirectionalShadowSplitDistances[cascadeIdx] = settings.splitData.cullingSphere;
                    m_DirectionalShadowSplitRadii[cascadeIdx]     = cullingSphereRadius * cullingSphereRadius;

                    if (!success)
                    {
                        break;
                    }

                    SetupShadowCasterConstants(cmd, ref shadowLight, proj, shadowResolution);
                    SetupShadowSliceTransform(cascadeIdx, shadowResolution, proj, view);
                    RenderShadowSlice(cmd, ref context, cascadeIdx, proj, view, settings);
                }
            }
            else
            {
                Debug.LogWarning("Only spot and directional shadow casters are supported in lightweight pipeline");
            }

            if (success)
            {
                SetupShadowReceiverConstants(cmd, shadowLight, ref context);
            }

            CommandBufferPool.Release(cmd);
            return(success);
        }
        //---------------------------------------------------------------------------------------------------------------------------------------------------
        // Render shadows
        //---------------------------------------------------------------------------------------------------------------------------------------------------
        void RenderPackedShadows(RenderLoop loop, CullResults cullResults, ref ShadowOutput packedShadows)
        {
            var setRenderTargetCommandBuffer = new CommandBuffer();

            setRenderTargetCommandBuffer.name = "Render packed shadows";
            setRenderTargetCommandBuffer.GetTemporaryRT(m_ShadowTexName, m_Settings.shadowAtlasWidth, m_Settings.shadowAtlasHeight, k_DepthBuffer, FilterMode.Bilinear, RenderTextureFormat.Shadowmap, RenderTextureReadWrite.Linear);
            setRenderTargetCommandBuffer.SetRenderTarget(new RenderTargetIdentifier(m_ShadowTexName));

            setRenderTargetCommandBuffer.ClearRenderTarget(true, true, Color.green);
            loop.ExecuteCommandBuffer(setRenderTargetCommandBuffer);
            setRenderTargetCommandBuffer.Dispose();

            VisibleLight[] visibleLights = cullResults.visibleLights;
            var            shadowSlices  = packedShadows.shadowSlices;

            // Render each light's shadow buffer into a subrect of the shared depth texture
            for (int lightIndex = 0; lightIndex < packedShadows.shadowLights.Length; lightIndex++)
            {
                int shadowSliceCount = packedShadows.shadowLights[lightIndex].shadowSliceCount;
                if (shadowSliceCount == 0)
                {
                    continue;
                }

                Profiler.BeginSample("Shadows.GetShadowCasterBounds");
                Bounds bounds;
                if (!cullResults.GetShadowCasterBounds(lightIndex, out bounds))
                {
                    Profiler.EndSample();
                    return;
                }
                Profiler.EndSample();

                Profiler.BeginSample("Shadows.DrawShadows");

                Matrix4x4 proj;
                Matrix4x4 view;

                var lightType      = visibleLights[lightIndex].lightType;
                var lightDirection = visibleLights[lightIndex].light.transform.forward;
                var shadowNearClip = visibleLights[lightIndex].light.shadowNearPlane;

                int shadowSliceIndex = packedShadows.GetShadowSliceIndex(lightIndex, 0);

                if (lightType == LightType.Spot)
                {
                    var  settings      = new DrawShadowsSettings(cullResults, lightIndex);
                    bool needRendering = cullResults.ComputeSpotShadowsMatricesAndCullingPrimitives(lightIndex, out view, out proj, out settings.splitData);
                    SetupShadowSplitMatrices(ref packedShadows.shadowSlices[shadowSliceIndex], proj, view);
                    if (needRendering)
                    {
                        RenderShadowSplit(ref shadowSlices[shadowSliceIndex], lightDirection, proj, view, ref loop, settings);
                    }
                }
                else if (lightType == LightType.Directional)
                {
                    Vector3 splitRatio = m_Settings.directionalLightCascades;

                    for (int s = 0; s < 4; ++s)
                    {
                        packedShadows.directionalShadowSplitSphereSqr[s] = new Vector4(0, 0, 0, float.NegativeInfinity);
                    }

                    for (int s = 0; s < shadowSliceCount; ++s, shadowSliceIndex++)
                    {
                        var  settings         = new DrawShadowsSettings(cullResults, lightIndex);
                        var  shadowResolution = shadowSlices[shadowSliceIndex].shadowResolution;
                        bool needRendering    = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, s, shadowSliceCount, splitRatio, shadowResolution, shadowNearClip, out view, out proj, out settings.splitData);

                        packedShadows.directionalShadowSplitSphereSqr[s]    = settings.splitData.cullingSphere;
                        packedShadows.directionalShadowSplitSphereSqr[s].w *= packedShadows.directionalShadowSplitSphereSqr[s].w;

                        SetupShadowSplitMatrices(ref shadowSlices[shadowSliceIndex], proj, view);
                        if (needRendering)
                        {
                            RenderShadowSplit(ref shadowSlices[shadowSliceIndex], lightDirection, proj, view, ref loop, settings);
                        }
                    }
                }
                else if (lightType == LightType.Point)
                {
                    for (int s = 0; s < shadowSliceCount; ++s, shadowSliceIndex++)
                    {
                        var  settings      = new DrawShadowsSettings(cullResults, lightIndex);
                        bool needRendering = cullResults.ComputePointShadowsMatricesAndCullingPrimitives(lightIndex, (CubemapFace)s, 2.0f, out view, out proj, out settings.splitData);

                        SetupShadowSplitMatrices(ref shadowSlices[shadowSliceIndex], proj, view);
                        if (needRendering)
                        {
                            RenderShadowSplit(ref shadowSlices[shadowSliceIndex], lightDirection, proj, view, ref loop, settings);
                        }
                    }
                }
                Profiler.EndSample();
            }
        }