Exemple #1
0
        void RenderDirectionalShadows(int index, int split, int tileSize)
        {
            ShadowedDirectionalLight light = shadowedDirectionalLights[index];
            var shadowSettings             = new ShadowDrawingSettings(cullingResults, light.visibleLightIndex);

            var     cascadeCount = settings.directional.cascadeCount;
            int     tileOffset   = index * cascadeCount;
            Vector3 ratios       = settings.directional.CascadeRatios;

            float cullingFactor = Mathf.Max(0, 0.8f - settings.directional.cascadeFade);

            for (int i = 0; i < cascadeCount; i++)
            {
                cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(light.visibleLightIndex, i, cascadeCount,
                                                                                    ratios, tileSize, light.nearPlaneOffset,
                                                                                    out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix,
                                                                                    out ShadowSplitData splitData);
                splitData.shadowCascadeBlendCullingFactor = cullingFactor;
                shadowSettings.splitData = splitData;
                if (index == 0)
                {
                    SetCascadeData(i, splitData.cullingSphere, tileSize);
                }
                int tileOffIndex = tileOffset + i;
                dirShadowMatrices[tileOffIndex] = ConvertToAtlasMatrix(projectionMatrix * viewMatrix, SetTileViewport(tileOffIndex, split, tileSize), split);
                buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
                buffer.SetGlobalDepthBias(0f, light.slopeScaleBias);
                ExecuteBuffer();
                context.DrawShadows(ref shadowSettings);
                buffer.SetGlobalDepthBias(0f, 0f);
            }
        }
        public static void ExtractDirectionalLightData(VisibleLight visibleLight, Vector2 viewportSize, uint cascadeIndex, int cascadeCount, float[] cascadeRatios, float nearPlaneOffset, CullingResults cullResults, int lightIndex, out Matrix4x4 view, out Matrix4x4 invViewProjection, out Matrix4x4 projection, out Matrix4x4 deviceProjection, out ShadowSplitData splitData)
        {
            Vector4 lightDir;

            Debug.Assert((uint)viewportSize.x == (uint)viewportSize.y, "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;

            // This used to be fixed to .6f, but is now configureable.
            splitData.shadowCascadeBlendCullingFactor = .6f;

            // get lightDir
            lightDir = visibleLight.GetForward();
            // 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 = cascadeRatios.Length < 3 ? cascadeRatios.Length : 3; i < cnt; i++)
            {
                ratios[i] = cascadeRatios[i];
            }
            cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, (int)cascadeIndex, cascadeCount, ratios, (int)viewportSize.x, nearPlaneOffset, out view, out projection, out splitData);
            // and the compound (deviceProjection will potentially inverse-Z)
            deviceProjection = GL.GetGPUProjectionMatrix(projection, false);
            projection       = GL.GetGPUProjectionMatrix(projection, true);
            InvertOrthographic(ref deviceProjection, ref view, out invViewProjection);
        }
Exemple #3
0
    void RenderDirectionalShadows(int index, int split, int tileSize)
    {
        ShadowedDirectionalLight light = ShadowedDirectionalLights[index];
        var shadowSettings             =
            new ShadowDrawingSettings(cullingResults, light.visibleLightIndex);
        int cascadeCount = settings.directional.cascadeCount;
        int tileOffset   = index * cascadeCount;

        for (int i = 0; i < cascadeCount; i++)
        {
            cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(
                light.visibleLightIndex, i, cascadeCount, cascadeRatio,
                tileSize, 0f, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix, out ShadowSplitData shadowSplitData
                );
            shadowSettings.splitData = shadowSplitData;

            int tileIndex = tileOffset + i;
            dirShadowMatrices[tileIndex] = ConvertToAtlasMatrix(
                projMatrix * viewMatrix,
                SetTileViewport(tileIndex, split, tileSize), split
                );
            buffer.SetViewProjectionMatrices(viewMatrix, projMatrix);
            ExecuteBuffer();
            context.DrawShadows(ref shadowSettings);
        }
    }
Exemple #4
0
	private void RenderDirectionalShadow(CullingResults cull, int sunlightIndex, Light sunlight) {
		ResetRenderTarget(SunlightShadowmapId, true, false, 1, Color.black);
		
		var shadowSettings = new ShadowDrawingSettings(cull, sunlightIndex);
		if (!cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(sunlightIndex, 0, 1, new Vector3(1, 0, 0), @params.sunlightParams.shadowResolution, sunlight.shadowNearPlane, out var viewMatrix, out var projectionMatrix, out var splitData)) {
			ExecuteCurrentBuffer();
			return;
		}
		
		shadowSettings.splitData = splitData;
		
		_currentBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
		
		if (_reversedZBuffer) {
			projectionMatrix.m20 = -projectionMatrix.m20;
			projectionMatrix.m21 = -projectionMatrix.m21;
			projectionMatrix.m22 = -projectionMatrix.m22;
			projectionMatrix.m23 = -projectionMatrix.m23;
		}
		
		var scaleOffset = Matrix4x4.identity;
		scaleOffset.m00 = scaleOffset.m11 = scaleOffset.m22 = scaleOffset.m03 = scaleOffset.m13 = scaleOffset.m23 = 0.5f;
		
		var sunlightInverseVP = scaleOffset * (projectionMatrix * viewMatrix);
		
		_currentBuffer.SetGlobalMatrix(ShaderManager.SUNLIGHT_INVERSE_VP, sunlightInverseVP);
		
		ExecuteCurrentBuffer();
		
		_context.DrawShadows(ref shadowSettings);
	}
Exemple #5
0
        /// <summary>
        /// Extracts the directional light matrix.
        /// </summary>
        /// <param name="cullResults"></param>
        /// <param name="shadowData"></param>
        /// <param name="shadowLightIndex"></param>
        /// <param name="cascadeIndex"></param>
        /// <param name="shadowmapWidth"></param>
        /// <param name="shadowmapHeight"></param>
        /// <param name="shadowResolution"></param>
        /// <param name="shadowNearPlane"></param>
        /// <param name="cascadeSplitDistance"></param>
        /// <param name="shadowSliceData"></param>
        /// <returns></returns>
        public static bool ExtractDirectionalLightMatrix(ref CullingResults cullResults, ref ShadowData shadowData, int shadowLightIndex, int cascadeIndex, int shadowmapWidth, int shadowmapHeight, int shadowResolution, float shadowNearPlane, out Vector4 cascadeSplitDistance, out ShadowSliceData shadowSliceData)
        {
            bool success = cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(shadowLightIndex,
                                                                                            cascadeIndex, shadowData.mainLightShadowCascadesCount, shadowData.mainLightShadowCascadesSplit, shadowResolution, shadowNearPlane, out shadowSliceData.viewMatrix, out shadowSliceData.projectionMatrix,
                                                                                            out shadowSliceData.splitData);

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

            // It is the culling sphere radius multiplier for shadow cascade blending
            // If this is less than 1.0, then it will begin to cull castors across cascades
            shadowSliceData.splitData.shadowCascadeBlendCullingFactor = 1.0f;

            // 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, shadowmapWidth, shadowmapHeight);
            }

            return(success);
        }
        public static bool ExtractDirectionalLightMatrix(ref CullingResults cullResults, ref ShadowData shadowData, int shadowLightIndex, int cascadeIndex, int shadowmapWidth, int shadowmapHeight, int shadowResolution, float shadowNearPlane, out Vector4 cascadeSplitDistance, out ShadowSliceData shadowSliceData, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix, Bounds bounds)
        {
            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;

            Bounds    lightViewBounts  = TransformBounds(viewMatrix, bounds);
            Matrix4x4 tight_projMatrix = ProjMatFromBounds(lightViewBounts, projMatrix);//tight aabb

            tight_projMatrix.SetRow(2, projMatrix.GetRow(2));
            shadowSliceData.projectionMatrix = tight_projMatrix;
            shadowSliceData.shadowTransform  = GetShadowTransform(tight_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, shadowmapWidth, shadowmapHeight);
            }

            return(success);
        }
