世界を動かす技術を、日本語で。

ビデオゲームのぼやけ(そして最高のものがどのように機能するか)

概要

  • ブラー(ぼかし) はゲームやGUIの主要なポストプロセス技術
  • Depth of FieldBloom など、多様なエフェクトの基盤
  • WebGL を用いてリアルタイムでのブラー実装方法を解説
  • GPU の活用とパフォーマンスのトレードオフに焦点
  • 技術的背景 から実装まで、手順を追って詳細に説明

ゲーム・GUIにおけるブラー技術の基礎と応用

  • ブラー(ぼかし) は、現代のゲームやユーザーインターフェースにおいて不可欠なポストプロセス効果
  • Depth of Field(被写界深度)Bloom(発光)、UIのフロストガラス風パネルなど、多くの場面で利用
  • 「色を半径内で平均化する」 という単純なアイデアが基本
  • リアルタイム実装 には、長年の研究や数学的手法の進化が必要
  • GPUWebGL を使い、現代のブラウザでも高速にブラー処理が可能

ポストプロセスの流れとフレームバッファの役割

  • ゲームの3Dシーンは レンダリング後、フレームバッファ に一時保存
  • そのフレームバッファを 後処理(ポストプロセス) で加工し、エフェクトを追加
  • Color-correctionTone-mapping など、画像以外のデータも処理可能
  • 本記事では、 NEOTOKYO° のシーンを例に、ブラー実装を段階的に解説

WebGLによるブラーシェーダーの実装例

  • Fragment Shader を利用し、各ピクセルごとにブラー処理を実行
    • precision highp float;で高精度カラー計算
    • UV座標 を使い、テクスチャから色情報を取得
    • lightBrightness (明るさ調整)もシェーダー内で制御
    • gl_FragColor = texture2D(texture, uv) * lightBrightness;で出力

WebGLを用いたJavaScript側の制御

  • canvas 要素にWebGL 1.0コンテキストを取得し、描画準備
  • フレームバッファテクスチャシェーダー の初期化処理
  • UI操作 でアニメーションや明るさをリアルタイムに変更可能
  • 描画モード (scene, bloomなど)の切り替えと再描画処理
  • FPSや描画時間 など、パフォーマンス計測の仕組みも実装

まとめ:理論と現実の橋渡し

  • 数学的理論技術的制約 のバランスを取りながら進化してきたブラー技術
  • GPU を最大限活用し、リアルタイムで美しく自然なエフェクトを実現
  • WebGL や最新ブラウザの力で、誰でも高度なグラフィックス表現が可能
  • 今後も グラフィックスプログラミング の進化に注目

この内容は、 Summer of Math Exposition 向けの解説として、 インタラクティブなビジュアルパフォーマンス比較 も交えながら、初心者でも理解できるように構成されています。

Hackerたちの意見

プログレッシブな例のおもちゃ、いいね!ありがとう!

内容はすごく好きなんだけど、テキストが両端揃えになってるせいで、読むのがちょっと大変になってる気がする。

初めて聞いた!テキストの両端揃えを外すnoJustifyというURLパラメータを追加したよ。例えば、https://blog.frost.kiwi/dual-kawase/?noJustify これで読みやすくなったと思う?デフォルトにした方がいいかな?

類似のテーマについての素晴らしい動画: https://m.youtube.com/watch?v=v9x_50czf-4

アセロラは面白いプロジェクトをやってるけど、彼の最適化された草の愚痴は、ここ数年で見た中で一番笑ったわ。=3

すごくよく書けたブログだね、素晴らしい仕事!

著者です!リンクしてくれてありがとう!川瀬雅樹さんは、僕のグラフィックスプログラミングのアイドルみたいな存在なんだ。日本に住んでるから、彼とZoomでインタビューして、1999年から2005年の日本のゲームシーンでのグラフィックスプログラマーとしての経験について話を聞いたよ。この経験がきっかけで、Linuxディストリビューションをいじってるときに見つけたデュアル川瀬ぼかしについて書きたいと思ったんだ。

