void RenderAdditionalShadowmapAtlas(ref ScriptableRenderContext context, ref CullResults cullResults, ref LightData lightData, ref ShadowData shadowData) { List <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 = RenderTexture.GetTemporary(shadowmapWidth, shadowmapHeight, k_ShadowmapBufferBits, m_AdditionalShadowmapFormat); m_AdditionalLightsShadowmapTexture.filterMode = FilterMode.Bilinear; m_AdditionalLightsShadowmapTexture.wrapMode = TextureWrapMode.Clamp; 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 DrawShadowsSettings(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); }
void RenderMainLightCascadeShadowmap(ref ScriptableRenderContext context, ref CullingResults cullResults, ref LightData lightData, ref ShadowData shadowData) { int shadowLightIndex = lightData.mainLightIndex; if (shadowLightIndex == -1) { return; } VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex]; CommandBuffer cmd = CommandBufferPool.Get(k_RenderMainLightShadowmapTag); using (new ProfilingSample(cmd, k_RenderMainLightShadowmapTag)) { var settings = new ShadowDrawingSettings(cullResults, shadowLightIndex); m_MainLightShadowmapTexture = RenderTexture.GetTemporary(shadowData.mainLightShadowmapWidth, shadowData.mainLightShadowmapHeight, k_ShadowmapBufferBits, m_ShadowmapFormat); m_MainLightShadowmapTexture.filterMode = FilterMode.Bilinear; m_MainLightShadowmapTexture.wrapMode = TextureWrapMode.Clamp; SetRenderTarget(cmd, m_MainLightShadowmapTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black, TextureDimension.Tex2D); for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex) { var splitData = settings.splitData; splitData.cullingSphere = m_CascadeSplitDistances[cascadeIndex]; settings.splitData = splitData; Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, m_CascadeSlices[cascadeIndex].projectionMatrix, m_CascadeSlices[cascadeIndex].resolution); ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias); ShadowUtils.RenderShadowSlice(cmd, ref context, ref m_CascadeSlices[cascadeIndex], ref settings, m_CascadeSlices[cascadeIndex].projectionMatrix, m_CascadeSlices[cascadeIndex].viewMatrix); } SetupMainLightShadowReceiverConstants(cmd, ref shadowData, shadowLight); } CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadows, true); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadowCascades, shadowData.mainLightShadowCascadesCount > 1); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, shadowLight.light.shadows == LightShadows.Soft && shadowData.supportsSoftShadows); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
void RenderMainLightCascadeShadowmap(ref ScriptableRenderContext context, ref CullResults cullResults, ref LightData lightData, ref ShadowData shadowData) { int shadowLightIndex = lightData.mainLightIndex; if (shadowLightIndex == -1) { return; } VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex]; Light light = shadowLight.light; Debug.Assert(shadowLight.lightType == LightType.Directional); if (light.shadows == LightShadows.None) { return; } Bounds bounds; if (!cullResults.GetShadowCasterBounds(shadowLightIndex, out bounds)) { return; } CommandBuffer cmd = CommandBufferPool.Get(k_RenderMainLightShadowmapTag); using (new ProfilingSample(cmd, k_RenderMainLightShadowmapTag)) { m_ShadowCasterCascadesCount = shadowData.mainLightShadowCascadesCount; int shadowResolution = ShadowUtils.GetMaxTileResolutionInAtlas(shadowData.mainLightShadowmapWidth, shadowData.mainLightShadowmapHeight, m_ShadowCasterCascadesCount); float shadowNearPlane = light.shadowNearPlane; Matrix4x4 view, proj; var settings = new DrawShadowsSettings(cullResults, shadowLightIndex); m_MainLightShadowmapTexture = RenderTexture.GetTemporary(shadowData.mainLightShadowmapWidth, shadowData.mainLightShadowmapHeight, k_ShadowmapBufferBits, m_ShadowmapFormat); m_MainLightShadowmapTexture.filterMode = FilterMode.Bilinear; m_MainLightShadowmapTexture.wrapMode = TextureWrapMode.Clamp; SetRenderTarget(cmd, m_MainLightShadowmapTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black, TextureDimension.Tex2D); bool success = false; for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex) { success = ShadowUtils.ExtractDirectionalLightMatrix(ref cullResults, ref shadowData, shadowLightIndex, cascadeIndex, shadowResolution, shadowNearPlane, out m_CascadeSplitDistances[cascadeIndex], out m_CascadeSlices[cascadeIndex], out view, out proj); if (success) { settings.splitData.cullingSphere = m_CascadeSplitDistances[cascadeIndex]; Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, proj, shadowResolution); ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias); ShadowUtils.RenderShadowSlice(cmd, ref context, ref m_CascadeSlices[cascadeIndex], ref settings, proj, view); } } if (success) { SetupMainLightShadowReceiverConstants(cmd, ref shadowData, shadowLight); } } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
/// <inheritdoc/> public override void Execute(ScriptableRenderer renderer, ScriptableRenderContext context, ref RenderingData renderingData) { if (renderer == null) { throw new ArgumentNullException("renderer"); } if (!renderingData.shadowData.supportsMainCharacterShadows) { return; } LightData lightData = renderingData.lightData; int shadowLightIndex = lightData.mainLightIndex; if (shadowLightIndex == -1) { return; } VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex]; ShadowData shadowData = renderingData.shadowData; if (!GetVPMatrix(shadowLight.light)) { return; } CommandBuffer cmd = CommandBufferPool.Get(k_RenderMainCharacterShadowmapTag); using (new ProfilingSample(cmd, k_RenderMainCharacterShadowmapTag)) { m_MainCharacterShadowmapTexture = RenderTexture.GetTemporary(shadowData.mainCharacterShadowmapWidth, shadowData.mainCharacterShadowmapHeight, k_ShadowmapBufferBits, m_ShadowmapFormat); m_MainCharacterShadowmapTexture.filterMode = FilterMode.Bilinear; m_MainCharacterShadowmapTexture.wrapMode = TextureWrapMode.Clamp; m_MainCharacterShadowmapTexture.name = "m_MainCharacterShadowmapTexture"; SetRenderTarget(cmd, m_MainCharacterShadowmapTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black, TextureDimension.Tex2D); Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, m_ProjMatrix, shadowData.mainCharacterShadowmapWidth); ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias); cmd.SetViewProjectionMatrices(m_ViewMatrix, m_ProjMatrix); context.ExecuteCommandBuffer(cmd); cmd.Clear(); //foreach (var r in _Renderers) //{ // for (int i = 0, imax = r.sharedMaterials.Length; i < imax; i++) // { // cmd.DrawRenderer(r, r.sharedMaterials[i], i, r.sharedMaterials[i].FindPass("ShadowCaster")); // } //} ShadowSliceData slice = new ShadowSliceData() { offsetX = 0, offsetY = 0, resolution = shadowData.mainCharacterShadowmapWidth }; DrawShadowsSettings settings = new DrawShadowsSettings(renderingData.cullResults, shadowLightIndex); settings.splitData.cullingSphere = m_CullingSphere; ShadowUtils.RenderShadowSlice(cmd, ref context, ref slice, ref settings, m_ProjMatrix, m_ViewMatrix); context.ExecuteCommandBuffer(cmd); cmd.Clear(); SetupMainCharacterShadowReceiverConstants(cmd, ref shadowData, shadowLight); } CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainCharacterShadows, true); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, shadowLight.light.shadows == LightShadows.Soft && shadowData.supportsSoftShadows); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
void RenderAdditionalShadowmapAtlas(ref ScriptableRenderContext context, ref CullResults cullResults, ref LightData lightData, ref ShadowData shadowData) { List <int> additionalLightIndices = lightData.additionalLightIndices; List <VisibleLight> visibleLights = lightData.visibleLights; int shadowCastingLightsCount = 0; int additionalLightsCount = additionalLightIndices.Count; for (int i = 0; i < additionalLightsCount; ++i) { VisibleLight shadowLight = visibleLights[additionalLightIndices[i]]; if (shadowLight.lightType == LightType.Spot && shadowLight.light.shadows != LightShadows.None) { shadowCastingLightsCount++; } } if (shadowCastingLightsCount == 0) { return; } Matrix4x4 view, proj; Bounds bounds; CommandBuffer cmd = CommandBufferPool.Get(k_RenderAdditionalLightShadows); using (new ProfilingSample(cmd, k_RenderAdditionalLightShadows)) { // 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.additionalLightsShadowmapWidth; int atlasHeight = shadowData.additionalLightsShadowmapHeight; int sliceResolution = ShadowUtils.GetMaxTileResolutionInAtlas(atlasWidth, atlasHeight, shadowCastingLightsCount); m_AdditionalLightsShadowmapTexture = RenderTexture.GetTemporary(shadowData.additionalLightsShadowmapWidth, shadowData.additionalLightsShadowmapHeight, k_ShadowmapBufferBits, m_AdditionalShadowmapFormat); m_AdditionalLightsShadowmapTexture.filterMode = FilterMode.Bilinear; m_AdditionalLightsShadowmapTexture.wrapMode = TextureWrapMode.Clamp; SetRenderTarget(cmd, m_AdditionalLightsShadowmapTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black, TextureDimension.Tex2D); for (int i = 0; i < additionalLightsCount; ++i) { int shadowLightIndex = additionalLightIndices[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 = ShadowUtils.ExtractSpotLightMatrix(ref cullResults, ref shadowData, shadowLightIndex, out shadowTransform, out view, out proj); if (success) { // This way of computing the shadow slice only work for spots and with most 4 shadow casting lights per pass // Change this when point lights are supported. Debug.Assert(shadowCastingLightsCount <= 4 && shadowLight.lightType == LightType.Spot); // TODO: We need to pass bias and scale list to shader to be able to support multiple // shadow casting additional lights. m_AdditionalLightSlices[i].offsetX = (i % 2) * sliceResolution; m_AdditionalLightSlices[i].offsetY = (i / 2) * sliceResolution; m_AdditionalLightSlices[i].resolution = sliceResolution; m_AdditionalLightSlices[i].shadowTransform = shadowTransform; m_AdditionalLightsShadowStrength[i] = light.shadowStrength; if (shadowCastingLightsCount > 1) { ShadowUtils.ApplySliceTransform(ref m_AdditionalLightSlices[i], atlasWidth, atlasHeight); } var settings = new DrawShadowsSettings(cullResults, shadowLightIndex); Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, proj, sliceResolution); ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias); ShadowUtils.RenderShadowSlice(cmd, ref context, ref m_AdditionalLightSlices[i], ref settings, proj, view); } } SetupAdditionalLightsShadowReceiverConstants(cmd, ref shadowData); } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
/// <inheritdoc/> public override void Execute(ScriptableRenderer renderer, ScriptableRenderContext context, ref RenderingData renderingData) { if (renderer == null) { throw new ArgumentNullException("renderer"); } if (!renderingData.shadowData.supportsDeepShadowMaps) { return; } LightData lightData = renderingData.lightData; int shadowLightIndex = lightData.mainLightIndex; if (shadowLightIndex == -1) { return; } VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex]; ShadowData shadowData = renderingData.shadowData; if (!GetVPMatrix(shadowLight.light)) { return; } if (null == _ResetCompute) { _ResetCompute = renderer.GetCompute(ComputeHandle.ResetDeepShadowDataCompute); KernelResetBuffer = _ResetCompute.FindKernel("KernelResetBuffer"); } CommandBuffer cmd = CommandBufferPool.Get(k_RenderDeepShadowCaster); using (new ProfilingSample(cmd, k_RenderDeepShadowCaster)) { int deepShadowMapsSize = shadowData.deepShadowMapsSize; int deepShadowMapsDepth = shadowData.deepShadowMapsDepth; // Reset cmd.SetComputeBufferParam(_ResetCompute, KernelResetBuffer, "_CountBuffer", _CountBuffer); cmd.SetComputeBufferParam(_ResetCompute, KernelResetBuffer, "_DataBuffer", _DataBuffer); cmd.SetComputeIntParam(_ResetCompute, "_DeepShadowMapSize", deepShadowMapsSize); cmd.SetComputeIntParam(_ResetCompute, "_DeepShadowMapDepth", deepShadowMapsDepth); cmd.DispatchCompute(_ResetCompute, KernelResetBuffer, deepShadowMapsSize / 8, deepShadowMapsSize / 8, 1); _Temp = RenderTexture.GetTemporary(deepShadowMapsSize, deepShadowMapsSize, 0, RenderTextureFormat.R8); //Without rt, the second row of the vp matrix is negated // Cast SetRenderTarget(cmd, _Temp, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.DontCare, ClearFlag.Color, Color.black, TextureDimension.Tex2D); cmd.SetViewport(new Rect(Vector2.zero, Vector2.one * deepShadowMapsSize)); Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, _ProjMatrix, shadowData.deepShadowMapsSize); ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias); cmd.SetViewProjectionMatrices(_ViewMatrix, _ProjMatrix); cmd.SetRandomWriteTarget(1, _CountBuffer); cmd.SetRandomWriteTarget(2, _DataBuffer); cmd.SetGlobalInt("_DeepShadowMapSize", deepShadowMapsSize); cmd.SetGlobalInt("_DeepShadowMapDepth", deepShadowMapsDepth); context.ExecuteCommandBuffer(cmd); cmd.Clear(); //foreach (var r in _Renderers) //{ // for (int i = 0, imax = r.sharedMaterials.Length; i < imax; i++) // { // cmd.DrawRenderer(r, r.sharedMaterials[i], i, r.sharedMaterials[i].FindPass("DeepShadowCaster")); // } //} ShadowSliceData slice = new ShadowSliceData() { offsetX = 0, offsetY = 0, resolution = deepShadowMapsSize, }; cmd.SetGlobalMatrix("_DeepShadowMapsWorldToShadow", _DeepShadowMatrix); DrawShadowsSettings settings = new DrawShadowsSettings(renderingData.cullResults, shadowLightIndex); settings.splitData.cullingSphere = _CullingSphere; cmd.EnableShaderKeyword("_DEEP_SHADOW_CASTER"); cmd.SetGlobalInt("_ShadowCasterZWrite", 0); ShadowUtils.RenderShadowSlice(cmd, ref context, ref slice, ref settings, _ProjMatrix, _ViewMatrix); cmd.DisableShaderKeyword("_DEEP_SHADOW_CASTER"); cmd.SetGlobalInt("_ShadowCasterZWrite", 1); context.ExecuteCommandBuffer(cmd); cmd.Clear(); // For Resolve SetupDeepShadowMapResolverConstants(cmd, ref shadowData, shadowLight); cmd.ClearRandomWriteTargets(); } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }