Having gone into it deeper I’ve found that the code that computes scene velocity (when the velocity in the texture from moving objects is 0) is incorrect. The code they run in that case to compute the velocity of static objects w.r.t. camera motion is this:
// THIS CODE FROM UE4 PRODUCES INCORRECT VELOCITY
float4 ThisClip = float4( UV, Depth, 1 );
float4 PrevClip = mul( ThisClip, View.ClipToPrevClip );
float2 PrevScreen = PrevClip.xy / PrevClip.w;
Velocity = UV - PrevScreen;
Which produces the incorrect output like I posted above if you run that code in a Custom
material node. The correct code they should be running (as found in Chapter 27 of GPU Gems 3) is this:
// Inputs to our custom node
float2 texCoord = UV;
float depth = Depth;
float3 WorldPosition = AbsoluteWorldPosition;
/**
Code From GPU Gems 3 - Chapter 27 Motion blur post processing effect:
https://developer.nvidia.com/gpugems/gpugems3/part-iv-image-effects/chapter-27-motion-blur-post-processing-effect
*/
// Get the depth buffer value at this pixel.
float zOverW = depth;
// H is the viewport position at this pixel in the range -1 to 1.
float4 H = float4(texCoord.x * 2 - 1, (1 - texCoord.y) * 2 - 1, zOverW, 1);
// make homogeneous coords for world position
float4 worldPos = float4(WorldPosition, 1.0);
// Current viewport position
float4 currentPos = H;
// Use the world position, and transform by the previous view-projection matrix.
float4 previousPos = mul(worldPos, View.PrevViewProj);
// Convert to nonhomogeneous points [-1,1] by dividing by w.
previousPos /= previousPos.w;
// Use this frame's position and last frame's to compute the pixel velocity.
float2 velocity = (currentPos - previousPos)/2.f;
// return depth / 100.0 to convert from centimeters (UE4 coords) to
// meters
return float4(depth / 100.0, velocity.x, velocity.y, 1.0);
Note: the main thing they seem to be doing incorrectly is coverting between clip spaces of the two cameras when they should in fact be converting between view spaces of the two cameras.
As can be seen in the discussion on this thread (specifically, this post )where I’ve been tracking my investigation into this issue, changing to this code in a custom node produces the correct velocity / motion vectors for the pixels in the scene. As i don’t see a ViewToPrevView function in FViewUniformShaderrParameters I will see what modifications to the engine are required to
- add
ViewToPrevView
convenience matrix, and - update their velocity calculation code to produce correct data for the velocity texture.