Primer 10 — Deep dive
過去のフレームを借りる技術と、その代償 / temporal antialiasing

TAA / TSR の副作用

TAA(時間的アンチエイリアス)と TSR(時間的スーパー解像度)は、今のフレームだけでは足りない情報を、過去のフレームから借りてくる技術です。安く綺麗になる代わりに、ゴースト・ボケ・ちらつきという独特の副作用がついてきます。このページは「なぜその副作用がアルゴリズム上どうしても出るのか」を、手を動かしながら追いかけます。

Jitter History Motion Vector Neighborhood Clamp TSR
まず用語だけ — 読む前の30秒
ジッター jitter
毎フレーム、カメラを1ピクセル未満だけずらすこと。違う場所を標本にするため。
履歴バッファ history buffer
前フレームまでの結果をためておく画像。これに今のフレームを少しずつ混ぜる。
モーションベクトル motion vector
各ピクセルが前フレームでどこにいたかを示す矢印。履歴を正しい位置から読むために要る。
ネイバークランプ neighborhood clamp
履歴の色を「今の周囲3×3の色の範囲」に押し込む安全装置。古すぎる色を捨てる。
ディスオクルージョン disocclusion
隠れていた背景が出てくること。そこには使える履歴が存在しない。
TSR temporal super resolution
UE5の上位版。低い解像度で描いて、履歴を使って高解像度に組み立て直す。
※ 各語の詳しい定義は、ページ末尾の用語集にもあります。

§1 — Why temporal

1フレームに1サンプルしかない、という制約

GPUは基本、1ピクセルにつき1回だけ色を計算します。ピクセルの中心をたまたま三角形の縁がかすめると、そのピクセルは「入っている/いない」の二択になり、階段(ジャギー)が出ます。素直な解決はスーパーサンプリング ── 1ピクセルを4回・8回と計算して平均する方法ですが、コストがそのまま4倍・8倍になります。

そこで発想を変えます。4倍のサンプルを1フレームで取る代わりに、4フレームかけて1個ずつ取る。毎フレーム、カメラをピクセル未満の量だけずらして(ジッター)別の場所を標本にし、結果を足していく。これが時間的アンチエイリアスの核です。コストは1フレームぶんのまま、標本数だけが時間軸に伸びます。

アルゴリズムの骨格 — 毎フレームこれだけ
1. jitter = halton(frame) // ±0.5px の副画素ずらし
2. C = render(scene, jitter) // 今フレーム(1サンプル・ギザギザ)
3. uv_prev = uv - motionVector(uv) // 前フレームでの居場所
4. H_prev = sample(History, uv_prev) // 履歴を再投影して読む
5. H_prev = clamp(H_prev, min3x3(C), max3x3(C))
6. History = lerp(H_prev, C, α) // α ≈ 0.05〜0.1
副作用はすべて、この6行のうち 3・4・5・6 の失敗として説明できます。3が外れる=ゴースト。5が働かない=スミア。6のαが小さすぎる=ボケと遅れ。αが大きすぎる=ちらつき。次の節で実際に壊してみます。

§2 — Break it yourself

壊して覚える ── 履歴ブレンド実験室

下は本物の TAA を小さく実装したものです。左が「毎フレーム1サンプルのまま(TAAなし)」、右が「履歴を混ぜた結果」。四角が右へ動き、背景は上にいくほど細かい市松模様(=標本しづらい)です。フレームを進めながら、モーションベクトルとクランプを切ってみてください。

TAA なし — 1サンプル/px
TAA あり — 履歴を混ぜた結果
小 = 履歴を重視(滑らか・遅い)大 = 今を重視(機敏・ギザギザ)
いま起きていること
実効サンプル数 1/α
収束までの目安
履歴に残る前フレームの重み

「実効サンプル数」は、収束したときに1ピクセルが何回ぶんの標本を平均しているかの目安で、およそ 1/α。α=0.1 なら約10サンプル相当 ── 8xスーパーサンプリングをタダで買っているようなものです。その代金が、この節で見た副作用


§3 — Symptoms

副作用カタログ ── 症状から原因へ

現場で「なんか変」と感じたとき、症状から6行のどこが壊れているかを逆引きできると直しが速いです。クリックで詳しい理屈を開きます。


§4 — TAA vs TSR

TSR は何を作り替えたのか

TSR(Temporal Super Resolution)は UE5 で入った、TAA の考えをアップスケールまで拡張したもの。「1080pで描いて4Kに組み立てる」ような使い方が前提になっています。狙いは同じ ── 履歴からサンプルを借りる ── ですが、借り方の慎重さが違います。

観点
TAA(従来)
TSR(UE5)

要するに TSR は「クランプで乱暴に捨てる」代わりに「履歴をどれだけ信じるかを画素ごとに見積もる」方向に進化した、と捉えると分かりやすいです。だから細部が保たれる一方、判定材料(モーションベクトルや深度)が嘘をつくと TAA より派手に崩れることもあります。


§5 — In UE

UEでの設定 ── PC とコンソール

まず Project Settings → Rendering → Anti-Aliasing Method で方式を選びます。UE5 の既定は TSR。触る価値のあるノブを、効き目の大きい順に並べます。

PC(デスクトップGPU)
解像度に余裕があるなら Screen Percentage 100 前後で TSR を「アンチエイリアス目的」に使うのが素直。高リフレッシュ狙いなら 66〜77% まで落として TSR に再構成させると、素直に解像度を落とすより明らかに綺麗です。DLSS/FSR 系プラグインを入れる場合は TSR とは排他。
コンソール(PS5 / XSX 相当)
そもそも TSR は「内部解像度を落として60fpsを守る」ために設計された道具です。動的解像度と組み合わせるのが定石で、負荷が上がると内部解像度が下がる = TSR の再構成負担が増える、という関係を頭に入れておくこと。60fps ターゲットでは履歴が1フレーム16.6msぶんしか古くならないので、30fps より副作用は軽くなります。
切り分けの手順
怪しい絵に出会ったら、まず r.AntiAliasingMethod 0(AAオフ)にして症状が消えるか確認します。消えるなら時間的手法のせい。次に ShowFlag.VisualizeMotionBlur や Buffer Visualization の Velocity でモーションベクトルが正しく出ているかを見る ── ゴースト系の犯人はほぼここです。それでも分からなければ Screen Percentage を 100 に戻して、再構成の問題かどうかを切り分けます。測り方の全体像は Primer 08 に。

Glossary — 用語

よく出る言葉

基礎に戻る
Primer 05 · ポストプロセス
次の深掘り
Primer 11 · Nanite とオーバードロー