// ------------------------ Debug API ------------------------------- #if UNITY_EDITOR internal void PrintLightStatusInCachedAtlas() { bool headerPrinted = false; var lights = GameObject.FindObjectsOfType <HDAdditionalLightData>(); foreach (var light in lights) { ShadowMapType shadowMapType = light.GetShadowMapType(light.type); if (instance.LightIsPendingPlacement(light, shadowMapType)) { if (!headerPrinted) { Debug.Log(" ===== Lights pending placement in the cached shadow atlas: ===== "); headerPrinted = true; } Debug.Log("\t Name: " + light.name + " Type: " + light.type + " Resolution: " + light.GetResolutionFromSettings(shadowMapType, m_InitParams)); } } headerPrinted = false; foreach (var light in lights) { ShadowMapType shadowMapType = light.GetShadowMapType(light.type); if (!(instance.LightIsPendingPlacement(light, light.GetShadowMapType(light.type))) && light.lightIdxForCachedShadows != -1) { if (!headerPrinted) { Debug.Log("===== Lights placed in cached shadow atlas: ===== "); headerPrinted = true; } Debug.Log("\t Name: " + light.name + " Type: " + light.type + " Resolution: " + light.GetResolutionFromSettings(shadowMapType, m_InitParams)); } } }
internal HDShadowResolutionRequest GetResolutionRequest(ShadowMapType type, bool cachedShadow, int index) { if (cachedShadow) { switch (type) { case ShadowMapType.PunctualAtlas: return(m_Atlas.GetCachedRequest(index)); case ShadowMapType.AreaLightAtlas: return(m_AreaLightShadowAtlas.GetCachedRequest(index)); } } else { if (index < 0 || index >= m_ShadowRequestCount) { return(null); } return(m_ShadowResolutionRequests[index]); } return(null); }
public int ReserveShadowResolutions(Vector2 resolution, ShadowMapType shadowMapType) { if (m_ShadowRequestCount >= m_MaxShadowRequests) { Debug.LogWarning("Max shadow requests count reached, dropping all exceeding requests. You can increase this limit by changing the max requests in the HDRP asset"); return(-1); } HDShadowResolutionRequest resolutionRequest = new HDShadowResolutionRequest { resolution = resolution, shadowMapType = shadowMapType, }; switch (shadowMapType) { case ShadowMapType.PunctualAtlas: m_Atlas.ReserveResolution(resolutionRequest); break; case ShadowMapType.AreaLightAtlas: m_AreaLightShadowAtlas.ReserveResolution(resolutionRequest); break; case ShadowMapType.CascadedDirectional: m_CascadeAtlas.ReserveResolution(resolutionRequest); break; } m_ShadowResolutionRequests.Add(resolutionRequest); m_ShadowRequestCount = m_ShadowResolutionRequests.Count; return(m_ShadowResolutionRequests.Count - 1); }
internal int ReserveShadowResolutions(Vector2 resolution, ShadowMapType shadowMapType, int lightID, int index, bool canBeCached, out int cachedRequestIdx) { cachedRequestIdx = -1; if (m_ShadowRequestCount >= m_MaxShadowRequests) { Debug.LogWarning("Max shadow requests count reached, dropping all exceeding requests. You can increase this limit by changing the max requests in the HDRP asset"); return(-1); } int cachedIndex = -1; m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter].resolution = resolution; m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter].shadowMapType = shadowMapType; m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter].lightID = lightID; m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter].emptyRequest = false; m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter].indexInLight = index; m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter].atlasViewport.width = resolution.x; m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter].atlasViewport.height = resolution.y; if (canBeCached) { m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter].hasBeenStoredInCachedList = true; } else { m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter].hasBeenStoredInCachedList = false; } switch (shadowMapType) { case ShadowMapType.PunctualAtlas: if (canBeCached) { cachedIndex = m_Atlas.RegisterCachedLight(m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter]); } m_Atlas.ReserveResolution(m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter]); break; case ShadowMapType.AreaLightAtlas: if (canBeCached) { cachedIndex = m_AreaLightShadowAtlas.RegisterCachedLight(m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter]); } m_AreaLightShadowAtlas.ReserveResolution(m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter]); break; case ShadowMapType.CascadedDirectional: m_CascadeAtlas.ReserveResolution(m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter]); break; } m_ShadowResolutionRequestCounter++; m_ShadowRequestCount = m_ShadowResolutionRequestCounter; cachedRequestIdx = cachedIndex; return(m_ShadowResolutionRequestCounter - 1); }
// ------------------------------------------------------------------------------------------ // Init Functions // ------------------------------------------------------------------------------------------ public HDCachedShadowAtlas(ShadowMapType type) { m_PlacedShadows = new Dictionary <int, CachedShadowRecord>(s_InitialCapacity); m_ShadowsPendingRendering = new Dictionary <int, CachedShadowRecord>(s_InitialCapacity); m_TempListForPlacement = new List <CachedShadowRecord>(s_InitialCapacity); m_RegisteredLightDataPendingPlacement = new Dictionary <int, HDAdditionalLightData>(s_InitialCapacity); m_RecordsPendingPlacement = new Dictionary <int, CachedShadowRecord>(s_InitialCapacity); m_ShadowType = type; }
internal int GetAtlasShapeID(ShadowMapType type) { switch (type) { case ShadowMapType.PunctualAtlas: return(m_Atlas.atlasShapeID); case ShadowMapType.AreaLightAtlas: return(m_AreaLightShadowAtlas.atlasShapeID); } return(-1); }
public static Reaction <Camera> Renderer(SceneGraph scene, int mapSize, ShadowMapType type, bool cascaded) { var depthFramebuffer = new Framebuffer(FramebufferTarget.Framebuffer); _shadowShader = cascaded ? new GLProgram( VertexShaderCascaded(), GeometryShaderCascaded(), DepthFragmentShader()) : new GLProgram( VertexShader(), type == ShadowMapType.Depth ? DepthFragmentShader() : VarianceFragmentShader()); _instance = new Shadows(_shadowShader, cascaded); Texture depthTexture; var render = React.By <Camera> (_instance.Render); if (type == ShadowMapType.Depth || cascaded) { depthTexture = cascaded ? new Texture(TextureTarget.Texture2DArray, PixelInternalFormat.DepthComponent16, mapSize, mapSize, CascadedShadowUniforms.MapCount, PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero) : new Texture(TextureTarget.Texture2D, PixelInternalFormat.DepthComponent16, mapSize, mapSize, PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero); depthFramebuffer.AddTexture(FramebufferAttachment.DepthAttachment, depthTexture); } else { depthTexture = new Texture(TextureTarget.Texture2D, PixelInternalFormat.Rg32f, mapSize, mapSize, PixelFormat.Rg, PixelType.Float, IntPtr.Zero); depthFramebuffer.AddTexture(FramebufferAttachment.ColorAttachment0, depthTexture); depthFramebuffer.AddRenderbuffer(FramebufferAttachment.DepthAttachment, RenderbufferStorage.DepthComponent16, mapSize, mapSize); var gaussTexture = new Texture(TextureTarget.Texture2D, PixelInternalFormat.Rg32f, mapSize / 2, mapSize / 2, PixelFormat.Rg, PixelType.Float, IntPtr.Zero); render = render.And(GaussianFilter.Both().MapInput((Camera cam) => Tuple.Create(depthTexture, gaussTexture))); } scene.GlobalLighting.ShadowMap = depthTexture; return(render .DrawBuffer(type == ShadowMapType.Depth ? DrawBufferMode.None : DrawBufferMode.Front) .DepthTest() .Culling() .Viewport(new Vec2i(mapSize, mapSize)) .Program(_shadowShader) .Texture(depthTexture) .Framebuffer(depthFramebuffer)); }
internal bool LightIsPendingPlacement(HDAdditionalLightData light, ShadowMapType shadowMapType) { if (shadowMapType == ShadowMapType.PunctualAtlas) { return(punctualShadowAtlas.LightIsPendingPlacement(light)); } if (shadowMapType == ShadowMapType.AreaLightAtlas) { return(areaShadowAtlas.LightIsPendingPlacement(light)); } return(false); }
internal bool AtlasHasResized(ShadowMapType type) { switch (type) { case ShadowMapType.PunctualAtlas: return(m_Atlas.HasResizedThisFrame()); case ShadowMapType.AreaLightAtlas: return(m_AreaLightShadowAtlas.HasResizedThisFrame()); } return(false); }
internal bool CachedDataIsValid(ShadowMapType type) { const int thresholdOfValidFrames = 30; switch (type) { case ShadowMapType.PunctualAtlas: return(m_Atlas.frameOfCacheValidity > thresholdOfValidFrames); case ShadowMapType.AreaLightAtlas: return(m_AreaLightShadowAtlas.frameOfCacheValidity > thresholdOfValidFrames); } return(false); }
internal void MarkShadowAsRendered(int shadowIdx, ShadowMapType shadowMapType) { if (shadowMapType == ShadowMapType.PunctualAtlas) { punctualShadowAtlas.MarkAsRendered(shadowIdx); } if (shadowMapType == ShadowMapType.AreaLightAtlas) { areaShadowAtlas.MarkAsRendered(shadowIdx); } if (shadowMapType == ShadowMapType.CascadedDirectional) { m_DirectionalShadowPendingUpdate[shadowIdx] = false; } }
internal bool ShadowIsPendingUpdate(int shadowIdx, ShadowMapType shadowMapType) { if (shadowMapType == ShadowMapType.PunctualAtlas) { return(punctualShadowAtlas.ShadowIsPendingRendering(shadowIdx)); } if (shadowMapType == ShadowMapType.AreaLightAtlas) { return(areaShadowAtlas.ShadowIsPendingRendering(shadowIdx)); } if (shadowMapType == ShadowMapType.CascadedDirectional) { return(m_DirectionalShadowPendingUpdate[shadowIdx]); } return(false); }
internal void MarkCachedShadowSlotsAsEmpty(ShadowMapType shadowMapType, int lightID) { switch (shadowMapType) { case ShadowMapType.PunctualAtlas: if (m_Atlas != null) { m_Atlas.MarkCachedShadowSlotAsEmpty(lightID); } break; case ShadowMapType.AreaLightAtlas: if (m_AreaLightShadowAtlas != null) { m_AreaLightShadowAtlas.MarkCachedShadowSlotAsEmpty(lightID); } break; } }
internal int ReserveShadowResolutions(Vector2 resolution, ShadowMapType shadowMapType, int lightID, int index, ShadowMapUpdateType updateType) { if (m_ShadowRequestCount >= m_MaxShadowRequests) { Debug.LogWarning("Max shadow requests count reached, dropping all exceeding requests. You can increase this limit by changing the max requests in the HDRP asset"); return(-1); } m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter].shadowMapType = shadowMapType; // Note: for cached shadows we manage the resolution requests directly on the CachedShadowAtlas as they need special handling. We however keep incrementing the counter for two reasons: // - Maintain the limit of m_MaxShadowRequests // - Avoid to refactor other parts that the shadow manager that get requests indices from here. if (updateType != ShadowMapUpdateType.Cached || shadowMapType == ShadowMapType.CascadedDirectional) { m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter].resolution = resolution; m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter].dynamicAtlasViewport.width = resolution.x; m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter].dynamicAtlasViewport.height = resolution.y; switch (shadowMapType) { case ShadowMapType.PunctualAtlas: m_Atlas.ReserveResolution(m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter]); break; case ShadowMapType.AreaLightAtlas: m_AreaLightShadowAtlas.ReserveResolution(m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter]); break; case ShadowMapType.CascadedDirectional: m_CascadeAtlas.ReserveResolution(m_ShadowResolutionRequests[m_ShadowResolutionRequestCounter]); break; } } m_ShadowResolutionRequestCounter++; m_ShadowRequestCount = m_ShadowResolutionRequestCounter; return(m_ShadowResolutionRequestCounter - 1); }
internal void PruneEmptyCachedSlots(ShadowMapType type) { switch (type) { case ShadowMapType.PunctualAtlas: if (m_Atlas != null) { m_Atlas.PruneDeadCachedLightSlots(); } break; case ShadowMapType.AreaLightAtlas: if (m_AreaLightShadowAtlas != null) { m_AreaLightShadowAtlas.PruneDeadCachedLightSlots(); } break; default: break; } }
public static Reaction<Camera> Renderer(SceneGraph scene, int mapSize, ShadowMapType type, bool cascaded) { var depthFramebuffer = new Framebuffer (FramebufferTarget.Framebuffer); _shadowShader = cascaded ? new GLProgram ( VertexShaderCascaded (), GeometryShaderCascaded (), DepthFragmentShader ()) : new GLProgram ( VertexShader (), type == ShadowMapType.Depth ? DepthFragmentShader () : VarianceFragmentShader ()); _instance = new Shadows (_shadowShader, cascaded); Texture depthTexture; var render =React.By<Camera> (_instance.Render); if (type == ShadowMapType.Depth || cascaded) { depthTexture = cascaded ? new Texture (TextureTarget.Texture2DArray, PixelInternalFormat.DepthComponent16, mapSize, mapSize, CascadedShadowUniforms.MapCount, PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero) : new Texture (TextureTarget.Texture2D, PixelInternalFormat.DepthComponent16, mapSize, mapSize, PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero); depthFramebuffer.AddTexture (FramebufferAttachment.DepthAttachment, depthTexture); } else { depthTexture = new Texture (TextureTarget.Texture2D, PixelInternalFormat.Rg32f, mapSize, mapSize, PixelFormat.Rg, PixelType.Float, IntPtr.Zero); depthFramebuffer.AddTexture (FramebufferAttachment.ColorAttachment0, depthTexture); depthFramebuffer.AddRenderbuffer (FramebufferAttachment.DepthAttachment, RenderbufferStorage.DepthComponent16, mapSize, mapSize); var gaussTexture = new Texture (TextureTarget.Texture2D, PixelInternalFormat.Rg32f, mapSize / 2, mapSize / 2, PixelFormat.Rg, PixelType.Float, IntPtr.Zero); render = render.And (GaussianFilter.Both ().MapInput ((Camera cam) => Tuple.Create (depthTexture, gaussTexture))); } scene.GlobalLighting.ShadowMap = depthTexture; return render .DrawBuffer (type == ShadowMapType.Depth ? DrawBufferMode.None : DrawBufferMode.Front) .DepthTest () .Culling () .Viewport (new Vec2i (mapSize, mapSize)) .Program (_shadowShader) .Texture (depthTexture) .Framebuffer (depthFramebuffer); }
internal void UpdateResolutionRequest(ref HDShadowResolutionRequest request, int shadowIdx, ShadowMapType shadowMapType) { if (shadowMapType == ShadowMapType.PunctualAtlas) { punctualShadowAtlas.UpdateResolutionRequest(ref request, shadowIdx); } else if (shadowMapType == ShadowMapType.AreaLightAtlas) { areaShadowAtlas.UpdateResolutionRequest(ref request, shadowIdx); } }
internal void UpdateResolutionRequest(ref HDShadowResolutionRequest request, int shadowIdx, ShadowMapType shadowMapType) { if (shadowMapType == ShadowMapType.PunctualAtlas) { punctualShadowAtlas.UpdateResolutionRequest(ref request, shadowIdx); } else if (shadowMapType == ShadowMapType.AreaLightAtlas) { areaShadowAtlas.UpdateResolutionRequest(ref request, shadowIdx); } else if (shadowMapType == ShadowMapType.CascadedDirectional) { request.cachedAtlasViewport = request.dynamicAtlasViewport; } }
public void ReserveShadows(Camera camera, HDShadowManager shadowManager, HDShadowInitParameters initParameters, CullingResults cullResults, FrameSettings frameSettings, int lightIndex) { Bounds bounds; float cameraDistance = Vector3.Distance(camera.transform.position, transform.position); m_WillRenderShadows = legacyLight.shadows != LightShadows.None && frameSettings.IsEnabled(FrameSettingsField.Shadow); m_WillRenderShadows &= cullResults.GetShadowCasterBounds(lightIndex, out bounds); // When creating a new light, at the first frame, there is no AdditionalShadowData so we can't really render shadows m_WillRenderShadows &= m_ShadowData != null && m_ShadowData.shadowDimmer > 0; // If the shadow is too far away, we don't render it if (m_ShadowData != null) { m_WillRenderShadows &= legacyLight.type == LightType.Directional || cameraDistance < (m_ShadowData.shadowFadeDistance); } #if ENABLE_RAYTRACING m_WillRenderShadows &= !(lightTypeExtent == LightTypeExtent.Rectangle && useRayTracedShadows); #endif if (!m_WillRenderShadows) { return; } // Create shadow requests array using the light type if (shadowRequests == null || m_ShadowRequestIndices == null) { const int maxLightShadowRequestsCount = 6; shadowRequests = new HDShadowRequest[maxLightShadowRequestsCount]; m_ShadowRequestIndices = new int[maxLightShadowRequestsCount]; for (int i = 0; i < maxLightShadowRequestsCount; i++) { shadowRequests[i] = new HDShadowRequest(); } } Vector2 viewportSize = new Vector2(m_ShadowData.shadowResolution, m_ShadowData.shadowResolution); // Reserver wanted resolution in the shadow atlas ShadowMapType shadowMapType = (lightTypeExtent == LightTypeExtent.Rectangle) ? ShadowMapType.AreaLightAtlas : (legacyLight.type != LightType.Directional) ? ShadowMapType.PunctualAtlas : ShadowMapType.CascadedDirectional; bool viewPortRescaling = false; // Compute dynamic shadow resolution viewPortRescaling |= (shadowMapType == ShadowMapType.PunctualAtlas && initParameters.punctualLightShadowAtlas.useDynamicViewportRescale); viewPortRescaling |= (shadowMapType == ShadowMapType.AreaLightAtlas && initParameters.areaLightShadowAtlas.useDynamicViewportRescale); if (viewPortRescaling) { // resize viewport size by the normalized size of the light on screen // When we will have access to the non screen clamped bounding sphere light size, we could use it to scale the shadow map resolution // For the moment, this will be enough viewportSize *= Mathf.Lerp(64f / viewportSize.x, 1f, legacyLight.range / (camera.transform.position - transform.position).magnitude); viewportSize = Vector2.Max(new Vector2(64f, 64f) / viewportSize, viewportSize); // Prevent flickering caused by the floating size of the viewport viewportSize.x = Mathf.Round(viewportSize.x); viewportSize.y = Mathf.Round(viewportSize.y); } viewportSize = Vector2.Max(viewportSize, new Vector2(16, 16)); // Update the directional shadow atlas size if (legacyLight.type == LightType.Directional) { shadowManager.UpdateDirectionalShadowResolution((int)viewportSize.x, m_ShadowSettings.cascadeShadowSplitCount.value); } int count = GetShadowRequestCount(); for (int index = 0; index < count; index++) { m_ShadowRequestIndices[index] = shadowManager.ReserveShadowResolutions(viewportSize, shadowMapType); } }