Rendering motion vectors?

HDRP can render motion vectors for objects that it deems eligible (objects that force 0 motion, objects that moved, etc.). The rest of the motion vectors are computed by a full screen pass for objects that didn’t move at all or have their motion vector flag set at camera motion only.

That’s all cool and good. However, I am very confused by how SRP determines which objects are eligible for motion vector rendering and which are not.

This is the code from HDRP that instructs Unity to render objects that are eligible for motion vector rendering. I see no apparent instructions that force Unity to skip ineligible objects. RenderList struct and the DrawOpaqueRenderList function also don’t have them.

Moreover, there is also an _ADD_PRECOMPUTED_VELOCITY keyword in shaders that makes them write proper motion vectors from vertex displacement or alembic even if the object never moves. This is all very confusing and I completely do not understand how HDRP forces Unity to render only eligible objects during the motion vector pass, both based on the flags and the material keywords.

Can anyone from the staff please clarify this matter? Thank you.

It happens on the c++ side if i had to guess.

I found something useful here How to correctly render the motion velocity buffer with SRP?
Although the link in this post is broken. But I finally work out that, you need to disable the motion vector pass with material.SetShaderPassEnabled for all the materials of motion vector objects. And the proper way is to override the defaultMaterial property in your RenderPipelineAsset, and write a custom editor for your shader, so that you can disable the velocity pass for all materials being created.
The associated code in HDRP can be found here → Graphics/com.unity.render-pipelines.high-definition/Editor/Material/PBR/HDPBRLit.cs at 56eb1c3bf66ec9b939716e7199284909f6208a93 · Unity-Technologies/Graphics · GitHub

1 Like

Sorry for leaving this thread, but yeah, that would be exactly right. You would need to set the MotionVector pass as a disabled one in materials’ properties, only then the pass will be used if a renderer moves. It’s quite counterintuitive and brought a bit of a trouble in our project, mainly because we integrated our custom SRP quite late in the development cycle and now we have to deal with globally updating the hidden material properties for our old materials.

Wonder why the built-in renderer didn’t need such a thing though, don’t think I ever saw that pass being disabled in the hidden properties of standard shader materials.

maybe some code in c++, they do this