godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
88.64k stars 20.1k forks source link

FSR2 viewport 3D scaling mode overrides velocity render layer values #94126

Open sphynx-owner opened 1 month ago

sphynx-owner commented 1 month ago

Tested versions

v4.3.beta2.official https://github.com/godotengine/godot/commit/b75f0485ba15951b87f1d9a2d8dd0fcd55e178e4

System information

Windows 10 - Godot v4.3.beta https://github.com/godotengine/godot/commit/16f98cd7079c2b22248ec358371f17bca355e42e

Issue description

This comes from testing the motion blur implementation made by me and the one made by @wojtekpil. When FSR2 interpolation is enabled, the debug view reveals that the velocity render layer (showed at the top right) gets flushed to values of (1, 1) and above, evident by the yellow color the across the velocity texture and the tone mapping dimming the entire screen when those textures are displayed, while keeping the original velocity values for some foreground elements like the player and street sign in that case. This results in extreme diagonal constant smear of the environment when the blur effect attempts to use it even when no motion is being performed like in the images below.

image

image

Steps to reproduce

  1. download and open the demo at https://github.com/sphynx-owner/JFA_driven_motion_blur_demo
  2. go to Resources/ScalabilitySettings.tres, double click it, and in the Normal setting resource, set the Scaling parameter to Viewport Scaling 3D Mode Fsr2
  3. press play, and then Z to enable the debug view
  4. look at the sky and keep it in view while looking around to see that is does not feed to the velocity buffer displayed at the top left, and thus does not get blurred.

Minimal reproduction project (MRP)

https://github.com/sphynx-owner/JFA_driven_motion_blur_demo

Calinou commented 1 month ago

cc @DarioSamo

DarioSamo commented 1 month ago

This is not a bug.

Motion vectors are not written for objects that don't move and instead are derived from depth using the following code.

https://github.com/godotengine/godot/blob/master/servers/rendering/renderer_rd/shaders/effects/motion_vector_inc.glsl

The effect must also implement this using the same reprojection matrix the renderer uses.

darksylinc commented 1 month ago

Dario explained the what without the why.

To put it another way, FSR2 (and any modern upscalers like DLSS) fundamentally requires motion vectors for everything. It's how it works and by design. Therefore enabling FSR2 means anything not having velocity motion vectors will be overridden to have one. Trying to workaround this requirement means FSR2 will start to glitch and malfunction.

DarioSamo commented 1 month ago

Dario explained the what without the why.

To put it another way, FSR2 (and any modern upscalers like DLSS) fundamentally requires motion vectors for everything. It's how it works and by design. Therefore enabling FSR2 means anything not having velocity motion vectors will be overridden to have one. Trying to workaround this requirement means FSR2 will start to glitch and malfunction.

Our FSR2 implementation is patched to use the code I linked above to derive the motion vector from depth when it's an invalid value. The standard implementation requires for the texture to be like the OP expects, but we modified it due to applying an optimization to reduce the amount of data written out during the regular render pass with static geometry.