Post 107

Motion Vectors Clock In

Temporal anti-aliasing is now on by default, and it finally reads the per-object motion vectors the renderer has been producing all along. Spinning, sliding, and skinned things get smooth edges instead of ghost trails. You change nothing; your edges just stop being staircases.

Every frame, for months, the renderer has computed exactly where every object moved since the previous frame and written it into a texture. Also every frame, for months, it has thrown that texture away. A prepass rendered per-object motion vectors with nowhere to go, while the anti-aliasing pass next door squinted at the depth buffer and guessed. The guess was fine for a parked camera. Point it at anything that moves and the history landed in the wrong place, the rejection clamp mopped up what it could, and fast objects wore a 43 percent surcharge of smeared trail pixels like a comet costume.

This release introduces the two systems to each other.

What changed in your patches

Nothing, which is the point. TAA is now on by default for every RenderScene. Your existing patches load unchanged and render with smooth edges: the instanced grid test scene drops 94 percent of its hard stair-step edges the moment history converges, with no blur catastrophe on the other side of the ledger (there is a gate that checks for that too, because “fewer hard edges” describes both anti-aliasing and vaseline).

For moving content, the resolve now reprojects each geometry pixel through its actual motion vector, camera motion and object motion both, including the rigid part of skinned characters. The regression gate spins a bar at exactly three degrees per frame for 240 frames and then counts pixels of ghost residue outside the bar’s true silhouette. The count is zero. Not reduced, not within budget. Zero.

Sky pixels keep the old depth-based reprojection, since the sky has no motion vectors and, helpfully, also no geometry to ghost.

The jitter bookkeeping

TAA works by nudging the camera a sub-pixel amount each frame in a Halton pattern and averaging the results, which is a polite way of supersampling over time. The motion vectors are rendered with that nudge baked in, so the resolve has to subtract the previous frame’s nudge before fetching history, or every fetch lands slightly drunk. The node now remembers its previous jitter alongside its previous camera matrix, and the algebra cancels where the textbooks say it should. We checked the sign twice. It mattered.

If you need pixel-exact single-frame captures, the taa_enabled pin still exists and still turns everything off, jitter included. For everything else, the renderer was already doing the work. Now it keeps the result.

← All posts