Ejemplo n.º 1
0
        //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.mainLightShadowCascadesCount, shadowData.mainLightShadowCascadesSplit, 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.viewMatrix = viewMatrix;
        //shadowSliceData.projectionMatrix = projMatrix;
        //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.mainLightShadowCascadesCount > 1)
        //    ApplySliceTransform(ref shadowSliceData, shadowData.mainLightShadowmapWidth, shadowData.mainLightShadowmapHeight);

        //return success;
        //return false;
        //}

        public static bool ExtractSpotLightMatrix(ref CullResults cullResults, ref ShadowData shadowData, int shadowLightIndex, out Matrix4x4 shadowMatrix, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix)
        {
            ShadowSplitData splitData;
            bool            success = cullResults.ComputeSpotShadowMatricesAndCullingPrimitives(shadowLightIndex, out viewMatrix, out projMatrix, out splitData);

            shadowMatrix = GetShadowTransform(projMatrix, viewMatrix);
            return(success);
        }
Ejemplo n.º 2
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();
    }
Ejemplo n.º 3
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 void RenderLocalShadowmapAtlas(ref CullResults cullResults, ref LightData lightData, ref ScriptableRenderContext context)
        {
            List <int>          localLightIndices = lightData.localLightIndices;
            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;
            }

            CommandBuffer cmd = CommandBufferPool.Get("Prepare Local Lights Shadowmap");
            Matrix4x4     view, proj;
            Bounds        bounds;

            // 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      = m_ShadowSettings.localShadowAtlasWidth;
            int atlasHeight     = m_ShadowSettings.localShadowAtlasHeight;
            int sliceResolution = GetMaxTileResolutionInAtlas(atlasWidth, atlasHeight, shadowCastingLightsCount);
            int shadowSampling  = 0;

            m_LocalShadowmapTexture            = RenderTexture.GetTemporary(m_LocalShadowmapDescriptor);
            m_LocalShadowmapTexture.filterMode = FilterMode.Bilinear;
            m_LocalShadowmapTexture.wrapMode   = TextureWrapMode.Clamp;

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

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

                var settings = new DrawShadowsSettings(cullResults, shadowLightIndex);

                if (cullResults.ComputeSpotShadowMatricesAndCullingPrimitives(shadowLightIndex, out view, out proj, out settings.splitData))
                {
                    // 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(localLightsCount <= 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 = GetShadowTransform(proj, view);

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

                    SetupShadowCasterConstants(cmd, ref shadowLight, proj, sliceResolution);
                    RenderShadowSlice(cmd, ref context, ref m_LocalLightSlices[i], proj, view, settings);
                    m_LocalShadowStrength[i] = light.shadowStrength;
                    shadowSampling           = Math.Max(shadowSampling, (int)light.shadows);
                }
            }

            SetupLocalLightsShadowReceiverConstants(cmd, ref context);

            m_LocalShadowmapQuality = (LightShadows)Math.Min(shadowSampling, (int)m_ShadowSettings.directionalShadowQuality);
            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);
        }
    private 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;
        }

        //虽然也可以用tex2DArray 但是不支持一些老机型手机
        //所以这里用图片分割成4*4块
        float tileSize  = shadowMapSize / split;
        float tileScale = 1f / split;

        globalShadowData.x = tileScale;

        shadowMap = SetShadowRenderTarget();

        shadowBuffer.BeginSample("Render Addition 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 < maxVisibleLights; i++)
        {
            //剔除没有强度的 或者不需要的
            if (shadowData[i].x <= 0f)
            {
                continue;
            }

            Matrix4x4       viewMatrix, projectionMatrix;
            ShadowSplitData splitData;

            //是否能生成有效的矩阵 如果没有 x=0 表示不启用阴影
            bool validShadows;

            if (shadowData[i].z > 0f)
            {
                //参数 1:灯光index  2:cascadeIndex  3:cascadeCount   4:cascade 分级距离
                //5: 分辨率   6:nearPlane 如果太近不画
                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);
            context.ExecuteCommandBuffer(shadowBuffer);
            shadowBuffer.Clear();

            var shadowSettings = new DrawShadowsSettings(cull, i);
            //用球剔除 xyz是中心点  w是半径
            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;
            }

            tileIndex += 1;
        }

        //渲染完成禁用裁剪   不然平常渲染也会收到影响
        shadowBuffer.DisableScissorRect();

        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));
        //if (haveSoftShadow == LightShadows.Soft)
        //{
        //    shadowBuffer.EnableShaderKeyword(shadowSoftKeyword);
        //}
        //else
        //{
        //    shadowBuffer.DisableShaderKeyword(shadowSoftKeyword);
        //}
        //下面是上面的封装
        CoreUtils.SetKeyword(shadowBuffer, shadowsHardKeyword, hardShadows);
        CoreUtils.SetKeyword(shadowBuffer, shadowsSoftKeyword, softShadows);

        shadowBuffer.EndSample("Render Addition Shadows");
        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();
    }