Exemple #7
0
    void RenderDirectionalShadows(int index, int split, int tileSize)
    {
        var light          = ShadowedDirectionalLights[index];
        var shadowSettings = new ShadowDrawingSettings(cullingResults, index);

        cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(
            light.VisibleLightIndex,
            0,
            1,
            Vector3.zero,
            tileSize,
            0f,
            out Matrix4x4 viewMatrix,
            out Matrix4x4 projMatrix,
            out ShadowSplitData shadowSplitData);

        shadowSettings.splitData = shadowSplitData;

        // SetTileViewport(index, split, tileSize);
        DirShadowMatrices[index] = ConvertToAtlasMatrix(
            projMatrix * viewMatrix,
            SetTileViewport(index, split, tileSize),
            split);

        buffer.SetGlobalMatrixArray(DirShadowMatricesID, DirShadowMatrices);
        buffer.SetViewProjectionMatrices(viewMatrix, projMatrix);
        ExecuteBuffer();
        context.DrawShadows(ref shadowSettings);
    }
Exemple #8
0
    void RenderDirectionalShadows(int index, int split, int tileSize)
    {
        ShadowedDirectionalLight light = ShadowedDirectionalLights[index];

        //create a shadowdrawsetting based on the light index
        var shadowDSettings = new ShadowDrawingSettings(cullingResults, light.visibleLightIndex)
        {
            useRenderingLayerMaskTest = true
        };                                  //make shadow effcted by rendering layer mask

        //take into count that each light will render max 4 cascades
        int     cascadeCount = shadowSettings.directional.cascadeCount;
        int     tileOffset   = index * cascadeCount;
        Vector3 ratios       = shadowSettings.directional.CascadeRatios;
        //cal the cascade culling factor, make it 0.8-fade to make sure casters in transition not being culled
        float cullingfactor = Mathf.Max(0f, 0.8f - shadowSettings.directional.cascadeFade);

        float tileScale = 1f / split;

        //get the lightviewMatrix, lightprojectionMatrix, clip space box for the dirctional lights
        for (int i = 0; i < cascadeCount; i++)
        {
            cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(
                light.visibleLightIndex, i, cascadeCount, ratios, tileSize, light.nearPlaneOffset,
                out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix,
                out ShadowSplitData splitData);
            //make UNITY to cull some shadow caster in large cascade if the smaller cascade is enough
            splitData.shadowCascadeBlendCullingFactor = cullingfactor;
            shadowDSettings.splitData = splitData;
            //assign the cascade culling sphere, all lights uses the same culling spheres and same cascade datas
            if (index == 0)
            {
                SetCascadeData(i, splitData.cullingSphere, tileSize);
            }
            int tileIdex = tileOffset + i;

            //set the render view port and get the offset for modify the dir shadow matrix
            //set the matrix from wolrd space to shadow Atlas space
            dirShadowMatrices[tileIdex] = ConvertToAtlasMatrix(
                projectionMatrix * viewMatrix,
                SetTileViewport(tileIdex, split, tileSize),
                tileScale
                );
            //set the ViewProjectionMatrices for the buffer
            buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);

            //experimental depth bias
            //buffer.SetGlobalDepthBias(50000f, 0f);
            //using slop bias
            buffer.SetGlobalDepthBias(0f, light.slopScaleBias);
            ExecuteBuffer();

            //draw shadow caster on the buffer
            context.DrawShadows(ref shadowDSettings);
            //Debug.Log(shadowDSettings
            buffer.SetGlobalDepthBias(0f, 0f);
        }
    }
Exemple #9
0
	private void RenderCascadedDirectionalShadow(CullingResults cull, int sunlightIndex, Light sunlight, float shadowDistance) {
		_currentBuffer.GetTemporaryRTArray(ShaderManager.SUNLIGHT_SHADOWMAP_ARRAY, @params.sunlightParams.shadowResolution, @params.sunlightParams.shadowResolution, @params.sunlightParams.shadowCascades, 16, FilterMode.Bilinear, RenderTextureFormat.Shadowmap);
		
		var shadowCascades = @params.sunlightParams.shadowCascades;
		
		var shadowSettings = new ShadowDrawingSettings(cull, sunlightIndex);
		var sunlightInverseVPArray = new Matrix4x4[shadowCascades];
		var sunlightShadowSplitBoundArray = new Vector4[shadowCascades];
		var scaleOffset = Matrix4x4.identity;
		scaleOffset.m00 = scaleOffset.m11 = scaleOffset.m22 =scaleOffset.m03 = scaleOffset.m13 = scaleOffset.m23 = 0.5f;
		
		_currentBuffer.SetGlobalFloat(ShaderManager.SHADOW_BIAS, sunlight.shadowBias);
		_currentBuffer.SetGlobalFloat(ShaderManager.SHADOW_NORMAL_BIAS, sunlight.shadowNormalBias);

		for (var i = 0; i < shadowCascades; i++) {
			ResetRenderTarget(SunlightShadowmapArrayId, CubemapFace.Unknown, i, true, false, 1, Color.black);

			if (!cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(sunlightIndex, i, shadowCascades, @params.sunlightParams.shadowCascadeSplits, @params.sunlightParams.shadowResolution, sunlight.shadowNearPlane, out var viewMatrix, out var projectionMatrix, out var splitData)) {
				ExecuteCurrentBuffer();
				continue;
			}
			
			shadowSettings.splitData = splitData;
			
			_currentBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
		
			if (_reversedZBuffer) {
				projectionMatrix.m20 = -projectionMatrix.m20;
				projectionMatrix.m21 = -projectionMatrix.m21;
				projectionMatrix.m22 = -projectionMatrix.m22;
				projectionMatrix.m23 = -projectionMatrix.m23;
			}
		
			sunlightInverseVPArray[i] = scaleOffset * (projectionMatrix * viewMatrix);
			sunlightShadowSplitBoundArray[i] = splitData.cullingSphere;
			sunlightShadowSplitBoundArray[i].w *= splitData.cullingSphere.w;
			
			ExecuteCurrentBuffer();
			
			_context.DrawShadows(ref shadowSettings);
		}

		var inverseShadowmapSize = 1f / @params.sunlightParams.shadowResolution;
		
		_currentBuffer.SetGlobalFloat(ShaderManager.SUNLIGHT_SHADOW_STRENGTH, sunlight.shadowStrength);
		_currentBuffer.SetGlobalFloat(ShaderManager.SUNLIGHT_SHADOW_DISTANCE, shadowDistance);
		_currentBuffer.SetGlobalVector(ShaderManager.SUNLIGHT_SHADOWMAP_SIZE, new Vector4(inverseShadowmapSize, inverseShadowmapSize, @params.sunlightParams.shadowResolution, @params.sunlightParams.shadowResolution));
		_currentBuffer.SetGlobalMatrixArray(ShaderManager.SUNLIGHT_INVERSE_VP_ARRAY, sunlightInverseVPArray);
		_currentBuffer.SetGlobalVectorArray(ShaderManager.SUNLIGHT_SHADOW_SPLIT_BOUND_ARRAY, sunlightShadowSplitBoundArray);
		
		if (sunlight.shadows == LightShadows.Soft) _currentBuffer.EnableShaderKeyword(ShaderManager.SUNLIGHT_SOFT_SHADOWS);
		else _currentBuffer.DisableShaderKeyword(ShaderManager.SUNLIGHT_SOFT_SHADOWS);
		
		ExecuteCurrentBuffer();
	}
