void SetupDirectionalShadowReceiverConstants(ref ScriptableRenderContext context, CommandBuffer cmd, ref ShadowData shadowData, VisibleLight shadowLight)
        {
            Light light = shadowLight.light;

            int cascadeCount = m_ShadowCasterCascadesCount;

            for (int i = 0; i < k_MaxCascades; ++i)
            {
                m_DirectionalShadowMatrices[i] = (cascadeCount >= i) ? m_CascadeSlices[i].shadowTransform : Matrix4x4.identity;
            }

            // We setup and additional a no-op WorldToShadow matrix in the last index
            // because the ComputeCascadeIndex function in Shadows.hlsl can return an index
            // out of bounds. (position not inside any cascade) and we want to avoid branching
            Matrix4x4 noOpShadowMatrix = Matrix4x4.zero;

            noOpShadowMatrix.m33 = (SystemInfo.usesReversedZBuffer) ? 1.0f : 0.0f;
            m_DirectionalShadowMatrices[k_MaxCascades] = noOpShadowMatrix;

            float invShadowAtlasWidth      = 1.0f / shadowData.directionalShadowAtlasWidth;
            float invShadowAtlasHeight     = 1.0f / shadowData.directionalShadowAtlasHeight;
            float invHalfShadowAtlasWidth  = 0.5f * invShadowAtlasWidth;
            float invHalfShadowAtlasHeight = 0.5f * invShadowAtlasHeight;

            cmd.SetGlobalTexture(RenderTargetHandles.DirectionalShadowmap, m_DirectionalShadowmapTexture);
            cmd.SetGlobalMatrixArray(DirectionalShadowConstantBuffer._WorldToShadow, m_DirectionalShadowMatrices);
            cmd.SetGlobalVector(DirectionalShadowConstantBuffer._ShadowData, new Vector4(light.shadowStrength, 0.0f, 0.0f, 0.0f));
            cmd.SetGlobalVectorArray(DirectionalShadowConstantBuffer._DirShadowSplitSpheres, m_CascadeSplitDistances);
            cmd.SetGlobalVector(DirectionalShadowConstantBuffer._DirShadowSplitSphereRadii, new Vector4(m_CascadeSplitDistances[0].w, m_CascadeSplitDistances[1].w, m_CascadeSplitDistances[2].w, m_CascadeSplitDistances[3].w));
            cmd.SetGlobalVector(DirectionalShadowConstantBuffer._ShadowOffset0, new Vector4(-invHalfShadowAtlasWidth, -invHalfShadowAtlasHeight, 0.0f, 0.0f));
            cmd.SetGlobalVector(DirectionalShadowConstantBuffer._ShadowOffset1, new Vector4(invHalfShadowAtlasWidth, -invHalfShadowAtlasHeight, 0.0f, 0.0f));
            cmd.SetGlobalVector(DirectionalShadowConstantBuffer._ShadowOffset2, new Vector4(-invHalfShadowAtlasWidth, invHalfShadowAtlasHeight, 0.0f, 0.0f));
            cmd.SetGlobalVector(DirectionalShadowConstantBuffer._ShadowOffset3, new Vector4(invHalfShadowAtlasWidth, invHalfShadowAtlasHeight, 0.0f, 0.0f));
            cmd.SetGlobalVector(DirectionalShadowConstantBuffer._ShadowmapSize, new Vector4(invShadowAtlasWidth, invShadowAtlasHeight,
                                                                                            shadowData.directionalShadowAtlasWidth, shadowData.directionalShadowAtlasHeight));
        }
        void SetupLocalLightsShadowReceiverConstants(ref ScriptableRenderContext context, CommandBuffer cmd, ref ShadowData shadowData)
        {
            for (int i = 0; i < m_LocalLightSlices.Length; ++i)
            {
                m_LocalShadowMatrices[i] = m_LocalLightSlices[i].shadowTransform;
            }

            float invShadowAtlasWidth      = 1.0f / shadowData.localShadowAtlasWidth;
            float invShadowAtlasHeight     = 1.0f / shadowData.localShadowAtlasHeight;
            float invHalfShadowAtlasWidth  = 0.5f * invShadowAtlasWidth;
            float invHalfShadowAtlasHeight = 0.5f * invShadowAtlasHeight;

            cmd.SetGlobalTexture(RenderTargetHandles.LocalShadowmap, m_LocalShadowmapTexture);
            cmd.SetGlobalMatrixArray(LocalShadowConstantBuffer._LocalWorldToShadowAtlas, m_LocalShadowMatrices);
            cmd.SetGlobalFloatArray(LocalShadowConstantBuffer._LocalShadowStrength, m_LocalShadowStrength);
            cmd.SetGlobalVector(LocalShadowConstantBuffer._LocalShadowOffset0, new Vector4(-invHalfShadowAtlasWidth, -invHalfShadowAtlasHeight, 0.0f, 0.0f));
            cmd.SetGlobalVector(LocalShadowConstantBuffer._LocalShadowOffset1, new Vector4(invHalfShadowAtlasWidth, -invHalfShadowAtlasHeight, 0.0f, 0.0f));
            cmd.SetGlobalVector(LocalShadowConstantBuffer._LocalShadowOffset2, new Vector4(-invHalfShadowAtlasWidth, invHalfShadowAtlasHeight, 0.0f, 0.0f));
            cmd.SetGlobalVector(LocalShadowConstantBuffer._LocalShadowOffset3, new Vector4(invHalfShadowAtlasWidth, invHalfShadowAtlasHeight, 0.0f, 0.0f));
            cmd.SetGlobalVector(LocalShadowConstantBuffer._LocalShadowmapSize, new Vector4(invShadowAtlasWidth, invShadowAtlasHeight,
                                                                                           shadowData.localShadowAtlasWidth, shadowData.localShadowAtlasHeight));
        }
        void RenderLocalShadowmapAtlas(ref ScriptableRenderContext context, ref CullResults cullResults, ref LightData lightData, ref ShadowData shadowData)
        {
            List <int>          localLightIndices = lightData.visibleLocalLightIndices;
            List <VisibleLight> visibleLights     = lightData.visibleLights;

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

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

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

            if (shadowCastingLightsCount == 0)
            {
                return;
            }

            Matrix4x4 view, proj;
            Bounds    bounds;
            int       shadowSampling = 0;

            CommandBuffer cmd = CommandBufferPool.Get(k_RenderLocalShadows);

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

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

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

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

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

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

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

                    if (success)
                    {
                        // This way of computing the shadow slice only work for spots and with most 4 shadow casting lights per pass
                        // Change this when point lights are supported.
                        Debug.Assert(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 = shadowTransform;

                        m_LocalShadowStrength[i] = light.shadowStrength;
                        shadowSampling           = Math.Max(shadowSampling, (int)light.shadows);

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

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

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

            // TODO: We should have RenderingData as a readonly but currently we need this to pass shadow rendering to litpass
            shadowData.renderedLocalShadowQuality = (shadowData.supportsSoftShadows) ? (LightShadows)shadowSampling : LightShadows.Hard;
        }
Beispiel #4
0
        void InitializeShadowData(bool hasDirectionalShadowCastingLight, bool hasLocalShadowCastingLight, out ShadowData shadowData)
        {
            // Until we can have keyword stripping forcing single cascade hard shadows on gles2
            bool supportsScreenSpaceShadows = SystemInfo.graphicsDeviceType != GraphicsDeviceType.OpenGLES2;

            shadowData.renderDirectionalShadows = pipelineAsset.supportsDirectionalShadows && hasDirectionalShadowCastingLight;

            // we resolve shadows in screenspace when cascades are enabled to save ALU as computing cascade index + shadowCoord on fragment is expensive
            shadowData.requiresScreenSpaceShadowResolve = shadowData.renderDirectionalShadows && supportsScreenSpaceShadows && pipelineAsset.cascadeCount > 1;
            shadowData.directionalLightCascadeCount     = (shadowData.requiresScreenSpaceShadowResolve) ? pipelineAsset.cascadeCount : 1;
            shadowData.directionalShadowAtlasWidth      = pipelineAsset.directionalShadowAtlasResolution;
            shadowData.directionalShadowAtlasHeight     = pipelineAsset.directionalShadowAtlasResolution;

            switch (shadowData.directionalLightCascadeCount)
            {
            case 1:
                shadowData.directionalLightCascades = new Vector3(1.0f, 0.0f, 0.0f);
                break;

            case 2:
                shadowData.directionalLightCascades = new Vector3(pipelineAsset.cascade2Split, 1.0f, 0.0f);
                break;

            default:
                shadowData.directionalLightCascades = pipelineAsset.cascade4Split;
                break;
            }

            shadowData.renderLocalShadows    = pipelineAsset.supportsLocalShadows && hasLocalShadowCastingLight;
            shadowData.localShadowAtlasWidth = shadowData.localShadowAtlasHeight = pipelineAsset.localShadowAtlasResolution;
            shadowData.supportsSoftShadows   = pipelineAsset.supportsSoftShadows;
            shadowData.bufferBitCount        = 16;

            shadowData.renderedDirectionalShadowQuality = LightShadows.None;
            shadowData.renderedLocalShadowQuality       = LightShadows.None;
        }
        static void InitializeShadowData(PipelineSettings settings, List <VisibleLight> visibleLights, bool mainLightCastShadows, bool additionalLightsCastShadows, out ShadowData shadowData)
        {
            m_ShadowBiasData.Clear();

            for (int i = 0; i < visibleLights.Count; ++i)
            {
                Light light = visibleLights[i].light;
                LWRPAdditionalLightData data =
                    (light != null) ? light.gameObject.GetComponent <LWRPAdditionalLightData>() : null;

                if (data && !data.usePipelineSettings)
                {
                    m_ShadowBiasData.Add(new Vector4(light.shadowBias, light.shadowNormalBias, 0.0f, 0.0f));
                }
                else
                {
                    m_ShadowBiasData.Add(new Vector4(settings.shadowDepthBias, settings.shadowNormalBias, 0.0f, 0.0f));
                }
            }

            shadowData.bias = m_ShadowBiasData;

            // Until we can have keyword stripping forcing single cascade hard shadows on gles2
            bool supportsScreenSpaceShadows = SystemInfo.graphicsDeviceType != GraphicsDeviceType.OpenGLES2;

            shadowData.supportsMainLightShadows = settings.supportsMainLightShadows && mainLightCastShadows;

            // we resolve shadows in screenspace when cascades are enabled to save ALU as computing cascade index + shadowCoord on fragment is expensive
            shadowData.requiresScreenSpaceShadowResolve = shadowData.supportsMainLightShadows && supportsScreenSpaceShadows && settings.cascadeCount > 1;
            shadowData.mainLightShadowCascadesCount     = (shadowData.requiresScreenSpaceShadowResolve) ? settings.cascadeCount : 1;
            shadowData.mainLightShadowmapWidth          = settings.mainLightShadowmapResolution;
            shadowData.mainLightShadowmapHeight         = settings.mainLightShadowmapResolution;
            shadowData.mainCharacterShadowmapWidth      = settings.mainCharacterShadowmapResolution;
            shadowData.mainCharacterShadowmapHeight     = settings.mainCharacterShadowmapResolution;
            shadowData.deepShadowMapsSize       = settings.deepShadowMapsSize;
            shadowData.deepShadowMapsDepth      = settings.deepShadowMapsDepth;
            shadowData.deepShadowMapsBlurOffset = settings.deepShadowMapsBlurOffset;

            switch (shadowData.mainLightShadowCascadesCount)
            {
            case 1:
                shadowData.mainLightShadowCascadesSplit = new Vector3(1.0f, 0.0f, 0.0f);
                break;

            case 2:
                shadowData.mainLightShadowCascadesSplit = new Vector3(settings.cascade2Split, 1.0f, 0.0f);
                break;

            default:
                shadowData.mainLightShadowCascadesSplit = settings.cascade4Split;
                break;
            }

            shadowData.supportsAdditionalLightShadows = settings.supportsAdditionalLightShadows && additionalLightsCastShadows;
            shadowData.additionalLightsShadowmapWidth = shadowData.additionalLightsShadowmapHeight = settings.additionalLightsShadowmapResolution;
            shadowData.supportsSoftShadows            = settings.supportsSoftShadows && (shadowData.supportsMainLightShadows || shadowData.supportsAdditionalLightShadows);
            shadowData.shadowmapDepthBufferBits       = 16;

            shadowData.supportsMainCharacterShadows = settings.supportsMainCharacterShadows && mainLightCastShadows;

            shadowData.supportsDeepShadowMaps = settings.supportsDeepShadowMaps && mainLightCastShadows;
        }
        void SetShaderKeywords(CommandBuffer cmd, ref CameraData cameraData, ref LightData lightData, ref ShadowData shadowData)
        {
            int vertexLightsCount = lightData.totalAdditionalLightsCount - lightData.pixelAdditionalLightsCount;

            CoreUtils.SetKeyword(cmd, LightweightKeywordStrings.AdditionalLights, lightData.totalAdditionalLightsCount > 0);
            CoreUtils.SetKeyword(cmd, LightweightKeywordStrings.MixedLightingSubtractive, m_MixedLightingSetup == MixedLightingSetup.Subtractive);
            CoreUtils.SetKeyword(cmd, LightweightKeywordStrings.VertexLights, vertexLightsCount > 0);

            List <VisibleLight> visibleLights = lightData.visibleLights;

            // If shadows were resolved in screen space we don't sample shadowmap in lit shader. In that case we just set softDirectionalShadows to false.
            bool softDirectionalShadows = shadowData.renderDirectionalShadows && !shadowData.requiresScreenSpaceShadowResolve &&
                                          shadowData.supportsSoftShadows && lightData.mainLightIndex != -1 &&
                                          visibleLights[lightData.mainLightIndex].light.shadows == LightShadows.Soft;

            bool softLocalShadows = false;

            if (shadowData.renderLocalShadows && shadowData.supportsSoftShadows)
            {
                List <int> visibleLocalLightIndices = lightData.visibleLocalLightIndices;
                for (int i = 0; i < visibleLocalLightIndices.Count; ++i)
                {
                    if (visibleLights[visibleLocalLightIndices[i]].light.shadows == LightShadows.Soft)
                    {
                        softLocalShadows = true;
                        break;
                    }
                }
            }

            // Currently shadow filtering keyword is shared between local and directional shadows.
            bool hasSoftShadows = softDirectionalShadows || softLocalShadows;

            CoreUtils.SetKeyword(cmd, LightweightKeywordStrings.DirectionalShadows, shadowData.renderDirectionalShadows);
            CoreUtils.SetKeyword(cmd, LightweightKeywordStrings.LocalShadows, shadowData.renderLocalShadows);
            CoreUtils.SetKeyword(cmd, LightweightKeywordStrings.SoftShadows, hasSoftShadows);
            CoreUtils.SetKeyword(cmd, LightweightKeywordStrings.CascadeShadows, shadowData.directionalLightCascadeCount > 1);

            // TODO: Remove this. legacy particles support will be removed from Unity in 2018.3. This should be a shader_feature instead with prop exposed in the Standard particles shader.
            CoreUtils.SetKeyword(cmd, LightweightKeywordStrings.SoftParticles, cameraData.requiresSoftParticles);
        }
Beispiel #7
0
 void SetShadowCollectPassKeywords(CommandBuffer cmd, ref ShadowData shadowData)
 {
     CoreUtils.SetKeyword(cmd, LightweightKeywordStrings.SoftShadows, shadowData.renderedDirectionalShadowQuality == LightShadows.Soft);
     CoreUtils.SetKeyword(cmd, LightweightKeywordStrings.CascadeShadows, shadowData.directionalLightCascadeCount > 1);
 }
Beispiel #8
0
        void RenderAdditionalShadowmapAtlas(ref ScriptableRenderContext context, ref CullingResults cullResults, ref LightData lightData, ref ShadowData shadowData)
        {
            NativeArray <VisibleLight> visibleLights = lightData.visibleLights;

            bool          additionalLightHasSoftShadows = false;
            CommandBuffer cmd = CommandBufferPool.Get(k_RenderAdditionalLightShadows);

            using (new ProfilingSample(cmd, k_RenderAdditionalLightShadows))
            {
                int shadowmapWidth  = shadowData.additionalLightsShadowmapWidth;
                int shadowmapHeight = shadowData.additionalLightsShadowmapHeight;

                m_AdditionalLightsShadowmapTexture = ShadowUtils.GetTemporaryShadowTexture(shadowmapWidth, shadowmapHeight, k_ShadowmapBufferBits);

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

                for (int i = 0; i < m_AdditionalShadowCastingLightIndices.Count; ++i)
                {
                    int          shadowLightIndex = m_AdditionalShadowCastingLightIndices[i];
                    VisibleLight shadowLight      = visibleLights[shadowLightIndex];

                    if (m_AdditionalShadowCastingLightIndices.Count > 1)
                    {
                        ShadowUtils.ApplySliceTransform(ref m_AdditionalLightSlices[i], shadowmapWidth, shadowmapHeight);
                    }

                    var     settings   = new ShadowDrawingSettings(cullResults, shadowLightIndex);
                    Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex,
                                                                   ref shadowData, m_AdditionalLightSlices[i].projectionMatrix, m_AdditionalLightSlices[i].resolution);
                    ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias);
                    ShadowUtils.RenderShadowSlice(cmd, ref context, ref m_AdditionalLightSlices[i], ref settings, m_AdditionalLightSlices[i].projectionMatrix, m_AdditionalLightSlices[i].viewMatrix);
                    additionalLightHasSoftShadows |= shadowLight.light.shadows == LightShadows.Soft;
                }

                SetupAdditionalLightsShadowReceiverConstants(cmd, ref shadowData);
            }

            // We share soft shadow settings for main light and additional lights to save keywords.
            // So we check here if pipeline supports soft shadows and either main light or any additional light has soft shadows
            // to enable the keyword.
            // TODO: In PC and Consoles we can upload shadow data per light and branch on shader. That will be more likely way faster.
            bool mainLightHasSoftShadows = shadowData.supportsMainLightShadows &&
                                           lightData.mainLightIndex != -1 &&
                                           visibleLights[lightData.mainLightIndex].light.shadows == LightShadows.Soft;

            bool softShadows = shadowData.supportsSoftShadows && (mainLightHasSoftShadows || additionalLightHasSoftShadows);

            CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.AdditionalLightShadows, true);
            CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, softShadows);
            context.ExecuteCommandBuffer(cmd);
            CommandBufferPool.Release(cmd);
        }