Ejemplo n.º 6
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();
    }
Ejemplo n.º 7
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);
        }
Ejemplo n.º 8
0
    private void RenderShadows(ScriptableRenderContext renderContext)
    {
        shadowMap            = RenderTexture.GetTemporary(shadowMapSize, shadowMapSize, 16, RenderTextureFormat.Shadowmap);
        shadowMap.filterMode = FilterMode.Bilinear;
        shadowMap.wrapMode   = TextureWrapMode.Clamp;
        //tell the GPU to render to our shaow map,load and store more precise texture
        CoreUtils.SetRenderTarget(shadowBuffer, shadowMap, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth);

        shadowBuffer.BeginSample("Render Shadows");
        renderContext.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();

        Matrix4x4       viewMatrix, projectionMatrix;
        ShadowSplitData splitData;

        cull.ComputeSpotShadowMatricesAndCullingPrimitives(0, out viewMatrix, out projectionMatrix, out splitData);
        shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
        shadowBuffer.SetGlobalFloat(shadowBiasId, cull.visibleLights[0].light.shadowBias);
        renderContext.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();

        var shadowSettings = new DrawShadowsSettings(cull, 0);

        renderContext.DrawShadows(ref shadowSettings);

        //Opengl Z is reversed
        if (SystemInfo.usesReversedZBuffer)
        {
            projectionMatrix.m20 = -projectionMatrix.m20;
            projectionMatrix.m21 = -projectionMatrix.m21;
            projectionMatrix.m22 = -projectionMatrix.m22;
            projectionMatrix.m23 = -projectionMatrix.m23;
        }
        //clip space goes from -1 to 1,while texture coordinates and depth go from 0 to 1.so need to tranfer the matrix
        var scaleOffset = Matrix4x4.identity;

        scaleOffset.m00 = scaleOffset.m11 = scaleOffset.m22 = 0.5f;
        scaleOffset.m03 = scaleOffset.m13 = scaleOffset.m23 = 0.5f;

        Matrix4x4 worldToShadowMatrix = scaleOffset * (projectionMatrix * viewMatrix);

        shadowBuffer.SetGlobalMatrix(worldToShadowMatrixId, worldToShadowMatrix);
        shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap);
        shadowBuffer.SetGlobalFloat(shadowStrengthId, cull.visibleLights[0].light.shadowStrength);

        float invShadowMapSize = 1f / shadowMapSize;

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

        // if(cull.visibleLights[0].light.shadows == LightShadows.Soft){
        //     shadowBuffer.EnableShaderKeyword(shadowSoftKeyword);
        // }else
        // {
        //     shadowBuffer.DisableShaderKeyword(shadowSoftKeyword);
        // }

        CoreUtils.SetKeyword(shadowBuffer, shadowSoftKeyword, cull.visibleLights[0].light.shadows == LightShadows.Soft);

        shadowBuffer.EndSample("Render Shadows");
        renderContext.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();
    }
Ejemplo n.º 9
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();
    }