Exemple #10
0
        private void RenderDirectionalShadows(int index, int tileSize)
        {
            ShadowDirectionalLight light = _shadowDirectionalLights[index];
            var shadowDrawSettings       = new ShadowDrawingSettings(_cullingResults, light.visibleLightIndex);

            _cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(light.visibleLightIndex, 0, 1,
                                                                                 Vector3.zero, tileSize, 0f, out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix,
                                                                                 out ShadowSplitData splitData);
            shadowDrawSettings.splitData = splitData;
            _buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
            ExecuteBuffer();
            _context.DrawShadows(ref shadowDrawSettings);
        }
Exemple #11
0
    void RenderDirectionalShadows(int index, int split, int tileSize)
    {
        ShadowDirectionalLight light = ShadowDirectionalLights[index];
        var shadowSettings           = new ShadowDrawingSettings(cullingResults, light.visibleLightIndex)
        {
            useRenderingLayerMaskTest = true
        };
        int     cascadeCount = settings.directional.cascadeCount;
        int     tileOffset   = index * cascadeCount;
        Vector3 ratios       = settings.directional.CascadeRatios;
        //裁剪参数
        float cullingFactor = Mathf.Max(0f, 0.8f - settings.directional.cascadeFade);
        float tileScale     = 1f / split;

        //遍历Cascade的数量
        for (int i = 0; i < cascadeCount; i++)
        {
            //Debug.Log(light.nearPlaneOffset);
            //Unity
            cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(
                light.visibleLightIndex, i, cascadeCount, ratios, tileSize, light.nearPlaneOffset, out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix,
                out ShadowSplitData splitData);
            //???????????
            splitData.shadowCascadeBlendCullingFactor = cullingFactor;
            shadowSettings.splitData = splitData;
            if (index == 0)
            {
                //裁剪球 判断片段在哪一级的Cascade里面 w为半径
                Vector4 cullingSphere = splitData.cullingSphere;
                SetCascadeData(i, splitData.cullingSphere, tileSize);
            }

            int tileIndex = tileOffset + i;
            //设置ViewPort大小
            //SetTileViewport(index, split, tileSize);
            //从世界空间到灯光阴影投影空间
            dirShadowMatrices[tileIndex] = ConvertToAtlasMatrix(projectionMatrix * viewMatrix, SetTileViewport(tileIndex, split, tileSize), tileScale);
            buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);

            //球覆盖
            buffer.SetGlobalVectorArray(cascadeCullingSpheresId, cascadeCullingSpheres);
            //Cascade数据
            buffer.SetGlobalVectorArray(cascadeDataId, cascadeData);
            //转换物体到灯光空间
            buffer.SetGlobalMatrixArray(dirShadowMatricesId, dirShadowMatrices);
            buffer.SetGlobalDepthBias(0f, light.slopeScaleBias);
            ExecuteBuffer();
            context.DrawShadows(ref shadowSettings);
            buffer.SetGlobalDepthBias(0f, 0f);
        }
    }
    public void RenderDirectionalShadows(int index, int splitCount, int size)
    {
        ShadowedDirectionalLight light = ShadowedDirectionalLights[index];
        var shadowSetting = new ShadowDrawingSettings(_results, light.visibleLightIndex);

        //https://docs.unity3d.com/2019.1/Documentation/ScriptReference/Rendering.CullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives.html
        //利用光源的方向(-transform.forward)方向可以求出view matrix,nearclip 和 最远的阴影距离等可以求出project matrix等等
        _results.ComputeDirectionalShadowMatricesAndCullingPrimitives(light.visibleLightIndex, 0, 1, Vector3.zero,
                                                                      size, 0, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix,
                                                                      out ShadowSplitData shadowSplitData);
        shadowSetting.splitData = shadowSplitData;
        SetTileViewport(index, splitCount, size);
        _commandBuffer.SetViewProjectionMatrices(viewMatrix, projMatrix);
        ExecuteCommandBuffer();
        _context.DrawShadows(ref shadowSetting);
    }
    private bool RenderShadowMaps(ref ScriptableRenderContext context, ref CullingResults cullingResults, ref Matrix4x4 worldToShadowMatrix)
    {
        if (cullingResults.visibleLights.Length == 0)
        {
            return(false);
        }

        int lightIndex = 0; // Just use first light (index 0) for shadows and assume it's a directional light

        bool needToRender = cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, 0, 1, Vector3.forward, 1024, cullingResults.visibleLights[0].light.shadowNearPlane, out Matrix4x4 viewMatrix, out Matrix4x4 projMatrix, out ShadowSplitData shadowSplitData);

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

        CommandBuffer cb = new CommandBuffer();

        cb.name = "Set up shadow data";
        cb.SetRenderTarget(m_ShadowMap);
        cb.ClearRenderTarget(true, true, Color.clear);
        cb.SetViewProjectionMatrices(viewMatrix, projMatrix);
        context.ExecuteCommandBuffer(cb);

        ShadowDrawingSettings shadowDrawSettings = new ShadowDrawingSettings(cullingResults, lightIndex);

        shadowDrawSettings.splitData = shadowSplitData;

        context.DrawShadows(ref shadowDrawSettings);

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

        var scaleOffset = Matrix4x4.TRS(
            Vector3.one * 0.5f, Quaternion.identity, Vector3.one * 0.5f
            );

        worldToShadowMatrix =
            scaleOffset * (projMatrix * viewMatrix);

        return(true);
    }
Exemple #14
0
    void RenderOneDirectionalShadow(int lightIdx, int tileSplitFactor)
    {
        ShadowedLight shadowedLight      = _shadowedDirLights[lightIdx];
        int           cascadeSplitFactor = _shadowSetting.directional.cascadeCount > 1 ? 2 : 1;
        int           tileSize           = (int)_shadowSetting.directional.atlasSize / tileSplitFactor;
        int           cascadeSize        = (int)_shadowSetting.directional.atlasSize / (tileSplitFactor * cascadeSplitFactor);
        int           visibleIndex       = shadowedLight.visibleIndex;

        _shadowMapSizes.x = cascadeSize;

        _cmdBuffer.SetGlobalDepthBias(0, shadowedLight.light.shadowBias);
        for (int cascadeIdx = 0; cascadeIdx < _shadowSetting.directional.cascadeCount; cascadeIdx++)
        {
            _cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(visibleIndex,
                                                                              cascadeIdx,
                                                                              _shadowSetting.directional.cascadeCount,
                                                                              _shadowSetting.directional.cascadeSplitRatio,
                                                                              cascadeSize,
                                                                              shadowedLight.light.shadowNearPlane,
                                                                              out Matrix4x4 viewMatrix,
                                                                              out Matrix4x4 projMatrix,
                                                                              out ShadowSplitData shadowSplitData);
            _cmdBuffer.SetViewProjectionMatrices(viewMatrix, projMatrix);

            Vector2 tileOffset     = new Vector2(lightIdx % 2, lightIdx / 2);
            Vector2 cascadeOffset  = new Vector2(cascadeIdx % 2, cascadeIdx / 2);
            Rect    viewPortOffset = new Rect(tileOffset.x * tileSize + cascadeOffset.x * cascadeSize, tileOffset.y * tileSize + cascadeOffset.y * cascadeSize, cascadeSize, cascadeSize);
            _cmdBuffer.SetViewport(viewPortOffset);
            ExecuteCommandBuffer();

            _dirShadowMatrixs[lightIdx * MAX_NUM_DIRECTIONAL_CASCADES + cascadeIdx] = ShadowMatrixToAtlasTileMatrix(projMatrix * viewMatrix, viewPortOffset, (int)_shadowSetting.directional.atlasSize);
            if (lightIdx == 0)   // all directional light share the same cascade culling spheres
            {
                _dirCascadeCullingSpheres[cascadeIdx] = shadowSplitData.cullingSphere;
            }

            ShadowDrawingSettings shadowDrawSetting = new ShadowDrawingSettings(_cullResults, visibleIndex)
            {
                splitData = shadowSplitData
            };
            _srContext.DrawShadows(ref shadowDrawSetting);
        }
        _cmdBuffer.SetGlobalDepthBias(0, 0);
    }
