web-dev-qa-db-ja.com

WebGLの高品質テキスト

WebGL内でより高品質の(任意の)テキストを描画する方法を探しています。現在、2Dキャンバスでビットマップフォントレンダリングを使用しており、それらをWebGLコンテキストにブリットしています。

この方法はここで説明されています http://delphic.me.uk/webgltext.html

これは、私が今知っているWebGL内に任意のUnicodeテキストを描画するための唯一のソリューションです。この方法の問題は、これらがビットマップフォントであり、小さいフォントサイズではブロック状に見えることです。私は主に18のフォントサイズを使用しており、結果はデスクトップ品質のフォントと比較してかなりブロック状です。

ThreeJSには見栄えの良いテキストを生成するフォントライブラリがあることは知っていますが、必要なものに対して正常に機能する独自のラッパーがあり、threeJSのオーバーヘッドを追加したくないため、threeJSを使用したくありません。

では、WebGLでより高品質のテキストを作成するにはどうすればよいでしょうか。品質を向上させるためにJavascriptでテキスト形状を抽出する方法はありますか?

19
Markus Moenig

しばらくの間フォントを使用した後、WebGLでフォントを作成する6つの方法を見ることができますが、すべて長所と短所があります。


幾何学としてのフォント

  1. Googleのようなオープンソースフォントを入手してください( Open Sans および Roboto は非常に人気があります)
  2. OpenTypeなどを使用してフォントの曲線を読み取ります( https://nodebox.github.io/opentype.js/
  3. 文字曲線を三角測量します。非常に高速なので、これが私のお気に入りです https://github.com/mapbox/earcut
  4. 各文字のポリゴンを通常のWebGL三角形として描画します。

利点

  • 非常に高速です。テキストが多く、フル機能のフォントが必要な場合は、これが最善の策です。フォントのスケーリングは、行列演算を介してGPUで実行されます。

短所

  • レンダリングされるフォントの品質は、WebGLブラウザで有効になっているアンチエイリアシングによって異なります。 Safariは8x8AAを実行しますが、他のすべてのブラウザーは4x4しか使用していないため、ブロックされているように見えます。また、モバイルブラウザはAAをまったく有効にしないため、モバイルデバイスでフォントが非常にブロック状に見えます。

キャンバス

これは「オンデマンドダイナミックテクスチャ」とも呼ばれます。ここで説明するように、テキストグリフのみを(オフスクリーン)キャンバスにレンダリングし、WebGLテクスチャとして画面にブリットします。 http://delphic.me.uk/webgltext.html

利点

  • まともな品質。

短所

  • 速度、これがうまくいくかもしれない時間にあなたがレンダリングする必要があるテキストの量に依存します。特に、静的テキストをレンダリングするだけでよい場合。

ゲームAge of Empires IIIはこの方法を使用します。


ビットマップフォント

限られた文字セットと固定文字サイズ(ゲーム)で最高の速度で最高速度が必要な場合は、使用する文字を特徴とする独自のビットマップを作成し、必要に応じて画面にブリットするのがおそらく最善です。これらの文字ビットマップのかなりの数がインターネット上で事前に作成されています。

これは高速で簡単ですが、使用できる言語と文字が制限されますが、たとえばゲームではこれを気にする必要はありません。

利点:

  • わかりやすい
  • テクスチャアトラスを作成するのは簡単です
  • 色付きのフォントを使用できます

短所

  • スケールアップするとひどくぼやけて見える
  • 使用されるすべてのグリフを事前にレンダリングする必要があります
  • フォントサイズごとにテクスチャが必要
  • 最適なテクスチャの使用には テクスチャビンパッキング が必要です。

符号付き距離フィールドフォント

ValveのChrisGreenは、テクスチャに符号付き距離フィールドを使用することに関する「本」を書きました。 2007 SIGGRAPHホワイトペーパーをお読みください "ベクターテクスチャと特殊効果のアルファテスト済み倍率の改善

通常、フォントテクスチャアトラスは this のようになります。 SDFテクスチャは like に見えます。はい、SDFテクスチャアトラスは「現状のまま」レンダリングするとぼやけて見えます。これは、8ビットチャネルが次のようにエンコードされているためです。

  • 0-> -1.0(外部)
  • 255-> +1.0(内部)

利点:

  • 単一のテクスチャを使用して、品質を損なうことなく、フォントを非常に小さい(6ピクセル)から非常に大きい(200ピクセル以上)にスケーリングできます。
  • 多くの場合、アンチエイリアシングは「無料」です。

短所:

  • 使用されるすべてのグリフを事前にレンダリングする必要があります。
  • SDFテクスチャの前処理は、S-L-O-W前処理(約15秒)のため、通常は「オフライン」で行われます。
  • 質の高いアンチエイリアシングを生成する方法を理解している人は多くありません。 smoothstep()fwidth()などのハックは、スクリーンスペースではなくテクスチャスペースで補間するため、スケーリングされた結果の品質が低くなります。また、WebGLのfwidth()が間違った定数を使用することも助けにはなりません。
  • シングルチャネルSDFは、Valveが論文で示唆しているように、エッジを保持しません。彼らの解決策はマルチチャネルSDFを使用することでしたが、詳細は提供されませんでした。 Chlumsky Viktor 修士論文 または彼のオープンソース msdfgen を参照してください。
  • SDFフォントを小さいサイズで使用する場合は、「セルのパディング」または数ピクセルの境界線が必要です。
  • モノクロフォントのみがサポートされています

とはいえ、複数のフォントがある場合、SDFフォントはサイズ(1つだけ必要)と品質(小さいサイズと大きいサイズの両方で見栄えがする)の両方で大きな勝利を収めることができます。

SDFテクスチャを作成する方法

SDFテクスチャとメタデータを生成する使いやすいnpmモジュールがあります ここで入手可能


SDFデモ


GPU上のフォント

人々は、GPUに三次曲線を保存し、スマートフラグメントシェーダーにレンダリングのすべての面倒な作業を行わせることで、テクスチャを完全にバイパスすることを模索しています。

この blog には、2017年2月現在のフォントレンダリングの概要があります。

利点

  • 通常サイズと大きいサイズの高品質グリフ

短所

  • 高いシェーダーコストと複雑さ
  • 小さいサイズで品質の問題があります

GPUフォントのデモ


キャンバスオーバーレイ

現在のプロジェクトでは、HTML5 2Dキャンバスを使用して、テキストやその他の2Dプリミティブをレンダリングし、WebgGLキャンバス上に透明度を使用してオーバーレイします。結果として得られる速度に驚きました。ここで説明する他のすべての方法よりも速度が優れており、品質は非常に優れています。

テキストが静的な2Dであり、3D変換を必要としない限り、これが私の推奨事項です。私のプロジェクトでは、これは以前に使用した方法(Font as Geometry)よりも約2倍高速です。

38
MarkusM

Three.jsのソースコードを見ると、解決策がわかります。

これがthree.jsフォント作成のコードです https://github.com/mrdoob/three.js/blob/master/src/extras/FontUtils.js

一番上に書いてあります

 * For Text operations in three.js (See TextGeometry)
 *
 * It uses techniques used in:
 *
 *  typeface.js and canvastext
 *      For converting fonts and rendering with javascript
 *      http://typeface.neocracy.org
 *
 *  Triangulation ported from AS3
 *      Simple Polygon Triangulation
 *      http://actionsnippet.com/?p=1462
 *
 *  A Method to triangulate shapes with holes
 *      http://www.sakri.net/blog/2009/06/12/an-approach-to-triangulating-polygons-with-holes/

Typeface.jsはフォントデータを提供し、TrueTypeフォントを変換するためのオンラインフォームがあります

その他の解決策:

  1. テキストをビットマップとより高い解像度にレンダリングし、その解像度以下で描画します。

  2. カーブレンダラーを使用します。 ( http://http.developer.nvidia.com/GPUGems3/gpugems3_ch25.html

3
gman

Pixi.jsは、SDFに関する上記の推奨事項に同意します。

https://github.com/PixelsCommander/pixi-sdf-text

彼らは言います(そして彼らはブラウザにとって優れたゲームプロジェクトです)

SDFは、WebGLでテキストを描画するための最も効率的な方法です。特別な種類のラスターアトラスとGLSLシェーダーを使用して、GPU上で非常にパフォーマンスの高い方法でベクトルスケーラブルテキストを描画します。

そして this は、少なくともある時点でそれを行ったMapBoxからのものでした。

0
Lance Pollard