Ejemplo n.º 10
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;
        Rect  tileViewport = new Rect(0f, 0f, tileSize, tileSize);

        //width, height, precision, type
        shadowMap = RenderTexture.GetTemporary(shadowMapSize, shadowMapSize, 16, RenderTextureFormat.Shadowmap);

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

        //set GPU prepared for shadowMap
        CoreUtils.SetRenderTarget(shadowBuffer, shadowMap,
                                  RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store,
                                  ClearFlag.Depth);

        shadowBuffer.BeginSample("Render Shadows");
        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;
            }
            //shadowStrength <=0 indicates the light needs no shadowmap
            if (shadowData[i].x <= 0f)
            {
                continue;
            }
            //render shadowMap for light i
            Matrix4x4       viewMatrix, projectionMatrix;
            ShadowSplitData splitData;
            if (!cull.ComputeSpotShadowMatricesAndCullingPrimitives(
                    i, out viewMatrix, out projectionMatrix, out splitData
                    ))
            {
                shadowData[i].x = 0f;
                continue;
            }
            ;

            float tileOffsetX = tileIndex % split;
            float tileOffsetY = tileIndex / split;
            tileViewport.x = tileOffsetX * tileSize;
            tileViewport.y = tileOffsetY * tileSize;

            if (split > 1)
            {
                //camera viewport does not affect light VP matrix
                shadowBuffer.SetViewport(tileViewport);

                //scissor edges for soft shadow filter does not get cross multiple shadowmaps
                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
                ); // shadow bias

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

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

            //prepare worldToShadowMatrices for shadow receiver
            if (SystemInfo.usesReversedZBuffer)  //if use z=-1 for near clip plane
            {
                projectionMatrix.m20 = -projectionMatrix.m20;
                projectionMatrix.m21 = -projectionMatrix.m21;
                projectionMatrix.m22 = -projectionMatrix.m22;
                projectionMatrix.m23 = -projectionMatrix.m23;
            }
            //[-1,1] in clip space to [0,1] in texture space
            // var scaleOffset = Matrix4x4.TRS(Vector3.one * 0.5f, Quaternion.identity, Vector3.one * 0.5f);
            var scaleOffset = Matrix4x4.identity;
            scaleOffset.m00 = scaleOffset.m11 = scaleOffset.m22 = 0.5f;
            scaleOffset.m03 = scaleOffset.m13 = scaleOffset.m23 = 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];
            }

            tileIndex += 1;

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

        if (split > 1)
        {
            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();
    }
Ejemplo n.º 11
0
        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);
        }
Ejemplo n.º 12
0
    //------------------------------------------------------------------------------
    private void RenderShadows(ScriptableRenderContext context)
    {
        shadowMap = RenderTexture.GetTemporary(
            512, 512, 16, RenderTextureFormat.Shadowmap
            );
        shadowMap.filterMode = FilterMode.Bilinear;
        shadowMap.wrapMode   = TextureWrapMode.Clamp;

        CoreUtils.SetRenderTarget(
            shadowBuffer, shadowMap,
            RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store,
            ClearFlag.Depth
            );
        shadowBuffer.BeginSample("Shadow Map");
        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();

        // configure view & proj matrices from POV of light that's casting shadows
        Matrix4x4       viewMatrix, projectionMatrix;
        ShadowSplitData splitData;

        cullResults.ComputeSpotShadowMatricesAndCullingPrimitives(
            shadowCastingLightIndex,
            out viewMatrix, out projectionMatrix, out splitData
            );

        shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();

        // draw all shadow-casting objects
        var shadowSettings = new DrawShadowsSettings(
            cullResults,
            shadowCastingLightIndex
            );

        context.DrawShadows(ref shadowSettings);

        // setup shadow projection matrix
        // account for z-direction setting
        if (SystemInfo.usesReversedZBuffer)
        {
            projectionMatrix.m20 = -projectionMatrix.m20;
            projectionMatrix.m21 = -projectionMatrix.m21;
            projectionMatrix.m22 = -projectionMatrix.m22;
            projectionMatrix.m23 = -projectionMatrix.m23;
        }
        // clip space is (-1, 1), but depth coordinates are (0, 1)
        // so bake the conversion into our matrix
        var scaleOffset = Matrix4x4.identity;

        scaleOffset.m00 = scaleOffset.m11 = scaleOffset.m22 = 0.5f;
        scaleOffset.m03 = scaleOffset.m13 = scaleOffset.m23 = 0.5f;

        // make shadow map available as global shader property
        Matrix4x4 worldtoShadowMatrix = scaleOffset * (projectionMatrix * viewMatrix);

        shadowBuffer.SetGlobalMatrix(worldToShadowMatrixId, worldtoShadowMatrix);
        shadowBuffer.SetGlobalTexture(shadowMapID, shadowMap);

        shadowBuffer.EndSample("Shadow Map");
        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();
    }