コンピュートシェーダーに適したぼかしアルゴリズムの提案があれば教えてほしい!記事に書いてある通常の川瀬ぼかしは、テクスチャのバイリニアサンプリングを使ってるよね。もちろん、テクスチャサンプリングを使ってそのままコンピュートシェーダーに実装できるけど、入力と出力を共有メモリにする必要がある状況なんだ。オフチップのDRAMに結果を書き出すのは避けたいから、効率的なコンピュートシェーダーぼかしを実現する方法を探ってる。ワープやウェーブ、サブグループのインストリンシックを使って画像をダウンサンプリングして、ガウスっぽい加重平均を取る感じで。ここで難しいのは、川瀬ぼかしが「奇数」の位置で入力をサンプリングするのに対して、ワープインストリンシックは「偶数」の位置に制限されてるってこと。もしこの分野での先行研究を知ってる人がいたら、教えてほしいな。

でも、入力と出力が共有メモリにある状況なんだ。テクスチャサンプリングを使うためにはオフチップDRAMに結果を書き出す必要があるから、それを避けたいんだ。なんで手動で補間(バイリニアサンプリング)しないの?そんなに難しくないよ。4つの離散サンプルをもっと一体化したものに統合すれば、いくつかの最適化ができるかもしれないし、正しく設定すれば各サンプルのクリッピングを心配する必要もないよ。ただ、そのアプローチのパフォーマンスがどうなるかは全然わからないけどね。バイリニア補間に関する情報はちょっと数学的なものが多いから、わかりやすい形で式を紹介するね:value = (1 - dx) * (1 - dy) * Q11 + dx * (1 - dy) * Q21 + (1 - dx) * dy * Q12 + dx * dy * Q22

ありがとう!インタラクティブな例が大好きだよ。

すごくいい投稿だね!書いてくれてありがとう。詳細がしっかりしてて好きだな。ボックスやガウスぼかしをよく使うけど、オブジェクトのアウトラインやハイライトをレンダリングする時に使ってるよ。

川瀬アプローチは2005年のもので、それ以来GPUの性能はかなり向上したよね。最近のゲームでは、複数の被写界深度を使ったボケぼかしを使ってるのもあるし、結果的にガウスのやつより自然に見えることが多いよ。ちなみに、これは単なるシネマティックな効果じゃなくて、私たちの瞳が丸いから、カメラと同じように焦点が合ってないものに対して円盤型のフィルターとして機能するんだ。Doom(2016)がどうやってるかの詳細はこちらだよ:

私はアドリアンの大ファンなんだ <3 そう、ボケぼかしは本当に心地いいよね。私の記事では、ガウスのぼかしは他のエフェクトの基本的なビルディングブロックとしての使い方に焦点を当ててるんだ。例えば、霜がかかったガラスや熱の歪み、ブルームなんかね。特に2015年のデュアル川瀬は、メモリスループットが弱いモバイルグラフィックスの文脈で作られたんだ。でも、RTX 4090のような最速のコンシューマーハードウェアでも、最適化されていないガウスの実装は遅くなるし、samplePosMultiplierは無視できないパフォーマンスの影響があるから、テクスチャキャッシュもまだ重要なんだ。今日の高解像度、特にモバイルでは、デュアル川瀬のような賢くて最適化されたアルゴリズムが必要なんだよ。

FFTを使ったローパスフィルタリングについての部分は、ガウスぼかしとは根本的に異なるものだという結論で終わってるね(「ローパスフィルタ ≠ ローパスフィルタ」)。でも、画像空間での畳み込みは、フーリエ空間での掛け算に過ぎないんだ。フーリエ空間でガウスと掛け算をすれば、ガウスぼかしが得られるはずだよ。ただ、必ずしも最速の選択肢ではないけどね。