public bool Setup(RenderTargetHandle destination, ref RenderingData renderingData) { Clear(); this.destination = destination; int shadowLightIndex = renderingData.lightData.mainLightIndex; if (shadowLightIndex == -1) { return(false); } VisibleLight shadowLight = renderingData.lightData.visibleLights[shadowLightIndex]; Light light = shadowLight.light; if (light.shadows == LightShadows.None) { return(false); } if (shadowLight.lightType != LightType.Directional) { Debug.LogWarning("Only directional lights are supported as main light."); } Bounds bounds; if (!renderingData.cullResults.GetShadowCasterBounds(shadowLightIndex, out bounds)) { return(false); } m_ShadowCasterCascadesCount = renderingData.shadowData.mainLightShadowCascadesCount; int shadowResolution = ShadowUtils.GetMaxTileResolutionInAtlas(renderingData.shadowData.mainLightShadowmapWidth, renderingData.shadowData.mainLightShadowmapHeight, m_ShadowCasterCascadesCount); for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex) { bool success = ShadowUtils.ExtractDirectionalLightMatrix(ref renderingData.cullResults, ref renderingData.shadowData, shadowLightIndex, cascadeIndex, shadowResolution, light.shadowNearPlane, out m_CascadeSplitDistances[cascadeIndex], out m_CascadeSlices[cascadeIndex], out m_CascadeSlices[cascadeIndex].viewMatrix, out m_CascadeSlices[cascadeIndex].projectionMatrix); if (!success) { return(false); } } return(true); }
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); }
public bool Setup(RenderTargetHandle destination, ref RenderingData renderingData, int maxVisibleAdditinalLights) { Clear(); this.destination = destination; if (m_AdditionalLightShadowMatrices.Length != maxVisibleAdditinalLights) { m_AdditionalLightShadowMatrices = new Matrix4x4[maxVisibleAdditinalLights]; m_AdditionalLightSlices = new ShadowSliceData[maxVisibleAdditinalLights]; m_AdditionalLightsShadowStrength = new float[maxVisibleAdditinalLights]; } m_AdditionalShadowCastingLightIndices.Clear(); Bounds bounds; List <VisibleLight> visibleLights = renderingData.lightData.visibleLights; int additionalLightsCount = renderingData.lightData.additionalLightsCount; for (int i = 0; i < visibleLights.Count && m_AdditionalShadowCastingLightIndices.Count < additionalLightsCount; ++i) { if (i == renderingData.lightData.mainLightIndex) { continue; } VisibleLight shadowLight = visibleLights[i]; Light light = shadowLight.light; if (shadowLight.lightType == LightType.Spot && light != null && light.shadows != LightShadows.None) { if (renderingData.cullResults.GetShadowCasterBounds(i, out bounds)) { m_AdditionalShadowCastingLightIndices.Add(i); } } } int shadowCastingLightsCount = m_AdditionalShadowCastingLightIndices.Count; if (shadowCastingLightsCount == 0) { return(false); } // 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 = renderingData.shadowData.additionalLightsShadowmapWidth; int atlasHeight = renderingData.shadowData.additionalLightsShadowmapHeight; int sliceResolution = ShadowUtils.GetMaxTileResolutionInAtlas(atlasWidth, atlasHeight, shadowCastingLightsCount); bool anyShadows = false; int shadowSlicesPerRow = (atlasWidth / sliceResolution); for (int i = 0; i < shadowCastingLightsCount; ++i) { int shadowLightIndex = m_AdditionalShadowCastingLightIndices[i]; VisibleLight shadowLight = visibleLights[shadowLightIndex]; // Currently Only Spot Lights are supported in additional lights Debug.Assert(shadowLight.lightType == LightType.Spot); Matrix4x4 shadowTransform; bool success = ShadowUtils.ExtractSpotLightMatrix(ref renderingData.cullResults, ref renderingData.shadowData, shadowLightIndex, out shadowTransform, out m_AdditionalLightSlices[i].viewMatrix, out m_AdditionalLightSlices[i].projectionMatrix); if (success) { // 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 % shadowSlicesPerRow) * sliceResolution; m_AdditionalLightSlices[i].offsetY = (i / shadowSlicesPerRow) * sliceResolution; m_AdditionalLightSlices[i].resolution = sliceResolution; m_AdditionalLightSlices[i].shadowTransform = shadowTransform; m_AdditionalLightsShadowStrength[i] = shadowLight.light.shadowStrength; anyShadows = true; } else { m_AdditionalShadowCastingLightIndices.RemoveAt(i--); } } return(anyShadows); }
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); }