We have found that during a game pause objects that are animated with WPO cause motionblur-like artifacts if they are mid motion the moment the game is paused.
This happens even when the motion blur pass is disabled by setting CVars such as
r.MotionBlurQuality 0
r.MotionBlur.Amount 0
If the game is “paused” by causing extreme slowdown these artifacts do not occur, however this is not a viable workaround for us as it causes physics glitches.
The problem seems to lie with Unreal Engine TSR, we don’t get the same issues when rendering with DLSS for example. The blur amount seems to be somewhat proportional to the amount of upscaling used. (hence the `r.ScreenPercentage 66` command).
When testing various r.TSR cvars we couldn’t find a setting that solves this issue.
We checked some frames in Pix for Windows and found a UAV texture called TSR.Velocity.HoleFilled : DilatedVelocityOutput in the first TSR postprocessing pass which seems to have motion vectors that correspond to the amount of artifacts in the frame. This is despite the fact that we moved the camera since pausing the game, which seems to indicate that objects with WPO emit motion vectors as if the game hadn’t been paused.
I am not seeing the attached project. Do you mind to reshare it? TSR does try to help generate the velocity texture used for motion blur for performance reason. If you find this artifact troublesome, you could try `r.MotionBlur.AllowExternalVelocityFlatten 0` to disable TSR to flatten the veloctiy texture and rely on the one in the motion blur instead.
Glad you have find a solution to stop the motion blur. I was able to run your level and see that the WPO material does output velocity. This causes confusion to TSR that relies on motion vector. DLSS has an optical flow component inside to correct motion vectors, so it is expected to not cause blurring. We have fired an internal JIRA and try to properly address it without adding the complexity in the shader.
[Image Removed]No WPO animated geometries should have detected the game stop and not updating and using the previous frame position to calculate velocity. If it does, there might be a bug somewhere. Would be much appreciated if you have a repro for this condition.
I’ll try to re-upload the ZIP with the repro, very sorry for that, not sure where it disappeared when we created the post.
As an update, when we pause the game, we have different kinds of problems:
Nanite or non-Nanite using WPO was motion-blurry (demonstrated in the Vanilla UE5.6 repro)
Groom assets with skinning binding are motion-blurry. Skinned mesh assets are fine, though.
For the WPO, I managed to understand it fully. In our case, we were using expressions like sin(Time) and your material expression builder within the shader compiler duplicates the whole material graph for WPO in order to get the previous frame WPO, replacing all time expressions with previous frame times.
This simply isn’t pause-aware, so our fix is in SceneView.cpp - detect “World->bIsCameraMoveableWhenPaused && World->IsPaused()” and replace ViewUniformShaderParameters.PrevFrameGameTime and PrevFrameRealTime with the current times, so they’re the same. Fixed.
For our other character assets (such as grooms used for hair with skinning binding, or for chaos-enabled clothes), not demonstrated in this repro, the situation is a bit more complicated, because the previous frame positions are stored inside of the vertex buffer. I have a partial fix where in VelocityShader.usf - detect the pause and take TranslatedWorldPosition instead of PrevTranslatedWorldPosition.
This isn’t perfect and I’d love to hear from you guys what you think could be missing when we pause the game, because the previous frame’s vertex positions still dwell in the vertex buffers, even when paused, but only for certain types of assets.
The solution was to set WorldIsPaused on this condition: World->bIsCameraMoveableWhenPaused && World->IsPaused() in C++, and then in shaders to add the proper checks and use the current frame transforms or vertex data. It was multiple shaders:
HairCardsVertexFactory
GpuSkinVertexFactory
NiagaraSpriteVertexFactory
NiagaraMeshVertexFactory
Plus Nanite WPO, as said above. None of them were pause-aware.
It took us some time to find all the places that showed a glitch.
I hope this helps your team fix it in a near future release, or others should they run into a similar pause issue.