New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mixed cached shadow maps (Cached static + dynamic rendered every frame) #1559
Mixed cached shadow maps (Cached static + dynamic rendered every frame) #1559
Conversation
…ters # Conflicts: # com.unity.render-pipelines.high-definition/Runtime/Lighting/Light/HDAdditionalLightData.cs
@@ -108,6 +108,10 @@ When a Light that caches its shadows renders its shadow map for the first time, | |||
If the Light's **Update Mode** is set to **OnDemand**, you can manually request HDRP to update the Light's shadow map. To do this, access the Light's **HDAdditionalLightData** component and call the `RequestShadowMapRendering` function. Also, if the Light has multiple shadows (e.g. multiple cascades of a directional light), you can request the update of a specific sub-shadow. To do this, use the `RequestSubShadowMapRendering(shadowIndex)` function. | |||
For a Light that does cache its shadows, if you disable it or set its **Update Mode** to **Every Frame**, you can tell HDRP to preserve the Light's shadow map's place in the cached shadow atlas. This means that, if you enable the Light again, HDRP does not need to re-render the shadow map or place it into a shadow atlas. For information on how to make a Light preserve its shadow map's place in the cached shadow atlas, see [Preserving shadow atlas placement](#preserving-shadow-atlas-placement). | |||
|
|||
As a shortcut for a common case, HDRP offers an option to automatically trigger an update when either the position or rotation of a light changes above a certain threshold. This option can be selected in the Shadow settings section on the Light as **Update on light movement**. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a shortcut for a common case, HDRP offers an option to automatically trigger an update when either the position or rotation of a light changes above a certain threshold. To enable this option, select a Light and, in the Shadow section of its Inspector, enable Update on light movement.
@@ -108,6 +108,10 @@ When a Light that caches its shadows renders its shadow map for the first time, | |||
If the Light's **Update Mode** is set to **OnDemand**, you can manually request HDRP to update the Light's shadow map. To do this, access the Light's **HDAdditionalLightData** component and call the `RequestShadowMapRendering` function. Also, if the Light has multiple shadows (e.g. multiple cascades of a directional light), you can request the update of a specific sub-shadow. To do this, use the `RequestSubShadowMapRendering(shadowIndex)` function. | |||
For a Light that does cache its shadows, if you disable it or set its **Update Mode** to **Every Frame**, you can tell HDRP to preserve the Light's shadow map's place in the cached shadow atlas. This means that, if you enable the Light again, HDRP does not need to re-render the shadow map or place it into a shadow atlas. For information on how to make a Light preserve its shadow map's place in the cached shadow atlas, see [Preserving shadow atlas placement](#preserving-shadow-atlas-placement). | |||
|
|||
As a shortcut for a common case, HDRP offers an option to automatically trigger an update when either the position or rotation of a light changes above a certain threshold. This option can be selected in the Shadow settings section on the Light as **Update on light movement**. | |||
The threshold that are used to determine how much a light needs to move or rotate to trigger an update can be customized per light with the properties |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can customize the threshold that HDRP uses to determine how much a light needs to move or rotate to trigger an update. To do this, use the:
@@ -108,6 +108,10 @@ When a Light that caches its shadows renders its shadow map for the first time, | |||
If the Light's **Update Mode** is set to **OnDemand**, you can manually request HDRP to update the Light's shadow map. To do this, access the Light's **HDAdditionalLightData** component and call the `RequestShadowMapRendering` function. Also, if the Light has multiple shadows (e.g. multiple cascades of a directional light), you can request the update of a specific sub-shadow. To do this, use the `RequestSubShadowMapRendering(shadowIndex)` function. | |||
For a Light that does cache its shadows, if you disable it or set its **Update Mode** to **Every Frame**, you can tell HDRP to preserve the Light's shadow map's place in the cached shadow atlas. This means that, if you enable the Light again, HDRP does not need to re-render the shadow map or place it into a shadow atlas. For information on how to make a Light preserve its shadow map's place in the cached shadow atlas, see [Preserving shadow atlas placement](#preserving-shadow-atlas-placement). | |||
|
|||
As a shortcut for a common case, HDRP offers an option to automatically trigger an update when either the position or rotation of a light changes above a certain threshold. This option can be selected in the Shadow settings section on the Light as **Update on light movement**. | |||
The threshold that are used to determine how much a light needs to move or rotate to trigger an update can be customized per light with the properties | |||
`cachedShadowTranslationUpdateThreshold` and `cachedShadowAngleUpdateThreshold` on the **HDAdditionalLightData** component. Note that point lights ignore the angle differences when determining if an update is needed with this mode. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cachedShadowTranslationUpdateThreshold
and cachedShadowAngleUpdateThreshold
properties on the Light's HDAdditionalLightData component. Note that point lights ignore the angle differences when determining if they need to perform an update in this mode.
@@ -131,6 +135,16 @@ Note that this causes HDRP to mark all the shadow maps in the atlas as dirty whi | |||
If you disable the Light or change its **Update Mode** to **Every Frame**, the cached shadow manager unreserves the Light's shadow map's space in the cached shadow atlas and HDRP begins to render the Light's shadow map to the normal shadow atlases every frame. If the cached shadow manager needs to allocate space on the atlas for another Light, it can overwrite the space currently taken up by the original Light's shadow map. | |||
If you plan to only temporarily set a Light's **Update Mode** to **Every Frame** and want to set it back to **On Enable** or **On Demand** later, you can preserve the Light's shadow map placement in its atlas. This is useful, for example, if you want HDRP to cache a far away Light's shadow map, but update it every frame when it gets close to the [Camera](HDRP-Camera.md). To do this, access the Light's **HDAdditionalLightData** component and enable the **preserveCachedShadow** property. If this property is set to `true`, HDRP preserves the Light's shadow map's space in its shadow atlas. Note that even if this property is enabled, if you destroy the Light, it loses its placement in the shadow atlas. | |||
|
|||
### Mixed Cached Shadow Maps | |||
|
|||
It is possible to cache only a portion of the shadow map. In order to do so, you must check the **Always draw dynamic** option in the shadow settings of the light and then tick the **Static Shadow Caster** checkbox all renderers that will be cached in shadows (in the Renderer component). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is possible to cache only a portion of the shadow map. To do this, enable the Always draw dynamic option in the Light's shadow settings and then enable the Static Shadow Caster option for all Renderers to cache shadows for.
### Mixed Cached Shadow Maps | ||
|
||
It is possible to cache only a portion of the shadow map. In order to do so, you must check the **Always draw dynamic** option in the shadow settings of the light and then tick the **Static Shadow Caster** checkbox all renderers that will be cached in shadows (in the Renderer component). | ||
With such setup, all static shadow casters are rendered in the shadow map only whenever an explicit update is requested (or only on light enable in case of **OnEnable** update mode), while the other casters (dynamic shadow casters) are drawn each frame. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this setup, HDRP only renders static shadow casters into the shadow map when an explicit update is requested (or, if the Light uses the OnEnable update mode, only when the Light enables) whereas, for dynamic shadow casters, HDRP renders them into their respective shadow maps each frame.
|
||
It is possible to cache only a portion of the shadow map. In order to do so, you must check the **Always draw dynamic** option in the shadow settings of the light and then tick the **Static Shadow Caster** checkbox all renderers that will be cached in shadows (in the Renderer component). | ||
With such setup, all static shadow casters are rendered in the shadow map only whenever an explicit update is requested (or only on light enable in case of **OnEnable** update mode), while the other casters (dynamic shadow casters) are drawn each frame. | ||
This setup is particularly useful if for example your environment is mostly static and the light doesn't move, but there are few dynamic objects that will need shadows to be cast by such lights. In such scenarios, setting the light as having a mixed cached shadow map will greatly improve performance both on CPU and GPU. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This setup is particularly useful if your environment consists of mostly static GameObjects and the lights do not move, but there are few dynamic GameObjects that you want the static lights to cast shadows for. In such scenarios, setting the light to have a mixed cached shadow map greatly improves performance both on the CPU and GPU.
With such setup, all static shadow casters are rendered in the shadow map only whenever an explicit update is requested (or only on light enable in case of **OnEnable** update mode), while the other casters (dynamic shadow casters) are drawn each frame. | ||
This setup is particularly useful if for example your environment is mostly static and the light doesn't move, but there are few dynamic objects that will need shadows to be cast by such lights. In such scenarios, setting the light as having a mixed cached shadow map will greatly improve performance both on CPU and GPU. | ||
|
||
Please note that as part of implementation details, if a shadow is set up as mixed cached, every frame a blit from the cached shadow map to the dynamic atlas is performed. This is important to keep in mind both for the extra runtime cost of the blit in itself, but also to understand that in terms of memory a single shadow map will require space in both atlases. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that, due to implementation details, if you set up a shadow to be mixed cached, HDRP performs a blit from the cached shadow map to the dynamic atlas. This is important to keep in mind both for the extra runtime cost of the blit in itself, but also to understand that, in terms of memory, a single shadow map requires space in both atlases.
|
||
Please note that as part of implementation details, if a shadow is set up as mixed cached, every frame a blit from the cached shadow map to the dynamic atlas is performed. This is important to keep in mind both for the extra runtime cost of the blit in itself, but also to understand that in terms of memory a single shadow map will require space in both atlases. | ||
|
||
Another important note, is due to implementation details, if a light with mixed cached shadows moves and the cached counterpart is not updated, the result will look wrong. In such cases either select the **Update on light movement** or the update mode to **OnDemand** and make sure an update is triggered when desired. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another important note, also due to implementation details, if a Light with mixed cached shadows moves and you do not update the cached counterpart, the result looks wrong. In such cases either enable the Light's Update on light movement option or set the Light's update mode to OnDemand and make sure to trigger an update when you move the Light.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some suggestions to the docs
Fixed up docs as suggested @JordanL8 |
1- Will fix, though it is on C++ side so it will be a bit of a mess :-) Will see for next release. 2- Several points to make here: The checkbox we absolutely need otherwise all cached shadows will be mixed and it is not what we want. We need to have a discrimination of the two types. Sometimes you are fine with dynamic stuff being rendered for one light and not for another and to differentiate you need a checkbox on the light. The checkbox on the renderer is engine side and it is going to be used by all SRPs, we cannot make it default (changing default behaviour) for HDRP usages. So while I agree, if it was hdrp only I would've made that on by default, we cannot really do that. 3- The static checkbox up there is lost at runtime, so it is unusable sadly. Again, the reason for the naming is due to it being a generic engine side thing and its implementation is generic to any Shadow map draw call that is done via SRP, so cannot really make it reference cached shadow maps. The tooltip is there to show a potential usage linking to what HDRP does. |
Thanks, added 4 and 5. |
4- I agree that it is a bit bad, but unfortunately we can't fix this case as we don't have a list of game objects that are in each state on C# nor easily in C++. If we ever will have scriptable culling then this could change at some point; as of now sadly not. 5- I think i know what's the issue! I am in vacation, but will check and fix when back. |
I disabled the directional light case, to make it work we need even more memory. Waiting for the RG to be main case to do that. Ping @iM0ve re the bug above on the directional light. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All issues fixed or addressed
…ters # Conflicts: # com.unity.render-pipelines.high-definition/Runtime/Lighting/Shadow/HDShadowAtlas.cs # com.unity.render-pipelines.high-definition/Runtime/RenderPipelineResources/HDRenderPipelineResources.asset
* Fix warning in ShaderPassDecal.hlsl * Tooltip for microshadows (#2100) * Update Alembic version to stop Alembic complaining * Disable quad overdraw on ps4 (#2107) * disable quad overdraw on ps4 * update doc Co-authored-by: sebastienlagarde <sebastien@unity3d.com> * Enable the DXR Vertex Format test for RG (#2022) * Add option to enable pure specular planar reflection (optimization) (#2105) * - Added a rough refraction option on planar reflections. - Added a rough distortion frame setting and and info box on distortion materials. - Added tests to cover the new features. * review changes * removed PerceptualRoughnessToMipmapLevel_LODFlag which isn't required. * clean more code (remove OutputSmoothPlanarReflection) * missing one update * removed rough distortion * remove distortion test scene * Update DistortionUIBlock.cs * clean distortion * update documentation * address doc feedback * Update Upgrading-from-2020.1-to-2020.2.md * Update Upgrading-from-2020.1-to-2020.2.md * update test 2220 * update smoothness test * Create 2220_SmoothPlanarReflection.png * update reference screenshots Co-authored-by: Anis <anis@unity3d.com> * Implementing scalabity settings for planar resolutions (#2059) * - Added a rough refraction option on planar reflections. - Added a rough distortion frame setting and and info box on distortion materials. - Added tests to cover the new features. * review changes * Added scalability settings for the planar reflection resolution. * support migration. * renamed the resolution parameters for the planar reflections * removed PerceptualRoughnessToMipmapLevel_LODFlag which isn't required. * clean more code (remove OutputSmoothPlanarReflection) * missing one update * removed rough distortion * remove distortion test scene * Update DistortionUIBlock.cs * clean distortion * update documentation * address doc feedback * Update Upgrading-from-2020.1-to-2020.2.md * Update Upgrading-from-2020.1-to-2020.2.md * update test 2220 * Revert "renamed the resolution parameters for the planar reflections" This reverts commit 753af88. * cleanup migration code * update smoothness test * Create 2220_SmoothPlanarReflection.png * some cleanup * Revert "Revert "renamed the resolution parameters for the planar reflections"" This reverts commit fbf3572. * update doc Co-authored-by: sebastienlagarde <sebastien@unity3d.com> * Remove useless SampleSkyTexture function * Fix errors when resizing the compositor's output and when removing/adding the compositor (#2118) # Conflicts: # com.unity.render-pipelines.high-definition/CHANGELOG.md * Remove BLEND keywords and replace with constant branch (#1884) * Removing blend keyword. * Changelog * Update DecalProperties.hlsl * revert change in AxF shader * fix compile issue with ordering when using VT * update comment * Update Upgrading-from-2020.1-to-2020.2.md * update comment + optimized code version (in case of bad compiler) * update comment revert (wrong) optimization * remove unused multicopmile in test * candidate fix for VFX * Revert "candidate fix for VFX" This reverts commit e3183f0. * Another tentative fix * Try differently * Fix compile issue. * Another vfx fix attempt. * Latest flavour of fix. * Remove old defines * Fix hybrid * Update includes in ray tracing * Update Upgrading-from-2020.1-to-2020.2.md Co-authored-by: Sebastien Lagarde <sebastien@unity3d.com> * Mixed cached shadow maps (Cached static + dynamic rendered every frame) (#1559) * UI for mixed cached shadows * Baby steps (# 1) * Baby steps (# 2) * Extrapolate the update request data into a function * Commit before blit code * Need to switch branch * Need to switch branch * Working as long the light does not move. * Fixed area light case * Make it render graph ready * Make sure we correctly update the freshly updated cached shadows * Raw update upon movement option (Missing API for threshold) * Threshold API * Add unity binary tag * New docs * Shader name change * Update docs * Fix bad merge * Update Shadows-in-HDRP.md * For now disable the directional light case. * Disable directional mixed. * Make it disabled under define * Remove docs * Implement rendergraph version * Remove superflous blit * Tentative fix for yamato. Co-authored-by: JordanL8 <lewis.jordan@hotmail.co.uk> * update meta file with wrong information Co-authored-by: Adrien de Tocqueville <adrien.tocqueville@unity3d.com> Co-authored-by: anisunity <42026998+anisunity@users.noreply.github.com> Co-authored-by: Anis <anis@unity3d.com> Co-authored-by: Pavlos Mavridis <pavlos.mavridis@unity3d.com> Co-authored-by: FrancescoC-unity <43168857+FrancescoC-unity@users.noreply.github.com> Co-authored-by: JordanL8 <lewis.jordan@hotmail.co.uk>
IMPORTANT: Requires this C++ PR https://ono.unity3d.com/unity/unity/pull-request/110280/_/graphics/concept-of-static-shadow-caster-for-SRP . Whenever that lands I will bump minimum required version of HDRP.
This PR introduces two features.
The biggest feature is
Mixed cached shadow maps
It is now possible to tag objects as Static Shadow Casters (with the C++ PR above). Selecting the new option Always draw dynamic on the shadows, it is possible to have all static objects cached and dynamic objects rendered on top every frame.
See the example in the gif, all pillars are marked as static (when moved the shadow is not updated) and the dancing dude is not. You can see how its shadow is updated every frame while the rest of the shadows are not.
This will allow the cached shadows to be used in many more use cases. Lots of games have static environments but few movable characters and objects, so before those couldn't use cached shadows, but now can for significant perf benefits (both CPU and GPU as most of the objects will not be rendered anymore in shadows).
Shortly, this work rendering first all static in cached atlas when an update is required, then blit from cache to dynamic atlas and subsequently every frame the dynamic objects are rendered on top of the blitted cached shadows.
Second feature is:
Update upon light movement
There is now a new option to shortcut a usual use case for OnDemand. This will now trigger an update every time a light moves above a certain threshold set via script (by default really small).
This helps for use cases when a light almost never moves, but you want to update when it does move.
Note: Rendergraph has not been updated, need a bit of a chat with @JulienIgnace-Unity to make sure of a change I need to do.
What have I tested: I tested what you can see in the gif, all the light types for both new options. I also tried when the dynamic atlas is full and the mixed cached shadows still work.
Still I'd love thorough testing on this since I changed a few fundamental things about what determines shadow rendering options.