ひとことで
過去のフレームの結果を再利用して、ギザギザ(エイリアシング)やちらつきを消すアンチエイリアスです。毎フレーム、カメラの投影を 1 画素より小さくずらして描き、前のフレームまでの結果と少しずつ混ぜます。すると、何枚ものずらした画像を平均したのと同じ効果が得られ、輪郭がなめらかになります。現代のほぼすべての 3D ゲームエンジンで使われている標準的な手法です。
ゲームでの使いどころ
- 細い物のちらつき防止:電線、柵、草、髪の毛、遠くの手すりが、カメラが動くたびにちらつくのを防ぐ。
- 鏡面反射のちらつき:金属の細かいハイライトのちらつきを抑える。
- ノイズの多い効果のまとめ役:SSAO、ボリューメトリックフォグ、ソフトシャドウ、SSR などを、少ない標本数でノイズを出しながら計算し、TAA で時間方向に平均して消す。
- アップスケーリングの土台:DLSS、FSR、XeSS などの超解像技術は、TAA の考え方を発展させたものです。
しくみ
1. ジッター:毎フレーム、投影行列に 1 画素より小さいずらしを加えます。ずらし量は、画素の中を均等に覆う数列(ハルトン列などの低食い違い列)から選びます。
2. 再投影:各画素が前のフレームではどこに映っていたかを、深度とカメラの動き(とモーションベクトル)から求め、そこから過去の結果(履歴)を読みます。
3. 混ぜる:今のフレームの色と履歴を混ぜます。
新しいフレームの割合 が 0.1 なら、おおよそ過去 10 フレーム分を平均したのと同じになります。
4. 履歴の修正(クランプ):物が動いたり、隠れていた物が現れたりすると、履歴は間違った色を持っています。そのまま混ぜると、動く物の後ろに残像(ゴースト)が残ります。そこで、今のフレームの周囲 3×3 画素の色の範囲(最小〜最大)に履歴の色を収めます。範囲外の色は「もう正しくない」とみなして切り捨てるわけです。
実装のポイント
- 2 枚の履歴を交互に使う:読み込み用と書き込み用のピンポンバッファで履歴を更新します。
- YCoCg 空間でクランプ:色を明るさと色差に分けた空間で範囲を求めると、クランプがより正確になります。
- シャープネス:平均によって画面が少しぼやけるので、軽いシャープ化を組み合わせることが多いです。
- UI は対象外:ジッターは 3D シーンだけにかけ、UI は TAA の後で描きます。
つまずきやすい点
- 残像(ゴースト):クランプが弱いと、動く物や粒子の後ろに尾を引きます。
- ぼやけ:過去のフレームを混ぜるので、静止画でもわずかに柔らかい画になります。「TAA は画面がぼやける」という不満はここから来ます。
- モーションベクトルのない物:モーションベクトルを出力しない物(一部のパーティクルや、頂点アニメーションする物)は正しく再投影されず、にじみます。
- 急な変化への遅れ:画面の明るさが急に変わると、履歴の影響で少し遅れて変化します。
デモで試すこと
- 「なし」にすると、奥の柵と電線がギザギザに途切れ、カメラが動くとちらつきます。
- 「TAA」に戻すと、線がなめらかにつながり、ちらつきが消えます。
- 「TAA(色の制限なし)」にすると、動くドローンや柵の後ろに残像が尾を引きます。これを防ぐのが近傍の色による制限です。
- 「新しいフレームの割合」を小さくすると、よりなめらかになりますが、残像が出やすくなり、変化への追従も遅れます。