Exemple #15
0
    void RenderDirectionalShadows(int index, int split, int tileSize)
    {
        ShadowedDirectionalLight light = ShadowedDirectionalLights[index];
        var     shadowSettings         = new ShadowDrawingSettings(_cullingResults, light.visibleLightIndex);
        int     cascadeCount           = _settings.directional.cascadeCount;
        int     tileOffset             = index * cascadeCount;
        Vector3 ratios        = _settings.directional.CascadeRatios;
        float   cullingFactor = Mathf.Max(0f, 0.8f - _settings.directional.cascadeFade);

        for (int i = 0; i < cascadeCount; i++)
        {
            // 阴影贴图的原理是,从灯光的角度渲染场景,只存储深度信息,用结果标记出来,光线在击中某物体之前会传播多远
            // 但是定向光没有真实位置,我们要做的是找出与灯光方向匹配的视图/投影矩阵,并为我们提供一个裁剪空间立方体
            // 该立方体与包含可见光阴影的摄像机可见区域重合
            _cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(
                light.visibleLightIndex, i, cascadeCount, ratios, tileSize,
                light.nearPlaneOffset, out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix,
                out ShadowSplitData splitData);
            // 避免对每个光源渲染相同的阴影投射器不止一次,如果可以保证从较小的级联中覆盖某些阴影投射器,就可以尝试从较大的级联中剔除掉
            // 某些阴影投射器
            splitData.shadowCascadeBlendCullingFactor = cullingFactor;
            shadowSettings.splitData = splitData;
            if (index == 0)
            {
                SetCascadeData(i, splitData.cullingSphere, tileSize);
                // Vector4 cullingSphere = splitData.cullingSphere;
            }
            int tileIndex = tileOffset + i;
            // SetTileViewport(index, split, tileSize);
            // dirShadowMatrices[index] = projectionMatrix * viewMatrix;
            dirShadowMatrices[tileIndex] =
                ConvertToAtlasMatrix(projectionMatrix * viewMatrix, SetTileViewport(tileIndex, split, tileSize), split);
            buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
            // buffer.SetGlobalDepthBias(500000f, 0f);
            // buffer.SetGlobalDepthBias(0f, 3f);
            buffer.SetGlobalDepthBias(0f, light.slopeScaleBias);
            ExecuteBuffer();
            _context.DrawShadows(ref shadowSettings);
            buffer.SetGlobalDepthBias(0f, 0f);
        }
    }
        void RenderDirectionalShadows(int index, int split, int tileSize)
        {
            ShadowedDirectionalLight light = _shadowedDirectionalLights[index];
            var     shadowSettings         = new ShadowDrawingSettings(_cullingResults, light.visibleLightIndex);
            int     splitCount             = _settings.directional.cascadeCount;
            Vector3 splitRatios            = _settings.directional.CascadeRatios;
            float   cullingFactor          = Mathf.Max(0f, 0.8f - _settings.directional.cascadeFade);

            for (int i = 0; i < splitCount; i++)
            {
                _cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(
                    light.visibleLightIndex,
                    splitIndex: i,
                    splitCount,
                    splitRatios,
                    shadowResolution: tileSize,
                    light.nearPlaneOffset,
                    out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix,
                    out ShadowSplitData splitData
                    );

                splitData.shadowCascadeBlendCullingFactor = cullingFactor;
                _settings.SplitData = splitData;
                if (index == 0)
                {
                    SetCascadeData(i, splitData.cullingSphere, tileSize);
                }

                int tileIndex  = index * splitCount + i;
                var tileOffset = GetTileViewportOffset(tileIndex, split);
                SetTileViewport(tileOffset, tileSize);
                _dirShadowMatrices[tileIndex] = ConvertToAtlasMatrix(worldToLight: projectionMatrix * viewMatrix,
                                                                     tileOffset, split);
                _buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);

                _buffer.SetGlobalDepthBias(0f, light.slopeScaleBias);
                ExecuteBuffer();
                _context.DrawShadows(ref shadowSettings);
                _buffer.SetGlobalDepthBias(0f, 0f);
            }
        }
Exemple #17
0
    private void RenderDirectionalShadows(int index, int split, int tileSize)
    {
        ShadowedDirectionalLight light          = shadowedDirectionalLights[index];
        ShadowDrawingSettings    shadowSettings = new ShadowDrawingSettings(cullingResults, light.visibleLightIndex)
        {
            useRenderingLayerMaskTest = true
        };

        int     cascadeCount = this.shadowSettings.directional.cascadeCount;
        int     tileOffset   = index * cascadeCount;
        Vector3 ratios       = this.shadowSettings.directional.CascadeRatios;

        float cullingFactor = Mathf.Max(0f, 0.8f - this.shadowSettings.directional.cascadeFade);
        float tileScale     = 1f / split;

        for (int i = 0; i < cascadeCount; ++i)
        {
            cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(
                light.visibleLightIndex, i, cascadeCount, ratios, tileSize, light.nearPlaneOffset, out Matrix4x4 viewMatrix,
                out Matrix4x4 projectionMatrix, out ShadowSplitData splitData);
            splitData.shadowCascadeBlendCullingFactor = cullingFactor;
            shadowSettings.splitData = splitData;
            int tileIndex = tileOffset + i;
            if (index == 0)
            {
                //Vector4 cullingSphere = splitData.cullingSphere;
                //cullingSphere.w *= cullingSphere.w;
                //cascadeCullingSpheres[i] = cullingSphere;

                SetCascadeData(i, splitData.cullingSphere, tileSize);
            }
            //SetTileViewport(index, split, tileSize);
            //dirShadowMatrices[index] = projectionMatrix * viewMatrix;
            dirShadowMatrices[tileIndex] = ConvertToAtlasMatrix(projectionMatrix * viewMatrix, SetTileViewport(tileIndex, split, tileSize), tileScale);
            buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
            buffer.SetGlobalDepthBias(0f, light.slopeScaleBias);
            ExecuteBuffer();
            context.DrawShadows(ref shadowSettings);
            buffer.SetGlobalDepthBias(0f, 0f);
        }
    }
