web-dev-qa-db-ja.com

バージョン4.1のOpenGLでのテキストレンダリングの最新技術とは何ですか?

OpenGLでのテキストレンダリングについては、すでに次のような質問があります。

ただし、ほとんどの場合、固定機能パイプラインを使用してテクスチャ付きクワッドをレンダリングします。確かにシェーダーはより良い方法を作らなければなりません。

私は国際化についてはあまり心配していません。私の文字列のほとんどは目盛りのラベル(日付と時刻または純粋に数値)をプロットします。ただし、プロットは画面のリフレッシュレートで再レンダリングされ、かなりの量のテキストが表示される場合があります(画面上に表示されるグリフは数千以下ですが、ハードウェアアクセラレーションレイアウトで十分です)。

最新のOpenGLを使用したテキストレンダリングの推奨アプローチは何ですか? (アプローチを使用して既存のソフトウェアを引用することは、それがうまく機能することの良い証拠です)

  • を受け入れるジオメトリシェーダー位置と方向、および文字シーケンスとテクスチャ付きクワッドの放出
  • ベクターフォントをレンダリングするジオメトリシェーダー
  • 上記と同じですが、代わりにテッセレーションシェーダーを使用します
  • フォントのラスタライズを行う計算シェーダー
191
Ben Voigt

合計12キャラクタのみをレンダリングしない限り、アウトラインのレンダリングは、曲率を概算するためにキャラクタごとに必要な頂点の数のため、「ノーゴー」のままです。代わりにピクセルシェーダーでベジェ曲線を評価するアプローチがありましたが、これらは簡単にアンチエイリアシングされないという欠点があります。これは、距離マップテクスチャ付きクワッドを使用すると簡単であり、シェーダーでの曲線の評価は依然として必要以上に計算コストがかかります。

「高速」と「品質」の最良のトレードオフは、符号付き距離フィールドテクスチャを使用したテクスチャ付きクワッドです。通常のテクスチャのクワッドを使用するよりもわずかに遅くなりますが、それほどではありません。一方、品質はまったく別のものです。結果は本当に驚くべきもので、できるだけ速く、グローなどの効果も簡単に追加できます。また、必要に応じて、この手法を古いハードウェアにうまくダウングレードできます。

テクニックについては、有名な Valve paper を参照してください。

この手法は、暗黙的なサーフェス(メタボールなど)の動作と概念的には似ていますが、ポリゴンを生成しません。完全にピクセルシェーダーで実行され、テクスチャからサンプリングされた距離を距離関数として取得します。選択したしきい値(通常は0.5)を超えるものはすべて「入力」、その他はすべて「出力」です。最も単純なケースでは、10年前のシェーダー非対応ハードウェアで、アルファテストのしきい値を0.5に設定すると、正確な処理が行われます(ただし、特殊効果やアンチエイリアシングはありません)。
フォントにもう少し太い(太字)を追加したい場合、コードの1行を変更せずに、わずかに小さいしきい値でトリックを行います(「font_weight」ユニフォームを変更するだけです)。グロー効果の場合、1つのしきい値を超えるものはすべて「入力」、別の(小さい)しきい値を超えるものはすべて「出力されますが、グロー」と見なされ、2つの間のLERPが考慮されます。アンチエイリアスも同様に機能します。

1ビットではなく8ビットの符号付き距離値を使用することにより、この手法はテクスチャマップの有効解像度を各次元で16倍に増やします(白黒ではなく、可能なすべてのシェードが使用されるため、256倍になります)同じストレージを使用する情報)。ただし、16倍をはるかに超えて拡大しても、結果はかなり許容できるように見えます。長い直線はやがて少し波状になりますが、典型的な「むらのある」サンプリングアーティファクトはありません。

ジオメトリシェーダーを使用してポイントからクワッドを生成できます(バス帯域幅を削減します)が、正直なところ、ゲインはわずかです。同じことが、GPG8で説明されているインスタンス化された文字のレンダリングにも当てはまります。インスタンス化のオーバーヘッドは、描画するテキストがlotある場合にのみ償却されます。私の意見では、この増加は、追加された複雑さや非ダウングレード性とは関係ありません。さらに、定数レジスタの量によって制限されるか、キャッシュの一貫性のために最適ではないテクスチャバッファオブジェクトから読み取る必要があります(最初の目的は最適化することでした!)。
アップロードを少し前にスケジュールし、過去15年間に構築されたすべてのハードウェアで実行する場合、シンプルで単純な古い頂点バッファーは同じくらい高速(おそらく高速)です。また、フォント内の特定の文字数や、レンダリングする特定の文字数に限定されません。

