読者です 読者をやめる 読者になる 読者になる

GameProgrammar's Night

ゲームプログラム系の覚え書き

DistanceFieldTexture実験結果

DistanceFieldTexture DirectX シェーダー HLSL

オレオレツールのアルゴリズムのミスを発見したので、現在はSDFツールと同等のクオリティが出るようになっています。

 というわけで、自作DistanceFieldTexture作成ツール(以下オレオレツール)を作って実験してみました。ツール比較用にgamedev.netのここで公開されてるツール(以下SDFツール)も使ってみました。

なにはともあれ結果

元画像

f:id:katze_7514:20130705145449p:plain
これは縮小版256x256。実際には2048x2048のものを使ってます。

オレオレツール

出力されたDistanceFieldTexture

f:id:katze_7514:20130705144119p:plain
64x64

描画結果

左から等倍、3倍、5倍
f:id:katze_7514:20130705144054p:plain

SDFツール

出力されたDistanceFieldTexture

f:id:katze_7514:20130705144111p:plain
64x64

描画結果

左から等倍、3倍、5倍
f:id:katze_7514:20130705144104p:plain

解説

 DistanceFieldTextureは、各色に入れた距離の値のみ使うことにして、文字色はデフューズカラーとして与えたものをそのまま使ってます。
 論文にあった通り、アルファテストを有効にして、距離の値が0.5以上を描画して0.5未満をα値を0にしてアルファテストで落ちるようにしてます。
 以下な感じ

// ピクセルシェーダー
float4 ps_df_color(float2 uv : TEXCOORD0, float4 color : COLOR0) : COLOR0
{
  float4 OUT = color;
  float4 df = tex2D(smp, uv);
  OUT.a = df.r>=0.5;
  return OUT;
}

 確かに拡縮しても字形は維持されてくっきりすっきり表示されます。元データの雰囲気をどこまで残せるかは、DistanceField計算アルゴリズム次第って感じですね。
 オレオレツールは、255として扱う最大長を与えて単純に距離を計算してるだけなんですが、かなりイマイチ……。
 オレオレよりマシに出てるSDFツールは、距離計算までは同じっぽいんですが、そのあと0~255変換の時によくわからん式が挟まってるのでそれが上手く行ってるっぽい?
 ナイスなDistanceField計算アルゴリズムを要研究って感じみたいです。日本語フォントに適したアルゴリズム知ってるよ! という方がいたらぜひ教えて頂きたく候

128×128のDistanceFieldTexture(SDFツール出力)を使うと

64×64とサイズを合わせるために、左から0.5倍、1.5倍、2.5倍

f:id:katze_7514:20130705155146p:plain

f:id:katze_7514:20130705184322p:plain

より字形が綺麗に残る感じですかね。
 やっぱり「DistanceFieldTextureサイズ、距離計算アルゴリズム、エッジとする距離の閾値」あたりが要研究。字形のベースとなる距離255を良い感じに残すのが肝なような気がします。

おまけ

シェーダーを以下のように変形させると

// ピクセルシェーダー
float4 ps_df_color(float2 uv : TEXCOORD0, float4 color : COLOR0) : COLOR0
{
  float4 OUT = color;
  float4 df = tex2D(smp, uv);
  OUT.a = df.r>=0.5;
  if(OUT.a==0)
  {
    OUT.a = smoothstep(0.2, 0.8, df.r);
    OUT.r = 0;
    OUT.g = 0;
    OUT.b = 0;
  }
  return OUT;
}


f:id:katze_7514:20130705144050p:plain

 縁取りができました!
 論文に書いてあったネタではありますが、シェーダーレベルで装飾ができるのは結構魅力