プログラミング
SDF vs MSDF vs Slug: GPU テキストレンダリング
SDF vs. MSDF vs. Slug: GPU Text Rendering (alphapixeldev.com)
要約
GPUでのテキストレンダリングにおいて、SDF(符号付き距離フィールド)、MSDF(マルチチャンネル符号付き距離フィールド)、Slugといった様々なアルゴリズムを比較解説しています。従来のテクスチャアトラス方式から、より高精度でスケーラブルな描画を実現する最新技術まで、それぞれのメリット・デメリットと適用範囲を掘り下げています。
全文翻訳
SDF、MSDF、Slug、テクスチャアトラス、またはRiveの間でテキストレンダリングアルゴリズムをどのように選択しますか? テキストは、自分で描画しようとするまで単純に見えます。文字は画像ではなく、アウトラインのセットです。閉じた直線とベジェ曲線のループで、巻き数規則に従って塗りつぶされます。これをCPUでビットマップに描画するのは解決済みの問題です。GPUで、あらゆるサイズで、あらゆる3D変換下で、テキストが毎フレーム変化する中で、鮮明に描画することはそうではありません。ほとんどのエンジンは、グリフを事前にテクスチャに焼き付け、妥協を受け入れて、難しいバージョンを回避します。2017年にEric LengyelはSlugというアルゴリズムを発表し、回避をやめました。これはテクスチャアトラスも毎フレームのテッセレーションもなしに、フラグメントシェーダーから直接アウトラインを描画します。Lengyelは2019年にこれを特許取得し、2026年3月17日にその特許をパブリックドメインに捧げました。だからこそ、私たちはSlug技術のC++20実装であるSlughornを構築し、それがどのように機能し、どこで優れているかを今話すことができるのです。これは、ビットマップアトラスからSlugまで、GPUテキストレンダリングが実際にどのように機能するかのツアーであり、各手法がどこに位置するかを示します。グリフを難しくしているものは何か? すべてのスケーラブルフォントは、各グリフをベクトルアウトラインとして格納します。TrueTypeは二次ベジェ曲線を使用し、OpenType with CFFは三次曲線を使用し、どちらも直線セグメントを混在させます。文字の内部は、通常ゼロでない巻き数規則である塗りつぶし規則が内部と判断するものです。ピクセルからレイを放ち、アウトラインがそれを横切る回数を数え、巻き数がおよそゼロでなければ、ピクセルはグリフの内部にあります。グリフはアウトラインのセットであり、ピクセルではありません。塗りつぶされた点はオンカーブポイント、開いた円はベジェ制御点です。レンダラーは一度に3つのことを同時に、かつ高速に行う必要があります。内部を正しく塗りつぶし、クリーンなアンチエイリアスエッジを生成し、メニューで8ピクセル高か、ビルボードで画面全体を埋めるかに関わらずシャープさを保つ必要があります。CPUでは、各グリフをターゲットサイズで一度ラスタライズすれば完了です。GPUでは、毎フレーム数千のグリフを任意のスケールで描画したいと考え、理想的には何も再ラスタライズしたくないでしょう。その制約が、以下のすべての手法がトレードオフを行う場所です。
手法1:テクスチャアトラス(ビットマップグリフ)
最も古く、依然として最も一般的なアプローチです。各グリフを一度、一つのサイズで、アトラスと呼ばれる共有テクスチャにラスタライズし、その後、画面上の各文字をそのスロットをサンプリングするテクスチャ付きクアッドとして描画します。高速で、移植性が高く、テクスチャユニットを持つあらゆるもので動作します。だからこそ、どこにでもあるのです。問題は、スケーリングした瞬間に現れます。焼き付けられたサイズを超えて拡大すると、ビットマップを拡大しているため、グリフはぼやけたりブロック状になったりします。縮小すると、シャイマーやステムの消失が発生します。シャープにしたいサイズごとに、別のアトラスが必要です。言語ごとに問題が異なります。ラテンアトラスは小さいですが、中国語、日本語、韓国語には数万のグリフがあり、それらをすべて複数のサイズで焼き付けるのはメモリの悪夢です。そして、ビットマップは3D表面に配置されたテキストがソフトに見えるように、パースペクティブで表示されていることを認識しません。焼き付けられたアトラスグリフを拡大(左と中央)した場合と、アウトラインからレンダリングした場合(右)の比較。
手法2:符号付き距離フィールド(SDF)
Valveが10年間業界を牽引した修正を導入しました。Chris Greenの2007年のSIGGRAPHでの研究「Improved Alpha-Tested Magnification for Vector Textures and Special Effects」は、グリフのピクセルではなく、符号付き距離フィールドを格納します。各テクセルは、最も近いエッジまでの距離を保持し、内部では正、外部では負です。シェーダーでは、そのフィールドをサンプリングし、ゼロで閾値を設定します。距離は滑らかに補間されるため、小さなSDFテクスチャを劇的に拡大してもクリーンなエッジが得られ、閾値を柔らかくすることで安価なアンチエイリアスが得られます。一つの小さなテクスチャ、妥当な範囲で解像度に依存しない、一つの安価なシェーダー。長らく、これはシャープなUIテキストやゲームHUDのデフォルトであり、制約のあるハードウェアでは今でもそうです。しかし、SDFは依然として固定解像度でサンプリングされた焼き付けテクスチャであり、コーナーについて嘘をつきます。シャープなコーナーは距離フィールドの不連続性であり、バイリニア補間がそれを丸めます。文字のすべてのシャープなコーナー、'A'の頂点、'K'の切り込みは柔らかくなります。拡大を十分に押し進めるか、グリフをフィールドが数テクセル幅しかないほど小さくすると、細いステムが壊れ、ディテールがにじみます。符号付き距離フィールド(左)と、シェーダーがそこから回復するシャープなエッジ(右)。
手法3:マルチチャンネル符号付き距離フィールド(MSDF)
Viktor Chlumskyの2015年の論文と2018年の論文「Improved Corners with Multi-Channel Signed Distance Fields」による研究は、コーナーの問題を解決します。一つの距離チャンネルの代わりに、MSDFは赤、緑、青の3つのチャンネルに3つを格納し、それぞれがシャープなコーナーを維持するように選択されたエッジの異なるサブセットへの距離をエンコードします。シェーダーでは、3つのチャンネルの中央値を取ります。中央値トリックはコーナーをほぼ完璧に再構築するため、MSDFグリフはSDFを泥に丸める拡大でもシャープさを保ちます。MSDFは多くのチームにとって現在のスイートスポットであり、ChlumskyのmsdfgenはMITライセンスで広く採用されています。シャープでスケーラブルなテキストが必要で、アトラスを焼き付ける意思があるなら、これは優れた選択肢です。しかし、それは依然としてアトラスであり、それに伴うコストがかかります。事前に選択した解像度で各グリフを焼き付けるため、動的またはユーザー提供のテキスト、およびCJKのような巨大なグリフセットは、依然として焼き付けパイプラインとメモリ予算を意味します。生成は通常のSDFよりもコストがかかります。非常に小さいサイズでは、まだ細かいディテールを保持するにはテクセルが少なすぎ、極端な縮小ではまだエイリアシングと戦います。3チャンネルのルックアップは、1チャンネルよりも帯域幅を多く消費します。MSDFは品質の上限を引き上げますが、依然としてアトラスを使用します。SDFはシャープなコーナーを丸めます。MSDFはそれらを保持します。画像:Viktor Chlumsky / msdfgen (MIT)。
手法4:テッセレーションとカバレッジ(Loop-Blinn、NV_path_rendering、Pathfinder、Rive)
別のファミリーはテクスチャを完全にスキップし、アウトラインをGPUがラスタライズできるジオメトリに変換します。Loop-Blinnはカーブした三角形をGPUに供給し、ピクセルごとのディスカードシェーダーを使用して、二次ベジェ曲線の内部のみを保持し、巻き数解決のためにステンシルバッファと組み合わせます。エレガントですが、信頼性の高いアンチエイリアスは、品質を犠牲にするトリックなしでは本当に困難です。ステンシル・ゼン・カバーは、NVIDIAのNV_path_rendering拡張として公開されており、パスを一度のパスでステンシルバッファに描画し、2番目のパスでそれをカバーします。高品質ですが、ベンダー拡張機能と特定のハードウェアパスに依存します。Pathfinderはエッジをマイクロトライアングルにテッセレートし、ピクセルごとに符号付き台形面積を計算し、コンピュートパスでカバレッジを蓄積します。タイルベースで、最新のGPUで高速です。2024年にオープンソース化されたRiveのレンダラーは、アンチエイリアスされたベクトルパスをユニークな三角形パッチに削減し、ピクセルローカルストレージを備えた大規模並列パイプラインでラスタライズし、アニメーションベクトルアートで120 fpsを達成します。このファミリーは真に解像度に依存せず、アニメーションデザインのベクトルグラフィックスにとっては、しばしば正しい答えです。特にRiveは、動くアートワークのために構築されています。コストは、ジオメトリが変更されたときに再実行する必要があるテッセレーション自体、複雑なグリフのジオメトリの増加、クリーンな解析的アンチエイリアスの困難さ、そして場合によっては特定のハードウェア機能または拡張機能への依存です。テッセレーション手法は、アウトラインをGPUがラスタライズする三角形に変換します。
手法5:Slug、アウトラインからの直接レンダリング
Slugはアトラスと毎フレームのテッセレーションをスキップし、グリフを小さなGPUバッファに格納された二次ベジェ曲線と線分のリストとして保持します。それに加えて、Slugは軽量なグリフごとのアクセラレーション構造を構築し、グリフを水平バンドにパーティション化します。これにより、ピクセルはアウトライン全体ではなく、近くの数本の曲線だけを考慮すればよくなります。その後、フラグメントシェーダーで直接カバレッジを解決します。各ピクセルに対して