Exemple #18
0
    void RenderDirectionalShadows(int index, int tileSize)
    {
        ShadowedDirectionalLight light = ShadowedDirectionalLights[index];
        ///ShadowDrawingSettings built-in
        var shadowSettings =
            new ShadowDrawingSettings(cullingResults, light.visibleLightIndex);

        ///The idea of a shadow map is that we render the scene from the light's point of view,
        ///only storing the depth information.
        ///The result tells us how far the light travels before it hits something.
        cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(
            light.visibleLightIndex, 0, 1, Vector3.zero, tileSize, 0f,
            out Matrix4x4 viewMatrix, out Matrix4x4 projectionMatrix,
            out ShadowSplitData splitData
            );
        ///The split data contains information about how shadow-casting objects should be culled
        shadowSettings.splitData = splitData;
        buffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
        ExecuteBuffer();
        context.DrawShadows(ref shadowSettings);
    }
    void SetupDirectionalShadow(ref ScriptableRenderContext context, ref CullingResults cullingResults, int shadowMapSize, int index, ref VisibleLight visibleLight)
    {
        Bounds shadowBounds;

        if (visibleLight.light.shadows != LightShadows.None && cullingResults.GetShadowCasterBounds(index, out shadowBounds))
        {
            ShadowLight shadowLight = new ShadowLight();
            shadowLight.cascades       = new ShadowCascade[4];
            shadowLight.cullingSpheres = new Vector4[4];
            shadowLight.tileSize       = shadowMapSize / 2;

            for (int j = 0; j < 4; j++)
            {
                Matrix4x4       viewMatrix;
                Matrix4x4       projectionMatrix;
                ShadowSplitData splitData;

                if (cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(index, j, 4, fourCascadesSplit, shadowLight.tileSize, visibleLight.light.shadowNearPlane, out viewMatrix, out projectionMatrix, out splitData))
                {
                    Vector2Int tileOffset = new Vector2Int(j % 2, j / 2);
                    Matrix4x4  tileMatrix = Matrix4x4.identity;
                    tileMatrix.m00 = tileMatrix.m11 = 0.5f;
                    tileMatrix.m03 = tileOffset.x * 0.5f;
                    tileMatrix.m13 = tileOffset.y * 0.5f;

                    ShadowCascade shadowCascade = new ShadowCascade();
                    shadowCascade.viewMatrix          = viewMatrix;
                    shadowCascade.projectionMatrix    = projectionMatrix;
                    shadowCascade.worldToShadowMatrix = tileMatrix * CreateWorldToShadowMatrix(viewMatrix, projectionMatrix);
                    shadowCascade.tileOffset          = tileOffset;
                    shadowCascade.splitData           = splitData;
                    shadowLight.cullingSpheres[j]     = splitData.cullingSphere;
                    shadowLight.cullingSpheres[j].w  *= shadowLight.cullingSpheres[j].w;
                    shadowLight.cascades[j]           = shadowCascade;
                }
            }

            shadowData.lights[index] = shadowLight;
        }
    }
Exemple #20
0
    private void SetUpRealtimeShadowVariables(Camera cam, ScriptableRenderContext context, CullingResults cull, Light light, int lightIndex)
    {
        Bounds bounds;
        bool   doShadow = light.shadows != LightShadows.None && cull.GetShadowCasterBounds(lightIndex, out bounds);

        //************************** Shadow Mapping ************************************
        if (doShadow)
        {
            ShadowDrawingSettings shadowSettings = new ShadowDrawingSettings(cull, lightIndex);

            //For shadowmapping, the matrices from the light's point of view
            Matrix4x4       view = Matrix4x4.identity;
            Matrix4x4       proj = Matrix4x4.identity;
            ShadowSplitData splitData;

            bool successShadowMap = false;
            if (light.type == LightType.Directional)
            {
                successShadowMap = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives
                                   (
                    lightIndex,
                    0, 1, new Vector3(1, 0, 0),
                    m_ShadowRes, light.shadowNearPlane, out view, out proj, out splitData
                                   );
                shadowSettings.splitData = splitData;
            }
            else
            {
                return;
            }

            if (successShadowMap)
            {
                CommandBuffer cmdShadow = new CommandBuffer();
                cmdShadow.name = "Shadow Mapping: light" + lightIndex;
                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);

                //Set shadowmap texture
                cmdShadow.DisableScissorRect();
                cmdShadow.SetViewProjectionMatrices(cam.worldToCameraMatrix, cam.projectionMatrix);
                cmdShadow.SetGlobalTexture(m_ShadowMapLightid, m_ShadowMapLight);
                context.ExecuteCommandBuffer(cmdShadow);
                cmdShadow.Clear();
                cmdShadow.Release();

                //Screen Space Shadow =================================================
                CommandBuffer cmdShadow2 = new CommandBuffer();
                cmdShadow2.name = "Screen Space Shadow: light" + lightIndex;

                //Bias
                float sign = (SystemInfo.usesReversedZBuffer) ? 1.0f : -1.0f;
                float bias = light.shadowBias * proj.m22 * sign;
                cmdShadow2.SetGlobalFloat("_ShadowBias", bias);

                //Shadow Transform
                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", light.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();
            }
        }
    }
