Skip to content
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

Add motion_draw_disabled render_mode to Spatial Shaders. #77523

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

EMBYRDEV
Copy link
Contributor

@EMBYRDEV EMBYRDEV commented May 26, 2023

This PR adds a new motion_draw_disabled render_mode that allows materials to skip drawing motion vectors.

This is required for post processing effects to play nicely with TAA. It also can help with the appearance of some translucent materials.

There are currently two methods of doing post processing:

  • A quad with a vertex shader positioning it infront of the camera.
    This works well with the editor camera however with TAA enabled the whole scene appears to shake.
  • A quad as a child of the players camera.
    This solves the shaking issue however the motion vectors are no longer accurate, leading to horrible artifacts.

With this render_mode enabled post processing effects such as this outline get properly antialiased and remain crisp in motion.

Clipboard - May 26, 2023 3 21 PM

TODO: Expose to BaseShader3D

@EMBYRDEV EMBYRDEV requested a review from a team as a code owner May 26, 2023 16:06
@Calinou Calinou added this to the 4.x milestone May 26, 2023
@EMBYRDEV EMBYRDEV force-pushed the motion-draw-mode branch from 6ebdf25 to 7c5a575 Compare May 27, 2023 00:44
@EMBYRDEV
Copy link
Contributor Author

EMBYRDEV commented Jun 2, 2023

@JFonS any other blockers?

@EMBYRDEV EMBYRDEV requested a review from a team as a code owner June 2, 2023 07:28
@EMBYRDEV EMBYRDEV force-pushed the motion-draw-mode branch from 023fbb7 to f2220c7 Compare June 2, 2023 07:29
@EMBYRDEV
Copy link
Contributor Author

EMBYRDEV commented Jun 2, 2023

I have now exposed this to BaseMaterial3D.

@EMBYRDEV EMBYRDEV force-pushed the motion-draw-mode branch from f2220c7 to 3504b35 Compare June 2, 2023 07:32
Copy link
Contributor

@JFonS JFonS left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks.

@clayjohn clayjohn modified the milestones: 4.x, 4.2 Jun 8, 2023
@YuriSizov
Copy link
Contributor

@EMBYRDEV Could you please rebase against the master instead of merging it into your branch?

@EMBYRDEV EMBYRDEV force-pushed the motion-draw-mode branch from 9c00cd1 to b267aed Compare July 7, 2023 20:45
@EMBYRDEV
Copy link
Contributor Author

EMBYRDEV commented Jul 7, 2023

@EMBYRDEV Could you please rebase against the master instead of merging it into your branch?

Done!

@YuriSizov YuriSizov requested a review from clayjohn July 16, 2023 12:26
@EMBYRDEV
Copy link
Contributor Author

Is there anything else needing done before looking at getting this merged?

@Calinou
Copy link
Member

Calinou commented Jul 16, 2023

Do you have a test project available to make sure this PR works as intended? I'd like to test this locally. This can be a scene with your post-processing shader setup.

@EMBYRDEV
Copy link
Contributor Author

@Calinou omg, I put it in my recycle bin last week and never got around to emptying it... lucky. 🤣

Here is a google drive link for the scene in the screenshot.

Both the post processing shader and the smoke on the torches have this render mode enabled. Remove the render mode to see the default behaviour of the engine prior to this PR.

Copy link
Member

@Calinou Calinou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally (rebased on top of master 851bc64), it works as expected.

Both videos were recorded with the engine FPS capped at 30.

Without motion_draw_disabled on the post-processing shader

simplescreenrecorder-2023-07-17_03.31.59.mp4

With motion_draw_disabled on the post-processing shader

simplescreenrecorder-2023-07-17_03.32.08.mp4

Documentation looks good to me too.

One question that may arise in the future is how we'll want to extend this once FSR 2 support is added. FSR 2 recommends creating a manually computed reactive mask, as well as a transparency & composition mask. This will probably need separate output variables and render modes to handle.

@YuriSizov
Copy link
Contributor

Is there anything else needing done before looking at getting this merged?

Clay needs to give it a review as the rendering lead. I asked and he said that he'd like to take a look.

@EMBYRDEV
Copy link
Contributor Author

Rebased :)

@clayjohn any chance this can make it in for 4.2?

@clayjohn
Copy link
Member

Yep, its tagged for "4.2". I just need to give it a review

Copy link
Member

@clayjohn clayjohn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks mostly good. It is a fairly simple change, but it seems necessary for implementing certain effects that should bypass motion vectors.

I suggest that, instead of using a render_mode_define you instead just select the non-Motion_Vector shader variant instead. Right now, this code compiles the following shader variants:

  1. #define MOTION_VECTORS \n #define MOTION_DRAW_DISABLED
  2. #define MOTION_VECTORS
  3. #define MOTION_DRAW_DISABLED
  4. ""
    But since MOTION_DRAW_DISABLED only serves to disable MOTION_VECTORS, we can get by without it.

Further, at draw time, we dynamically select our shader variant, based on whatever settings we choose. So instead of adding a new define, you can just avoid asking for the Motion Vector shader variant here:

