日別アーカイブ: 2008年11月26日

Direct3D11/DirectX11 (14) GPU を使ったアウトラインフォントの描画の(2)

Direct3D 11 の Tessellator を使って、GPU だけでアウトラインフォントの描画を
行ってみました。
↓左からそれぞれ TessFactor (分割数) = 1, 2, 12

tess font 20

改良しました。

(1) 事前の変換処理を自動化した。
(2) isoline ではなく quad プリミティブを使ったテセレートを行っており、
  必要に応じて任意のエッジをテセレートできる。

まだ (1) がやっとなのであまり最適化していません。

前回
Direct3D11/DirectX11 (9) テセレータによるアウトラインフォントの描画など

tess font 21

↑左が前回のもの。2点 X-Y を挿入し、赤 (B-C-X-Y) と 緑 (D-E-X-Y) の 2つの
プリミティブに分解。

右が今回のもの。B-C-D-E で 1つの quad で表現され、必要なエッジのみ分割。
中央の X の位置は事前に求めておく

塗りつぶしたフォントの描画のために、事前にプリミティブに分割します。
思ったよりも難しい処理で、特に細長い三角形ができてしまうとアウトラインから
はみ出します。

tess font 22

↑では波線が本来のカーブです。A の上のエッジが沈み込んで対角線に重なっています。
カーブが極端になると対角線エッジの直線部分が表に出てしまいます。
(前回はこれをうまく解決できなかったので手作業だった)

いろいろと試行錯誤した結果がこれ↓です。

tess font 24
↑ましになったもの。

元↓はこちら。

tess font 23
↑だめな分割 (はみ出ているのはバグ)。

(白線=カーブ、青線=直線、ピンクの点=中心の頂点、水色の点=コントロールポイント)

(1) 角度が一番開いた頂点を求める。
(2) (1) の頂点から直線を引ける他の頂点を探す。
  (エッジと交差しない、かつ隣接でない、かつ文字の外側ではない)
(3) (2) の条件を満たす頂点の中で一番近い頂点と結ぶ。エッジを挿入して領域を分ける
(4) 4 頂点以下の領域ができたら取り除く。

すべての領域が取り除かれるまで再帰的に繰り返します。
比較的細長い領域への分割を避けてぶつ切りになります。

内外判定のために方向をそろえる必要があるため挿入したエッジは両面分必要です。

循環している可能性があるので、(3) で単一のエッジを挿入しても 2つの領域が
できるとは限りません。

(4) の場合くりぬいた領域が裏返しで繋がっている可能性があるため、4頂点以下の
パスのループでも閉じているかどうか判定が必要です。(対角線の可視など)
上の「だめな分割」の図は失敗しています。

領域毎に、アウトラインをじゃましない位置に中心座標を配置します。(上の図のピンクの点)
ただしアンカーが少なくカーブが極端な場合、最適な中心座標は求まらない可能性が
あります。まだ完全には解決していません。

tess font 25
↑ TessFactor = 8 のワイヤー表示です。

●データの準備

xml で対応ツールが比較的多いことと参照しやすいため、SVG / FXG フォーマットを
使用しています。
Scalable Vector Graphics (SVG) 1.1 Specification

含まれるカーブの種類は複数あり、直線部分も Line で出力されるので、変換時に
情報を保存しておきます。
現在エッジ情報は 座標ペア × 4 (Cubic Bezier時) で、Arc は未対応です。

v0.xy, c0.xy, c1.xy, v1.xy

Line 時は c0.xy, c1.xy は未使用。c0.x に範囲外の値を入れて、シェーダー内で
未使用(直線)かどうか判断できるようにしています。

(1) カーブの種類をを考慮してパスデータを 4 パラメータに変換
(2) エッジの方向をノーマライズする

(2) は内外判定のため。進行方向 v0 → v1 に向かって右側が必ず文字の外側など、
どちらかに統一されていれば OK。

次回に続きます。

関連エントリ
Direct3D11/DirectX11 (13) TessFactor とシェーダーリンクの補足など
Direct3D11/DirectX11 (12) テセレータのレンダーステート他
Direct3D11/DirectX11 (11) 互換性とシェーダーの対応表など
Direct3D11/DirectX11 (10) テセレータの補間
Direct3D11/DirectX11 (9) テセレータによるアウトラインフォントの描画など
Direct3D11/DirectX11 (8) テセレータの動作
Direct3D11/DirectX11 (7) テセレータの流れの基本部分
Direct3D11/DirectX11 (6) D3D11 の ComputeShader を使ってみる
Direct3D11/DirectX11 (5) WARP の試し方、Dynamic Shader Linkage
Direct3D11/DirectX11 (4) FeatureLevel と旧 GPU の互換性、テクスチャ形式など
Direct3D11 (DirectX11) シェーダーの書き込み RWBuffer 他
Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
Direct3D11 Technical Preview D3D11の互換性、WARP Driver