Exemple #21
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
        shadowMap = SetShadowRenderTarget();

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

        int tileIndex = 0;

        for (int i = mainLightExists?1:0; i < cull.visibleLights.Length; i++)
        {
            if (i == maxVisibleLights)
            {
                break;
            }
            if (shadowData[i].x <= 0f)
            {
                continue;
            }

            VisibleLight visibleLight = cull.visibleLights[i];

            Matrix4x4       viewMatrix, projectionMatrix;
            ShadowSplitData splitData;
            bool            validShadows;
            if (shadowData[i].z > 0f)
            {
                // directional
                validShadows = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(i, 0, 1, Vector3.right, (int)tileSize, visibleLight.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, visibleLight.light.shadowBias);
            context.ExecuteCommandBuffer(shadowBuffer);
            shadowBuffer.Clear();

            // draw shadow for light i
            var shadowSettings = new ShadowDrawingSettings(cull, i);
            shadowSettings.splitData = splitData;
            context.DrawShadows(ref shadowSettings);

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

            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));
        shadowBuffer.EndSample("Render Shadows");
        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();
    }
        private void RenderShadows(ScriptableRenderContext context)
        {
            // 设置阴影贴图图集大小。
            int split = 4;

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

            globalShadowData.x = tileScale;

            shadowMap = SetShadowRenderTarget(); // 设置阴影渲染目标。

            shadowBuffer.BeginSample(shadowBufferName);
            context.ExecuteCommandBuffer(shadowBuffer);
            shadowBuffer.Clear();
            int  tileIndex   = 0;
            bool hardShadows = false;
            bool softShadows = false;

            for (int i = mainLightExists ? 1 : 0; i < cullingResults.visibleLights.Length; i++)
            {
                if (i == maxVisibleLights)
                {
                    break;
                }
                if (shadowData[i].x <= 0f)
                {
                    continue;
                }
                // 聚光灯的视角投影矩阵。我们可以通过 CullingResults 中的 ComputeSpotShadowMatricesAndCullingPrimitives 方法得到。
                // 该方法的第一个参数是光源序列,视野矩阵 和 投影矩阵 则是在后两个输出参数中。
                // 最后一个参数 阴影剔除数据 我们用不到,但作为输出参数,我们必须提供。
                // 方向光的视角投影矩阵。我们可以通过 CullingResults 中的 ComputeDirectionalShadowMatricesAndCullingPrimitives 方法得到。
                // 该方法的第一个参数是光源序列,接着是级联序列,级联数量,级联分级的三维向量,整型的图块尺寸,阴影近平面值,视野矩阵,投影矩阵 和 阴影剔除数据。
                // 阴影剔除数据中包含了一个有效的剔除球体。该球体包裹了所有需要被渲染进直射光阴影贴图的物体。
                // 这对于方向光来说非常重要,因为方向光不像聚光灯,它会影响所有物体,我们需要有一个剔除球体来限制渲染进阴影贴图的图形数量。
                Matrix4x4       viewMatrix, projectionMatrix;
                ShadowSplitData splitData;
                bool            validShadows;
                if (shadowData[i].z > 0f)
                {
                    validShadows = cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(i, 0, 1, Vector3.right, (int)tileSize,
                                                                                                       cullingResults.visibleLights[i].light.shadowNearPlane,
                                                                                                       out viewMatrix, out projectionMatrix, out splitData);
                }
                else
                {
                    validShadows = cullingResults.ComputeSpotShadowMatricesAndCullingPrimitives(i, out viewMatrix, out projectionMatrix, out splitData);
                }
                if (!validShadows)
                {
                    shadowData[i].x = 0f;
                    continue;
                }
                if (shadowData[i].y <= 0f)
                {
                    hardShadows = true;
                }
                else
                {
                    softShadows = true;
                }
                // 设置阴影tiles,计算tiles偏移,设置视口以及剪裁,返回偏移值。
                Vector2 tileOffset = ConfigureShadowTile(tileIndex, split, tileSize);
                shadowData[i].z = tileOffset.x * tileSize;
                shadowData[i].w = tileOffset.y * tileSize;
                // 当我们获得了该矩阵,调用 shadowBuffer 的 SetViewProjectionMatrices 方法,然后执行 CommandBuffer 并清理。
                shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
                // 在渲染深度贴图(ShadowCaster)时,在深度上添加一点偏移,来掩盖阴影的瑕疵(条纹状阴影)。
                shadowBuffer.SetGlobalFloat(shadowBiasId, cullingResults.visibleLights[i].light.shadowBias);
                context.ExecuteCommandBuffer(shadowBuffer);
                shadowBuffer.Clear();

                // 有了正确的矩阵信息,我们现在可以渲染所有投射阴影的物体了。
                // 我们通过调用 DrawShadows 方法来实现。 这个方法需要一个 DrawShadowsSettings 类型的引用参数。
                // 我们用 cullingResults 和 光源序列 作为参数来创建一个该实例。
                var shadowSettings = new ShadowDrawingSettings(cullingResults, i);
                context.DrawShadows(ref shadowSettings);
                // 计算world-to-shadow矩阵。
                CalculateWorldToShadowMatrix(ref viewMatrix, ref projectionMatrix, out worldToShadowMatrices[i]);

                tileIndex += 1;
            }
            shadowBuffer.DisableScissorRect(); // 我们在渲染阴影后调用 DisableScissorRect 关闭裁剪矩形,不然会影响到后面的常规渲染。
            shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap);
            shadowBuffer.SetGlobalVectorArray(shadowDataId, shadowData);
            shadowBuffer.SetGlobalMatrixArray(worldToShadowMatricesId, worldToShadowMatrices);

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

            float invShadowMapSize = 1f / ShadowMapSize;

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

            shadowBuffer.EndSample(shadowBufferName);
            context.ExecuteCommandBuffer(shadowBuffer);
            shadowBuffer.Clear();
        }
Exemple #23
0
    void RenderShadows(ScriptableRenderContext context)
    {
        Debug.Log("Shadow Render");
        int   split;
        float tileSize, tileScale;

        SetupSplitAndTileInfo(shadowMapTileCount, out split, out tileSize, out tileScale);
        shadowBuffer.SetGlobalVector(
            globalShadowDataId, new Vector4(tileScale, shadowDistance * shadowDistance)
            );


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

        shadowMap = SetupRednerTargetForShadow();
        shadowBuffer.BeginSample("Render Shadows");
        context.ExecuteCommandBuffer(shadowBuffer);
        shadowBuffer.Clear();
        int  tileIndex  = 0;
        bool hardShadow = false;
        bool softShadow = false;


        for (int n = mainLightExists ? 1:0; n < cullingResults.visibleLights.Length; n++)
        //for (int n = 0; n < cullingResults.visibleLights.Length; n++)
        {
            if (n == maxVisibleLights)
            {
                break;
            }

            if (shadowData[n].x <= 0f)
            {
                continue;
            }
            Matrix4x4       viewMatrix, projectionMatrix;
            ShadowSplitData splitData;
            bool            vaildShadows;

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


            Vector2 tileOffset = ConfigShadowTile(n, split, tileSize);
            shadowData[n].z = tileOffset.x * tileScale;
            shadowData[n].y = tileOffset.y * tileScale;
            shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
            shadowBuffer.SetGlobalFloat(shadowBiasId, cullingResults.visibleLights[n].light.shadowBias);
            shadowBuffer.SetGlobalVectorArray(shadowDataId, shadowData);


            context.ExecuteCommandBuffer(shadowBuffer);
            shadowBuffer.Clear();
            var shadowSetting = new ShadowDrawingSettings(cullingResults, n);
            context.DrawShadows(ref shadowSetting);
            worldToShadowMatrices[n] = SetupWorldToShadowMatrix(ref projectionMatrix, ref viewMatrix);

            tileIndex += 1;

            if (shadowData[n].y <= 0f)
            {
                hardShadow = true;
            }
            else
            {
                softShadow = true;
            }
        }

        shadowBuffer.DisableScissorRect();

        shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap);
        shadowBuffer.SetGlobalMatrixArray(worldToShadowMatricesId, worldToShadowMatrices);
        float invShadowMapSize = 1f / shadowMapSize;

        shadowBuffer.SetGlobalVector(shadowMapSizeId, new Vector4(invShadowMapSize, invShadowMapSize,
                                                                  shadowMapSize, shadowMapSize));
        CoreUtils.SetKeyword(shadowBuffer, shadowHardKeyWord, hardShadow);
        CoreUtils.SetKeyword(shadowBuffer, shadowSoftKeyWord, softShadow);

        shadowBuffer.EndSample("Render Shadows");
        context.ExecuteCommandBuffer(shadowBuffer);

        shadowBuffer.Clear();
    }