フォントに256文字を超えないことが確実な場合、テクスチャアレイは、ジオメトリシェーダーのポイントからクワッドを生成するのと同様の方法でバス帯域幅を取り除くために検討する価値があります。配列テクスチャを使用する場合、すべての四角形のテクスチャ座標は同一の定数sおよびt座標を持ち、レンダリングする文字インデックスに等しいr座標のみが異なります。
しかし、他の技術と同様に、前世代のハードウェアとの互換性がないという犠牲を払って、期待されるゲインはわずかです。

距離テクスチャを生成するためのJonathan Dummerによる便利なツールがあります。 説明ページ

更新:
最近指摘されたProgrammable Vertex Pulling(D.Rákos、 "OpenGL Insights"、pp。239)には、引っ張ることに関連する余分なレイテンシやオーバーヘッドはありません。標準の固定機能を使用して同じことを行うのと比較して、最新世代のGPUでシェーダーからプログラムで頂点データを取得します。
[。テクスチャの問題が少ない。

これにより、バッファーテクスチャから一定のデータ(クアッドサイズなど)を取得するというアイデアがより魅力的になります。したがって、仮想的な実装では、次のようなアプローチにより、GPUメモリだけでなくPCIeとメモリの転送を最小限に抑えることができます。

  • このインデックスとgl_VertexIDを渡す頂点シェーダーへの唯一の入力として、文字インデックス(表示される文字ごとに1つ)のみをアップロードし、ジオメトリシェーダーの4ポイントに増幅します。頂点ID(これは「頂点シェーダーで使用可能になるgl_primitiveID」)を唯一の属性として使用し、変換フィードバックを介してこれをキャプチャします。
  • 出力属性は2つ(GSの主なボトルネック)しかないため、これは高速になり、それ以外の場合は両方のステージで「no-op」に近くなります。
  • フォントの各文字に対して、ベースポイントを基準としたテクスチャ付きクワッドの頂点位置を含むバッファテクスチャをバインドします(これらは基本的に「フォントメトリック」です)。このデータは、左下の頂点のオフセットのみを格納し、軸に合わせたボックスの幅と高さをエンコードすることで、クワッドごとに4つの数値に圧縮できます(ハーフフロートを想定し、これは文字ごとに8バイトの定数バッファーになります-典型的な256文字のフォントは2kiBのL1キャッシュに完全に収まります)。
  • ベースラインのユニフォームを設定します
  • 水平オフセットでバッファテクスチャをバインドします。これらのcouldはおそらくGPUで計算することもできますが、CPU上のその種のものよりもはるかに簡単で効率的です。カーニングを考えてください)。また、別のフィードバックパス(別の同期ポイント)が必要になります。
  • フィードバックバッファーから以前に生成されたデータをレンダリングします。頂点シェーダーは、基点の水平オフセットとコーナー頂点のオフセットをバッファーオブジェクトから引き出します(プリミティブIDと文字インデックスを使用)。送信された頂点の元の頂点IDは、「プリミティブID」になりました(GSが頂点を四角形に変換したことを思い出してください)。

このように、理想的には必要な頂点帯域幅を75%(償却)削減できますが、1行しかレンダリングできません。 1回の描画呼び出しで複数のラインをレンダリングできるようにするには、ユニフォームを使用する(帯域幅のゲインを小さくする)のではなく、バッファテクスチャにベースラインを追加する必要があります。

ただし、75%の削減を想定した場合でも、「合理的な」量のテキストを表示する頂点データは50〜100kiB程度(GPUまたはPCIeに対して実質的にzeroであるため)バス)-複雑さを増し、下位互換性を失うことは本当に面倒な価値があるとはまだ思いません。ゼロを75%削減しても、まだゼロにすぎません。私は確かに上記のアプローチを試していないので、真に適格な声明を出すにはさらに研究が必要だろう。それでも、誰かが本当に驚くべきパフォーマンスの違いを実証できない限り(数十億文字ではなく「通常」の量のテキストを使用して!)、私の視点では、頂点データについては、単純で単純な古い頂点バッファーで十分です「最先端のソリューション」の一部と見なされます。シンプルでわかりやすく、機能し、うまく機能します。

既に上記の「 OpenGL Insights 」を参照したので、距離フィールドを説明するStefan Gustavsonによる章「距離フィールドによる2D形状レンダリング」も指摘する価値があります。非常に詳細にレンダリングします。

2016年の更新:

一方、極端な倍率で邪魔になる角の丸みを帯びたアーティファクトを除去することを目的とするいくつかの追加の技術が存在します。

1つのアプローチでは、距離フィールドの代わりに擬似距離フィールドを使用します(実際のアウトラインではなく、アウトラインまたは架空のラインまでの最短距離であるという違いがあります)縁)。これはいくぶん優れており、同じ量のテクスチャメモリを使用して、同じ速度(同一のシェーダー)で実行されます。

別のアプローチでは、3チャネルテクスチャの詳細と実装で3の中央値を使用します githubで利用可能 。これは、この問題に対処するために以前に使用されていたand-orハックを改善することを目的としています。高品質、わずかに、ほとんど目立たないほど遅くなりますが、3倍のテクスチャメモリを使用します。また、追加の効果(グローなど)を正しくするのは困難です。

最後に、キャラクターを構成する実際のベジェ曲線を保存し、フラグメントシェーダーで評価します 実用的になりました
WebGLデモは、このテクニックを使用して、大規模なPDFをリアルタイムでレンダリングします here

194
Damon

http://code.google.com/p/glyphy/

GLyphyと他のSDFベースのOpenGLレンダラーの主な違いは、他のほとんどのプロジェクトがテクスチャにSDFをサンプリングすることです。これには、サンプリングに伴う通常の問題がすべてあります。すなわち。アウトラインを歪め、低品質です。 代わりに、GLyphyは、GPUに送信された実際のベクトルを使用してSDFを表します。 これにより、非常に高品質のレンダリングが可能になります。

欠点は、コードがOpenGL ESを備えたiOS用であることです。おそらくWindows/Linux OpenGL 4.xポートを作成するつもりです(ただし、著者が実際のドキュメントを追加してくれることを願っています)。

14
Display Name

最も普及している手法は、テクスチャ付きのクワッドです。しかし、2005年にLORIAはベクターテクスチャと呼ばれるものを開発しました。つまり、ベクターグラフィックスをプリミティブのテクスチャとしてレンダリングします。これを使用してTrueTypeまたはOpenTypeフォントをベクターテクスチャに変換すると、次のようになります。

http://alice.loria.fr/index.php/publications.html?Paper=VTM@2005

12
datenwolf

マークキルガードの赤ちゃん、NV_path_rendering(NVpr)が上記のいずれにも言及されていなかったことに驚いています。その目標はフォントレンダリングよりも一般的ですが、フォントからカーニングを使用してテキストをレンダリングすることもできます。 OpenGL 4.1も必要ありませんが、現時点ではベンダー/ Nvidiaのみの拡張機能です。基本的に、メトリックを取得するためにfreetype2ライブラリに依存するglPathGlyphsNVを使用してフォントをパスに変換します。次に、glGetPathSpacingNVでカーニング情報にアクセスし、NVprの一般的なパスレンダリングメカニズムを使用してパス「変換」フォントを使用します。 (実際の変換がないため、引用符で囲みます。曲線はそのまま使用されます。)

NVprのフォント機能の記録されたデモ は、残念ながら特に印象的ではありません。 (たぶん、誰かが 非常におしゃれなSDFデモ の間に沿って1つを作成する必要があります。

フォント部分に関する2011年のNVpr APIプレゼンテーションの話 ここから始まる そして、続く 次の部分 ;そのプレゼンテーションがどのように分割されるかは少し残念です。

NVprに関するより一般的な資料:

  • Nvidia NVpr hub 、ただし、ランディングページの一部の資料は最新ではありません
  • Siggraph 2012 paper 「ステンシル、カバー」(StC)と呼ばれるパスレンダリングメソッドの頭脳用。また、Direct2Dのような競合する技術の仕組みについても簡単に説明しています。フォント関連のビットは 論文の別紙 に委ねられました。 videos/demosのような追加機能 もあります。
  • GTC 2014プレゼンテーション 更新ステータス。簡単に言うと、GoogleのSkiaによってサポートされています(Nvidiaは2013年と2014年後半にコードを提供しました)。これはGoogle ChromeおよびAdobeのベータ版で[Skiaとは独立して]で使用されますIllustrator CC 2014
  • OpenGL拡張レジストリの公式ドキュメント
  • USPTOは、NVprに関連して少なくとも4つの特許をKilgard/Nvidiaに付与しました。StCを自分で実装したい場合は、 S8698837S8698808S87048 および S873025 。これに関連する17のUSPTO文書のようなものもあり、それらのほとんどが特許出願であることに注意してください。

そして、「ステンシル」という言葉は私の答えの前にこのページでヒットしなかったので、このページに参​​加したSOコミュニティのサブセットは、かなり多数であるにもかかわらず、テッセレーションを認識していなかったようです。一般的なパス/フォントレンダリング用の無料のステンシルバッファベースのメソッド。 Kilgardには openglフォーラムでのFAQのような投稿 があります。これは、[GP] GPUを使用している場合でも、テッセレーションのないパスレンダリング方法が沼地の標準3Dグラフィックスと異なることを示しています。 (NVprにはCUDA対応チップが必要です。)

歴史的観点から、Kilgardは古典的な "テクスチャマップテキスト用のシンプルなOpenGLベースのAPI"、SGI、1997 の作者でもあり、ステンシルベースのNVprと混同しないでください。 2011年。


NVprのようなステンシルベースのメソッドやGLyphyのようなSDFベースのメソッド(他の回答で既に説明されているのでここでは説明しません)など、このページで説明した最近のメソッドのほとんどではありませんが、1つの制限があります:任意のスケーリングレベルでジャギーのない従来の(〜100 DPI)モニターでの大きなテキスト表示に適しています。また、高DPIの網膜のようなディスプレイで、小さいサイズでも見栄えがよくなります。ただし、MicrosoftのDirect2D + DirectWriteが提供するもの、つまりメインストリームディスプレイ上の小さなグリフのヒントを完全には提供しません。 (一般的なヒントの視覚的な調査については、 this typotheque page を参照してください。より詳細なリソースは on antigrain.com です。)

現時点では、Microsoftができることをヒントにできるオープンで製品化されたOpenGLベースのものは知りません。 (私の知る限り、AppleはGLベースのフォント/パスのレンダリング方法を公開していないので、AppleのOS X GL/Quartz内部には無知だと認めます。OSXは、 MacOS 9は、まったくヒントを行いません。これは 一部の人々を悩ます です。とにかく、 OpenGLシェーダを介してヒントを扱う2013年の研究論文 INRIAのNicolas Pによって書かれました。 。Rougier; OpenGLからヒントを行う必要がある場合は、おそらく読む価値があります。 freetypeのようなライブラリーは、ヒンティングに関してはすでにすべての作業を行っているように思えるかもしれませんが、実際には次の理由でそうではありません。

FreeTypeライブラリは、RGBモードのサブピクセルアンチエイリアスを使用してグリフをラスタライズできます。ただし、グリフを正確に配置するためにサブピクセルの配置を実現したいので、これは問題の半分にすぎません。テクスチャ化されたクワッドを小数ピクセル座標で表示しても、ピクセルレベル全体でテクスチャ補間が行われるだけなので、問題は解決しません。代わりに、サブピクセルドメインで正確なシフト(0〜1)を実現する必要があります。これは、フラグメントシェーダーで実行できます[...]。

解決策は必ずしも簡単ではないため、ここで説明するつもりはありません。 (論文はオープンアクセスです。)


Rougierの論文から学んだもう1つのこと(およびKilgardは考慮していないようです)は、(Microsoft + Adob​​e)のフォントパワーが1つではなく2つのカーニング仕様メソッドを作成したことです。古いものはいわゆるkernテーブルに基づいており、freetypeでサポートされています。新しいものはGPOSと呼ばれ、フリーソフトウェアの世界ではHarfBuzzやpangoなどの新しいフォントライブラリでのみサポートされています。 NVprはこれらのライブラリのいずれもサポートしていないようであるため、いくつかの新しいフォントでは、カーニングはNVprですぐに動作しない場合があります。 このフォーラムの議論 によると、明らかに野生のものがいくつかあります。

最後に、 複雑なテキストレイアウト(CTL) を実行する必要がある場合、OpenGLベースのライブラリが存在しないため、現在OpenGLで運が悪いようです。 (一方、DirectWriteはCTLを処理できます。)CTLをレンダリングできるHarfBuzzのようなオープンソースのライブラリがありますが、(ステンシルベースのメソッドを使用する場合のように)どのようにうまく動作させるかわかりませんOpenGL。おそらく、再形成されたアウトラインを抽出し、それらをパスとしてNVprまたはSDFベースのソリューションに供給するために、グルーコードを記述する必要があります。

7
Fizz

あなたの最善の策は、OpenGLバックエンドで cairo graphics を調べることだと思います。

3.3コアのプロトタイプを開発するときに抱えていた唯一の問題は、OpenGLバックエンドでの機能の使用が非推奨になったことです。 1〜2年前だったので、状況は改善したかもしれません...

とにかく、将来、デスクトップのOpenGLグラフィックスドライバーがOpenVGを実装することを願っています。

3
Orhun