October 24, 2024

Implementing a Motion Vectors Pass for Post-processing

New Evergine version Motion vectors are an essential component when working with post-processing techniques like Temporal Anti-Aliasing (TAA) and Motion Blur. In Evergine, a motion vectors pass allows the GPU to track the movement of objects and pixels between frames, enabling smoother visual effects.

What Are Motion Vectors?

Motion vectors store information about how each pixel moves from one frame to the next. This is crucial in Evergine post-processing techniques like TAA, where the algorithm accumulates samples over multiple frames to reduce aliasing artifacts, using the motion vector texture to track the previous pixel location.

Similarly, Motion Blur effects simulate the streaking of moving objects based on their velocity across the screen. Both these effects rely heavily on accurate motion vectors to calculate the appropriate visual adjustments.

Upgraded Render Path to accommodate Motion Vectors

In our default Render Path, Evergine uses Forward Rendering system. However, it also needs some additional passes for storing useful information for post-processing. Until now we were using an initial render pass (ZPrePass) for generating a texture with depth, metalness and roughness information. The need of generating motion vectors texture made us reorganize the Render Path for clarity and efficiency. Next diagram explains the changes:

ZPrePass

Now the ZPrePass stage only has one texture:

NameFormatDescription
DepthD24S8Depth and Stencil information. Useful in plenty of postprocessing effects.

Figure 1 DepthStencil texture

GBuferPass

We have removed the previous Distortion stage and created a new MRT (Multiple Render Target) pass using more frame buffers, embedding the previous information with the new Motion Vector texture.

TextureFormatDescription
RT 0R8G8B8A8_UnormStores multiple information:

–            R, G: Normals, used in SSAO and SSR.

–            B: Roughness, used in SSR

–            A: Metalness, used in SSR.

RT 1R16G16_FloatThe new Motion Vector texture. It stores the X and Y velocity of the pixel in screen space. Used in Temporal Antialiasing and Motion Blur post-processing.
RT 2R8G8B8A8_UnormContains the distortion information for the Distortion post-processing effect.

 

Figure 2 Motion Vectors texture clamped into a normal RGB texture

Figure 3 Normals, roughness, and metalness texture

DefaultPass

With no changes from the previous version, this is the main pass where all the objects are rendered into the scene with Forward lighting and PBR, using the previous passes when needed. Its textures are:

NameFormatDescription
ColorR16G16B16A16_Float HDR texture with the color in linear space.
DepthD24S8Texture with the final depth and stencil.

Figure 4 Color texture (before post-processing), in linear color

 

Once the post-processing is applied and the color is corrected into gamma space, we have the final result.

Changes in the engine

Adding the motion vector feature in Evergine made us add the following changes in the engine:

  • Transform3D stores the previous frame World matrix (PreWorld )for allowing to reconstruct the previous pixel position.
  • SkinnedMeshRenderer now keep the positions of all the vertices of the previous frame.
  • Effects now have a new Metatag for accessing previous frame matrices [PreWorld].
  • In case of skinned mesh, the vertex position of the previous frame will be stored into the syntax Position1 (While in Position_0 will be current frame position, as usual).
Antonio avila
Author
Antonio Ávila
Plain Concepts Research

Wait! Don't leave yet.

Sign up for our monthly newsletter to be updated on all the latest news, case studies, and more.

We don't send spam and you can unsubscribe at any time.