Exemple #24
0
    /// <summary>
    /// 渲染阴影
    /// </summary>
    /// <param name="_context"></param>
    private void renderShadows()
    {
        int split;

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

        Matrix4x4       viewMatrix, projectionMatrix;
        ShadowSplitData splitData;

        float tileSize  = m_rpp.shadowMapSize / split;
        float tileScale = 1.0f / split;

        m_shadowMap = setShadowRenderTarget();
        m_shadowBuffer.BeginSample("Render Shadows");

        m_shadowBuffer.SetGlobalVector(m_globalShadowDataId, new Vector4(tileScale, m_rpp.shadowDistance * m_rpp.shadowDistance));
        executeBuffer(m_shadowBuffer);

        m_shadowBuffer.ClearRenderTarget(true, true, Color.clear, 1);
        executeBuffer(m_shadowBuffer);

        Matrix4x4[] worldToShadowMatrices = new Matrix4x4[m_cullingResults.visibleLights.Length];

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

        //主灯光跳过构建
        for (int i = m_mainLightExits ? 1 : 0; i < m_cullingResults.visibleLights.Length; i++)
        {
            if (i == m_maxVisibleLights)
            {
                break;
            }

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

            bool bScb = m_cullingResults.GetShadowCasterBounds(i, out Bounds outBounds);

            bool bHaveShadow;

            //通过阴影数据判断是方向光还是聚光灯
            if (m_shadowData[i].z > 0.0f)
            {
                bHaveShadow = m_cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(i, 0, 1, Vector3.right, (int)tileSize,
                                                                                                    m_cullingResults.visibleLights[i].light.shadowNearPlane, out viewMatrix, out projectionMatrix, out splitData);
            }
            else
            {
                bHaveShadow = m_cullingResults.ComputeSpotShadowMatricesAndCullingPrimitives(i, out viewMatrix, out projectionMatrix, out splitData);
            }

            if (!(bHaveShadow && bScb))
            {
                m_shadowData[i].x = 0.0f;
                continue;
            }

            Vector2 tileOffset = configureShadowTile(tileIndex, split, tileSize);

            m_shadowData[i].z = tileOffset.x * tileScale;
            m_shadowData[i].w = tileOffset.y * tileScale;

            m_shadowBuffer.SetViewProjectionMatrices(viewMatrix, projectionMatrix);
            m_shadowBuffer.SetGlobalFloat(m_shadowBiasId, m_cullingResults.visibleLights[i].light.shadowBias);
            executeBuffer(m_shadowBuffer);

            //绘制阴影贴图
            var shadowSetting = new ShadowDrawingSettings(m_cullingResults, i);
            shadowSetting.splitData = splitData;
            m_context.DrawShadows(ref shadowSetting);

            //检查Z轴是否反向
            //将深度从-1 - 1 映射到 0 - 1
            calculateWorldToShadowMatrix(ref viewMatrix, ref projectionMatrix, out worldToShadowMatrices[i]);

            tileIndex += 1;

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

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

        m_shadowBuffer.SetGlobalTexture(m_shadowMapId, m_shadowMap);
        m_shadowBuffer.SetGlobalVectorArray(m_shadowDataId, m_shadowData);
        m_shadowBuffer.SetGlobalMatrixArray(m_worldToShadowMatricesId, worldToShadowMatrices);

        float invShadowMapSize = 1.0f / m_rpp.shadowMapSize;

        m_shadowBuffer.SetGlobalVector(m_shadowMapSizeId, new Vector4(invShadowMapSize, invShadowMapSize, m_rpp.shadowMapSize, m_rpp.shadowMapSize));
        CoreUtils.SetKeyword(m_shadowBuffer, m_shadowsHardKeyWord, hardShadows);
        CoreUtils.SetKeyword(m_shadowBuffer, m_shadowsSoftKeyWord, softShadows);

        m_shadowBuffer.EndSample("Render Shadows");
        executeBuffer(m_shadowBuffer);
    }
Exemple #25
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;
            Rect  tileViewport = new Rect(0f, 0f, tileSize, tileSize);

            //设置shadowMap贴图的
            shadowMap = SetShadowRenderTarget();
            shadowBuffer.BeginSample(commandShadowBufferName);
            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 < culling.visibleLights.Length; ++i)
            {
                if (i == maxVisibleLights)
                {
                    break;
                }

                //跳过不需要产生阴影的灯光
                if (shadowData[i].x <= 0f)
                {
                    continue;
                }

                //获取spot等的相关矩阵
                //目前这里有报错
                Matrix4x4       viewMatrix, projectionMatrix;
                ShadowSplitData splitData;

                bool validShadows;

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

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

                //将16个灯光的阴影图渲染到一个rt上,将rt分成16分
                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, culling.visibleLights[i].light.shadowBias);
                context.ExecuteCommandBuffer(shadowBuffer);
                shadowBuffer.Clear();

                //正式draw
                var shadowSettings         = new ShadowDrawingSettings(culling, i);
                var shadowSettingSplitData = shadowSettings.splitData;
                //对于方向光而言,cullingSphere包含了需要渲染进阴影图的所有物体,减少不必要物体的渲染
                shadowSettingSplitData.cullingSphere = splitData.cullingSphere;
                shadowSettings.splitData             = shadowSettingSplitData;

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

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

            shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap);
            shadowBuffer.SetGlobalMatrixArray(worldToShadowMatrixsId, worldToShadowMatrices);
            shadowBuffer.SetGlobalVectorArray(shadowDataId, shadowData);
            float invShadowMapSize = 1f / shadowMapSize;

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

            shadowBuffer.EndSample(commandShadowBufferName);
            context.ExecuteCommandBuffer(shadowBuffer);
            shadowBuffer.Clear();
        }
    void RenderShadows(ScriptableRenderContext context)
    {
        //this will adjust the tiling of the shadowmap dynamically, so as to use the maximum amount of texture possible while still tiling multiple shadows togather
        int split;

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

        //because we support 16 lights, this will tile the shadowmap into 16 portions
        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.SetRenderTarget(shadowMap, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);

        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.Length; i++)
        {
            if (i == maxVisibleLights)            //skip this section if the light doesn't have shadows or we've hit the max number of lights
            {
                break;
            }
            if (shadowData[i].x <= 0f)
            {
                continue;
            }

            Matrix4x4       viewMatrix, projectionMatrix;
            ShadowSplitData splitData;

            bool validShadows;
            //because we are essentially rendering the scene from the light's pov, this sets up the spoof VP matricies for the light's perspective. Also checks to see whether it was able to generate a sensible matrix
            if (shadowData[i].z > 0f)           //if the light is directional
            {
                validShadows = cull.ComputeDirectionalShadowMatricesAndCullingPrimitives(
                    i, 0, 1, Vector3.right, (int)tileSize,
                    cull.visibleLights[i].light.shadowNearPlane,
                    out viewMatrix, out projectionMatrix, out splitData
                    );
            }
            else             //spotlight
            {
                validShadows = cull.ComputeSpotShadowMatricesAndCullingPrimitives(i, out viewMatrix, out projectionMatrix, out splitData);
            }

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


            //this is used for tiling
            float tileOffsetX = tileIndex % split;
            float tileOffsetY = tileIndex / split;
            tileViewport.x  = tileOffsetX * tileSize;
            tileViewport.y  = tileOffsetY * tileSize;
            shadowData[i].z = tileOffsetX * tileScale;
            shadowData[i].w = tileOffsetY * tileScale;

            shadowBuffer.SetViewport(tileViewport);
            //stops the different tiled shadow maps from cross sampling by adding a border around each one
            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);

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


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

            if (SystemInfo.usesReversedZBuffer)            //some gpus flip clipspace z
            {
                projectionMatrix.m20 = -projectionMatrix.m20;
                projectionMatrix.m21 = -projectionMatrix.m21;
                projectionMatrix.m22 = -projectionMatrix.m22;
                projectionMatrix.m23 = -projectionMatrix.m23;
            }

            //clip space goes from -1 to 1, but texture space goes from 0 to 1, this will imbue that transformation into the matrix
            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);


            tileIndex += 1;          //only advance the tileindex when we actually use a tile
            if (shadowData[i].y <= 0)
            {
                hardShadows = true;
            }
            else
            {
                softShadows = true;
            }
        }

        shadowBuffer.DisableScissorRect();

        shadowBuffer.SetGlobalTexture(shadowMapId, shadowMap);
        shadowBuffer.SetGlobalMatrixArray(worldToShadowMatricesId, worldToShadowMatrices);
        shadowBuffer.SetGlobalVectorArray(shadowDataId, shadowData);

        //Used for soft shadows
        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();
    }
