SetGamePaused / APlayerController::SetPause() causes MotionBlur-like artifacts on Objects animated with WorldPostionOffset even if motion blur is disabled

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.

[Image Removed]

We have implemented the suggestion in this thread, and it has significantly reduced artifacts in the editor however the motion blur issue persists: https://forums.unrealengine.com/t/set-game-paused-horrible-rendering-artifacts/91249/6

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.

Steps to Reproduce

  • Run the attached project, open Lvl_ThirdPerson in the editor (or create a level in which objects are animated with WPO and the game can be paused)
  • Run game through PIE or as a standalone game
  • enter `r.MotionBlurQuality 0` in the console
  • enter `r.ScreenPercentage 66` in the console
  • game pause has been mapped to the characters jump, so to view the problem:
    • walk to the mannequin that has their torso animated through WPO
    • run towards it and “jump” while the torso is in mid motion and ideally taking up significant space in the screen
    • Observe artifacts on the torso
    • enter `ToggleDebugCamera` in the console
    • Observe that the artifacts persist even when the camera angle changes

[Image Removed]

Hi Leah,

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.

Hope it helps.

Tiantian

Hi Pavel,

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.

Thanks,

Tiantian

Hi Pavel,

Thanks for providing the detailed information. I have added it to the JIRA.

Best,

Tiantian

Hey Tiantian, thanks.

“r.MotionBlur.AllowExternalVelocityFlatten 0” doesn’t solve our problem, unfortunately.

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.

Pavel

Hey Tiantian, we managed to fix it on our end.

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.

Have a fine day,

Pavel