We are making a game with relatively fast camera movement, and want more predictable performance from VSM. One of the ideas we’re thinking of exploring is to dynamically scale VSM resolution with respect to camera movement. Some ideas we had was to estimate tile churn from measuring camera rotation per frame, or measuring the amount of tile churn/invalidation per frame and reduce VSM resolution based on that. Or some portaling system that would help with rapid camera movement through enclosures or other level designs that could cause full screen re-renders of a VSM
Would you have any concerns about doing something like this that we should be aware of? Or does anyone have experience with similar VSM scaling ideas against fast camera movement
thanks for reaching out. The VSM tile cache invalidation with rapid camera movement is somewhat similar to having a continuous time of day, which invalidates all cached pages for the directional light. The following UDN cases may provide some ideas on how to amortize the cost of updating many VSM pages at once:
The official Epic documentation on VSM also mentions “In a future release, caching should improve by adding a priority system and per-frame update budgets to allow finer control over the cost of rendering shadows. For example, allowing shadow resolution to temporarily lower in cases where too many pages need updates”, so the dynamic resolution approach is something Epic is planning to implement as well.
Hopefully that helps. Please let me know if you have any further questions.
I checked the public roadmap, but could not find a timeline indicating when this optimization is planned. However, both 5.5 and 5.6 include performance optimizations to the virtual shadow map system, so it may be worth upgrading your project to a newer version if that’s an option.
If not, adjusting the VSM resolution dynamically by changing r.Shadow.Virtual.ResolutionLodBiasDirectional (or r.Shadow.Virtual.ResolutionLodBiasLocal) at runtime based on measured camera motion should work, keeping in mind that changing this value at runtime can impact performance, especially if you are frequently adjusting it or using very low bias values that significantly increase shadow map resolution. Also, lowering the ResolutionLodBiasDirectional value increases the resolution of virtual shadow maps, which can lead to a VSM page pool overflow if not managed carefully.
I hope that helps, but let me know if you have more questions.
as far as I can tell, it’s not possible to pregenerate VSM tile caches if the camera moves in unpredictable ways, but Unreal 5.4 has a feature called Separate Static Caching which optimizes cache invalidation behavior for static geometry (please see this link for details on how to benefit from this feature).
Regarding implementing the dynamic shadow resolution idea, I would measure the difference in degrees in the Z-direction between the previous and current frame (or equivalent for translation in the XY plane) and dynamically set the value of r.Shadow.Virtual.ResolutionLodBiasDirectional (or r.Shadow.Virtual.ResolutionLodBiasLocal depending on the type of light) each frame within a certain clamped range e.g. from -0.5 for still camera to 3 when the camera is rotating quickly, based on the degree of movement.
Could you also check if your scene contains a SceneCaptureComponent2D as that may cause cache invalidations when rotating the camera according to this thread (this may or may not be related to the issue you are seeing).
Thanks for the response. I think that WRT the TOD technical solutions, the solutions that affect TOD are slightly different as delaying the clipmap updates won’t apply since with rapid camera translation or rotation you can’t guarantee that any of the tiles will be preserved in the next frame. That’s sort of why I was thinking of tying the resolution to camera rotation,and its a fairly simple implementation. Would you have any suggestions on how we could pregenerate or cache any VSM tiles, or implementation ideas for a dynamic VSM resolution WRT to this kind of camera movement?