Exemple #27
0
    // シャドウマップのセットアップ
    private void SetupShadowMap(ScriptableRenderContext context, Camera camera, CommandBuffer cb)
    {
        // コマンドバッファ利用の準備
        cb.Clear();

        //
        // <comment>
        // ライト情報を取得しています
        // 今回は最初に見つかった平行光源をシャドウライトとして利用します
        //
        int lightIndex = -1;

        for (int h = 0; h < cullResults.visibleLights.Length; ++h)
        {
            // 今回のライトを取得
            VisibleLight currLight = cullResults.visibleLights[h];
            Light        light     = currLight.light;
            if (light == null)
            {
                continue;
            }

            // シャドウを落とす?
            if (light.shadows == LightShadows.None)
            {
                continue;
            }
            if (light.shadowStrength <= 0.0f)
            {
                continue;
            }

            // 今回は平行光源のみ
            if (light.type != LightType.Directional)
            {
                continue;
            }

            // バウンド判定
            Bounds bounds;
            if (!cullResults.GetShadowCasterBounds(h, out bounds))
            {
                continue;
            }

            // 使用ライトの決定
            lightIndex = h;
            break;
        }

        // もしシャドウが無さそうな時はダミーテクスチャを設定して終わり
        if (lightIndex < 0)
        {
            cb.SetGlobalTexture("_ShadowMap", Texture2D.whiteTexture);
            context.ExecuteCommandBuffer(cb);
            return;
        }

        // 各種パラメータの算出と設定
        ShadowSplitData shadowSplitData;

        {
            // パラメータ算出
            Matrix4x4 viewMatrix;
            Matrix4x4 projMatrix;
            cullResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(
                lightIndex,                                                     // int activeLightIndex,
                0,                                                              // int splitIndex,
                1,                                                              // int splitCount,
                new Vector3(1.0f, 0.0f, 0.0f),                                  // Vector3 splitRatio,
                1024,                                                           // int shadowResolution,
                QualitySettings.shadowNearPlaneOffset,                          // float shadowNearPlaneOffset,
                out viewMatrix,                                                 // out Matrix4x4 viewMatrix,
                out projMatrix,                                                 // out Matrix4x4 projMatrix,
                out shadowSplitData                                             // out Experimental.Rendering.ShadowSplitData shadowSplitData
                );

            // マトリクスを作ってグローバル化
            Matrix4x4 matView        = viewMatrix;
            Matrix4x4 matProj        = projMatrix;
            Matrix4x4 matProj_shader = GL.GetGPUProjectionMatrix(matProj, true);
            Matrix4x4 matVP          = matProj_shader * matView;
            cb.SetGlobalMatrix("_ShadowLightView", matView);
            cb.SetGlobalMatrix("_ShadowLightProj", matProj_shader);
            cb.SetGlobalMatrix("_ShadowLightVP", matVP);

            // シャドウマップのグローバル化
            cb.SetGlobalTexture("_ShadowMap", RTI[(int)RenderTextureKind.ShadowMap]);
        }

        // RenderTarget設定(R8フォーマットのシャドウマップ)してクリア処理
        cb.SetRenderTarget(RTI[(int)RenderTextureKind.ShadowMap]);
        cb.ClearRenderTarget(true, true, Color.white, 1.0f);
        context.ExecuteCommandBuffer(cb);

        // 描画
        var settings = new ShadowDrawingSettings(cullResults, lightIndex);

        settings.splitData = shadowSplitData;
        context.DrawShadows(ref settings);
    }
Exemple #28
0
            public void DrawMainDirShadow(int lightIndex)
            {
                var light = cullingResults.visibleLights[lightIndex].light;

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

                if (!cullingResults.GetShadowCasterBounds(lightIndex, out _))
                {
                    Debug.Log("return");
                    return;
                }
                buffer.SetGlobalTexture(ShaderPropIDs.MainShadowAtlas, mainShadowAtlas);
                buffer.SetRenderTarget(mainShadowAtlas, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
                buffer.ClearRenderTarget(true, false, Color.clear);
                context.ExecuteCommandBuffer(buffer);
                buffer.Clear();


                Vector3 splitRatio = new Vector3(settings.mainLightsShadowSetting.SplitRatio1, settings.mainLightsShadowSetting.SplitRatio2, settings.mainLightsShadowSetting.SplitRatio3);

                int split;

                switch (settings.mainLightsShadowSetting.Cascades)
                {
                case CascadeMap.TwoCascades:
                {
                    split = 2;
                    //splitRatio.y = 1.0f;
                    break;
                }

                case CascadeMap.FourCascades:
                {
                    split = 2;
                    break;
                }

                default:
                {
                    split        = 1;
                    splitRatio.x = 1.0f;
                    break;
                }
                }
                int cascadedCount = (int)settings.mainLightsShadowSetting.Cascades;
                int tileSize      = Mathf.FloorToInt((int)settings.mainLightsShadowSetting.Resolution / split);

                for (int i = 0; i < cascadedCount; i++)
                {
                    if (!cullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives(lightIndex, i, 4, splitRatio, (int)settings.mainLightsShadowSetting.Resolution, light.shadowNearPlane, out var viewMatrix, out var projMatrix, out var shadowSplitData))
                    {
                        Debug.Log("CascadeShadowCullingError");
                    }

                    buffer.SetViewProjectionMatrices(viewMatrix, projMatrix);
                    ShadowDrawingSettings shadowDrawingSettings = new ShadowDrawingSettings(cullingResults, lightIndex)
                    {
                        splitData = shadowSplitData
                    };
                    var rect = GetTileViewport(i, split, tileSize, out var offset);
                    buffer.SetViewport(rect);
                    buffer.SetGlobalDepthBias(1f, settings.SlopeBias);
                    context.ExecuteCommandBuffer(buffer);
                    context.DrawShadows(ref shadowDrawingSettings);
                    buffer.Clear();

                    var cullingSphere = shadowSplitData.cullingSphere;
                    cullingSphere.w            = Mathf.Pow(cullingSphere.w, 2);
                    cascadeCullingSphere[i]    = cullingSphere;
                    MainShadowVPMatrixArray[i] = ConvertToAtlasMatrix(projMatrix * viewMatrix, offset, split);
                }
                buffer.SetGlobalInt(ShaderPropIDs.CascadeCount, cascadedCount);
                float f = 1f - settings.mainLightsShadowSetting.CascdeFading;

                buffer.SetGlobalVector(ShaderPropIDs.CascadeDistanceFade, new Vector4(1f / settings.mainLightsShadowSetting.MaxDistance,
                                                                                      1f / settings.mainLightsShadowSetting.CascdeFading,
                                                                                      1f / (1f - f * f)));
                buffer.SetGlobalVectorArray(ShaderPropIDs.CascadeCullingSphereArray, cascadeCullingSphere);
                buffer.SetGlobalMatrixArray(ShaderPropIDs.MainShadowVPMatrixArray, MainShadowVPMatrixArray);
                buffer.SetGlobalFloat(ShaderPropIDs.NormalBias, settings.NormalBias);
                context.ExecuteCommandBuffer(buffer);
                buffer.Clear();
            }