if constexpr ((p_color_pass_flags & COLOR_PASS_FLAG_MOTION_VECTORS) != 0) {
pipeline_color_pass_flags |= SceneShaderForwardClustered::PIPELINE_COLOR_PASS_FLAG_MOTION_VECTORS;
}

Additionally, since the setting is a render_mode, at shader compile time, you know you will never select the TAA version, so you can just avoid compiling it by doing an early out here: https://github.com/godotengine/godot/blob/41dca2cbbeeb96c41aacbc7b0ef5c15c4f8dbfdf/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp#L343-L345

I think using this approach both fits better with the current architecture and will be ideal with our plan to split the opaque render pass into two phases (1 with motion vectors and one without)

@akien-mga
Copy link
Member

@EMBYRDEV Are you able to do the changes suggested by @clayjohn?

@EMBYRDEV
Copy link
Contributor Author

@clayjohn is it worth me reworking this PR in the next week or so, or should I wait until #81197 has had some time in the oven?

@clayjohn
Copy link
Member

@clayjohn is it worth me reworking this PR in the next week or so, or should I wait until #81197 has had some time in the oven?

I would save your time! I have a gut feeling this PR is still needed. But I don't have a specific use case in mind other than disabling motion vectors for objects in the transparent pass. So better to wait and see and avoid doing work in case it turns out to be unnecessary.

@YuriSizov YuriSizov modified the milestones: 4.2, 4.3 Oct 2, 2023
@RPicster
Copy link
Contributor

Just to add some more feedback. I have a lot of problems with motion vectors on transparent materials with TAA.
While using this flag will have the drawback of destroying smaller particles, it is very needed for a lot of effects. TAA often introduces weird artefacts at the edges of transparent particles/quads. Is it planned to also add this flag to the StandardMaterial3D or just just in shaders?

@EMBYRDEV
Copy link
Contributor Author

Is it planned to also add this flag to the StandardMaterial3D or just just in shaders?

This PR does expose the setting to StandardMaterial3D too. Just need to get some free time to rebase this PR if @clayjohn believes there is still a use case for this?

@clayjohn
Copy link
Member

Just to add some more feedback. I have a lot of problems with motion vectors on transparent materials with TAA. While using this flag will have the drawback of destroying smaller particles, it is very needed for a lot of effects. TAA often introduces weird artefacts at the edges of transparent particles/quads. Is it planned to also add this flag to the StandardMaterial3D or just just in shaders?

It depends. As of 4.2, we never write motion vectors when using transparent materials. So if your need is just for disabling TAA on transparent materials, then it will be fixed in 4.2 without this PR.

If you are using one of the 4.2 betas, and are still having issues with transparent materials, then this PR won't help you.

If you need to disable motion vectors for another reason, then we can move forward with this PR. Basically this PR is just waiting until someone finds a need for it.

@PhilipWitte
Copy link

I want to add that this issue with Motion Vectors also applies to more than just post-processing effects. I've been working on a terrain system with polygons that follow the Camera as it moves (in unit steps), the motion vectors used for FSR 2 cause a lot of artifacts when the ground shifts position. I've included videos below to illustrate the issue:

No Upscale + FXAA (baseline, no artifacts):
https://github.com/godotengine/godot/assets/1392440/0254a1d2-8130-4322-97b1-43c24e085935

Upscale (0.5 renderscale) + FSR 2
https://github.com/godotengine/godot/assets/1392440/2f7990ac-7ed6-489f-a4be-cedfb364bb48

As you can see, FSR2 looks great while still.. but in motion these artifacts essentially make it unusable with this terrain technique without the ability to disable motion vectors. So I would love to see this render_mode motion_draw_disabled option added in the future, and would even suggest including an additional motion_draw_custom option in the future. That would allow shaders to output their own screen-space motion vectors explicitly, as any "one size fits all" solution will likely have performance/memory trade-offs and may still be unusable in some situations (such as ray-marched clouds, or other visual effects) where doing motion calculations in the shader is basically the only practical solution.

@EMBYRDEV
Copy link
Contributor Author

EMBYRDEV commented Nov 19, 2023

I want to add that this issue with Motion Vectors also applies to more than just post-processing effects. I've been working on a terrain system with polygons that follow the Camera as it moves (in unit steps), the motion vectors used for FSR 2 cause a lot of artifacts when the ground shifts position.

Can you try this PR out and confirm that it does indeed help with your issue? I'm not convinced that using this shader flag on a large portion of the screen with an opaque material wont lead to smearing artifacts. Although, with motion vector passthrough, if we ever address #67332 then the sky might help some of those issues.

@PhilipWitte
Copy link

PhilipWitte commented Nov 20, 2023

Can you try this PR out and confirm that it does indeed help with your issue?

I copied my Godot repo (up-to-date with master) and fetched this PR... however while the new motion_draw_disabled render_mode option is there... FSR 2 itself is not. I'm assuming this PR is from before FSR2 was added into master, but without FSR2 it's hard to test. While TAA does seem to have some subtle artifacts due to motions-vectors... it's not noticeable enough for me to do valid comparison. Certainly no where near the very obvious "fuzzing" FSR2 artifacts.

I tried merging in master.. but there's 5 different conflicts I'm not going to try and resolve myself. If there's an update to this PR with those issues resolved, ping me and I'll try again.

@EMBYRDEV
Copy link
Contributor Author

@clayjohn I can confirm that this is still required as of 4.2rc1 With FSR2 enabled the problem isnt as pronounced but if you have FSR disabled and TAA enabled then we do still need this for post processing effects.

I'll take some time soon to rebase this against master to aim for 4.3.

@EMBYRDEV EMBYRDEV force-pushed the motion-draw-mode branch 2 times, most recently from b094690 to 412d6ed Compare November 25, 2023 13:19
@EMBYRDEV
Copy link
Contributor Author

EMBYRDEV commented Nov 25, 2023

I have rebased against master and this should be safe to merge now.

As for @clayjohn's suggestion of switching the shader variant instead of using the define, this actually causes a problem as the rest of the pipeline seems to expect the shader to still have the vector in it's output layout.

#ifdef MOTION_VECTORS
layout(location = 2) out vec2 motion_vector;
#endif

And since we don't check for the disabled flag here it works nicely. If you have any suggestions on how best to handle this then I'll be happy to implement but this seems like the most streamlined solution.

@EMBYRDEV EMBYRDEV requested a review from clayjohn December 13, 2023 18:16
@DarioSamo
Copy link
Contributor

DarioSamo commented Dec 19, 2023

As you can see, FSR2 looks great while still.. but in motion these artifacts essentially make it unusable with this terrain technique without the ability to disable motion vectors. So I would love to see this render_mode motion_draw_disabled option added in the future, and would even suggest including an additional motion_draw_custom option in the future. That would allow shaders to output their own screen-space motion vectors explicitly, as any "one size fits all" solution will likely have performance/memory trade-offs and may still be unusable in some situations (such as ray-marched clouds, or other visual effects) where doing motion calculations in the shader is basically the only practical solution.

I don't think disabling the motion vectors would result in any different result at all in your use case here: motion vectors are not generated for static geometry in the first place and are derived from depth buffer and the camera movement.

It sounds to me like your second suggestion is the one that applies the best: being able to output motion vectors value from the shader. I've suggested as much but it sounds like it'd have to be added by modifying parts of Godot I haven't really looked into yet (shader compiler, the shader template acknowledging the new shader variable, permutations, etc).

@PhilipWitte
Copy link

motion vectors are not generated for static geometry in the first place and are derived from depth buffer and the camera movement.

Yes I figured, but keep in mind the ground is not actually static, but a mesh which moves along with the camera at distinct unit steps. In between those steps things look fine, it's only for a split second after each "step" (where the ground actually shifts position) where the artifacts occur.

That being said, I agree that ultimately just disabling motion vectors might not fully solve everything here, as other parts (like portions of the grass) will do the same thing as the ground (in terms of following the camera), but also sway with the wind, and so dynamically move each frame. Ultimately having the ability to output correct motion vectors may be the only way to eliminate artifacts (tho for the most part it looks fine until the large snap happens).

@TokisanGames
Copy link
Contributor

Terrain3D has issues with TAA/FSR. Like Phil, our terrain is a clipmap. The meshes follow the camera and the vertices move potentially every frame. I'd like a method to disable motion vectors on the terrain while allowing the user to have them for the rest of their scene. Or a method to clear, overwrite or insert an inverted motion vector so these modes are usable.

Downstream issue
TokisanGames/Terrain3D#302

@EMBYRDEV
Copy link
Contributor Author

So I havent tested the new CompositorEffect API but I imagine that removed my usecase for this PR, being PostProcessing shaders that play nicely with AA.

That being said this may still be useful for some particle types where smearing is desired over rippling effects (EG. Small smoke particles & sparks)

As for Terrain3D I have a feeling that enabling this mode would potentially lead to the terrain itself becomign a smeary mess.

@TokisanGames would you be able to give this PR a test to see if this actually solves your issue or if we need a differing approach?

@akien-mga akien-mga changed the title Add motion_draw_disabled render_mode to Spatial Shaders. Add motion_draw_disabled render_mode to Spatial Shaders. Aug 19, 2024
@TokisanGames
Copy link
Contributor

I built this PR rebased off of the 4.2 branch. With TAA enabled on my 3070, motion vectors are mostly calculated correctly, with flickering only in some areas. This PR does disable motion vectors, but it turns my terrain into a blurry mess.

TAA

godot.windows.editor.x86_64_exIgOdNXk9.mp4

TAA Motion Vectors

godot.windows.editor.x86_64_lZcMtSnwEc.mp4

TAA Motion vectors disabled

godot.windows.editor.x86_64_SnNx7EOyAz.mp4

@EMBYRDEV
Copy link
Contributor Author

Ahh looks liek this isnt the solution to your problem. I think it is still super important to expose the ability to passthrough motion vectors from behind the object as some large billboard sprites like lens flares can cause big problems with TAA but I think in addition to this we need to expose a way to write custom motion vectors from shader.

I'll get this rebased and implement feedback soon so that this can make it in for 4.4 sorry for the delay.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

TAA causes jittering with "Advanced Post-Processing"
10 participants