フォントが崩れるのの調査(終わり)

(①~⑤は下に掲載)

ようやく新SpriteFontの実装が終わりました。
左が修正前、右が修正後。(Windows10で実行)


ゲーム基盤を修正しただけなので、実際のゲームはdll入れ替えだけで実行できました。
下がWindows10での実行画面。



フォントが崩れるのの調査⑤


④でTextOutは早くない!と書きましたが、やはり早かったです。
DrawStringに比べると、25%くらい早いですかね。(4秒が3秒になる感じ)

ただ、SpriteFont作成のコストが思ったよりも多くなく、TextOutにしても劇的に変わらなそうなので、DrawStringのまま行こうと思います。

下記が実験結果。
byte[]でAlpha描画を直接行う方法((23)以降)でなかなかパフォーマンスが上がらず、作業遅延してしまいましたが、
その原因が、
  「Bitmap.Width/Bitmap.Heightへのアクセスは、コストが高い」
という結論になりました。

現在、60pt.フォントの(26)で、1800ms程度かかっていますが、
Bitmap.Width/Heightへのアクセスの修正前は、およそ27秒程度かかっていました。
ループ内のBitmap.Width/Heightへのアクセスはたった3回なのですが、処理時間全体の93%程度を、Bitmap.Width/Heightのアクセスに占めていたようです。


今回の対応で、24ptの一番右(フォント周りに4pt分の光沢)が、
  (6)DrawString版 ・・・ 2300ms / 1000回
  (26)byte[]でAlpha版 ・・・ 900ms / 1000回
になるので、それなりの高速化が見込めそうです。

ただし、今回の実験結果が、予想していたより早かったので、他にも処理が重い要因が潜んでいそう・・・



(3)~(6)  : 従来のDrawStringバージョン
(7)~(10)  : 従来のDrawStringバージョンから、CompositeMode=SourceOverに変更したもの
(11)~(14) : TextOutバージョン。http://theartofdev.com/2013/08/12/using-native-gdi-for-text-rendering-in-c/を参考にしたもの
(15)~(18) : TextOutバージョン。必要な部分のみ抜き出したバージョン
(19)~(22) : (15)~(22)に、毎回のフォント設定を追加したもの。ほとんど変わりませんね
(23)~(26) : DrawString + byte[]でAlpha設定。
(27)~(30) : (23)~(26)のループをParallel.Foreachにしたもの。。。遅い。。。VisualStudioの診断ツールをみたところ、GCが動きまくっていました。。。




フォントが崩れるのの調査④ …… TextOutは早くない!!


ToDoに記載していた、SpriteFontの高速化でも検討していたのが
 ・TextOutを使用する
 ・シャドー編集をbyte[]直接加工して対応する。
の2点。

ですが、1点目のTextOutは思ったほど早くないという事実にぶつかりました。

計測1.長文文字列(26文字) 10,000回描画の場合
 Graphics.DrawString …… 400~900ms
 TextRendere.DrawText …… 4000~4800ms
 TextOut ……………………… 100~250ms

計測2.1文字 10,000回描画の場合
 Graphics.DrawString …… 70~140ms
 TextRendere.DrawText …… 4000~4300ms
 TextOut ……………………… 60~150ms

ばらつきは大きいですが、1文字ずつ表示する場合は、DrawStringもTextOutもそれほど変わらないようです。
(TextOutは、Fontを毎回指定してもしなくても、速度は変わりませんでした)

CursedDungeon(のゲーム基盤であるGameBox)では、1文字ずつ描画しますので、従来通り(使い慣れた)DrawStringで実装しようかと思います。


フォントが崩れるのの調査③


Windows8以降、Graphics.DrawStringをCompositingMode.SourceCopyで行うと
この事象が発生するようです。



フォントが崩れるのの調査②


System.Drawing.Bitmapを作成するときのPixelFormatの違いによるものと推測中。

参考。左:PixelFormat.Format32bppArgb、右:PixelFormat.Format24bppRgb


ちなみにデフォルト値はPixelFormat.Format32bppArgbです。




フォントが崩れるのの調査①


推測としては、Win7とWin10の違いだけど、他の理由かもしれない。



Face画像


  • SpriteDrawerクラスのDrawSpriteを使用
  • ShaderResourceViewをd3dContext.Drawで描画
  • System.Drawing.Bitmapに画像をロード
  • Bitmap.LockBitsでBitmapDataを取得
  • BitmapDataからMarshal.Copyでbyte[]を取得
  • d3dDeviceContext.UpdateSubresourceで、byte[]をDirect3D11.Texture2Dに格納

この場合はうまくいく


Panel画像


風景画像も正しく表示されていました。

  • System.Drawing.Bitmapに画像をロード
  • Bitmap.LockBitsでBitmapDataを取得
  • BitmapDataからMarshal.Copyでbyte[]を取得
  • d3dDeviceContext.UpdateSubresourceで、byte[]をDirect3D11.Texture2Dに格納

同じ流れを2か所にコーディングしてた。ショック!!


フォント


問題のフォントです。

  • System.Drawing.BitmapをFillRectangle(Transparent)で透明に
  • System.Drawing.Graphics.DrawStringで文字を描画
  • Bitmapを、「Panel画像」と同じメソッドでShaderResourceViewに変換

なので、DrawStringが問題なのかなぁ・・・

フォント定義


ちなみにinifile定義はこんな感じ
顔画像の赤文字の"hp"、青文字の"mp"はMS 明朝ですね。

[SpriteFont.Font]
Default = MS 明朝,20,Bold,true,-1
DefaultProportional = MS P明朝,20,Bold,false,-1
System = MS 明朝,12,Regular,true,0
MessageFont = MS P明朝,32,Bold,false,0
CenterMessageFont = MS P明朝,72,Bold,false,-8
PopupMessageFont = MS P明朝,20,Bold,false,-2

Spell = Times New Roman,16,BoldItalic,false,-4
SpellPopup = Times New Roman,20,BoldItalic,false,-5
SpellMessage = Times New Roman,32,BoldItalic,false,-6

CharacterSheet = Default #Alias
CharacterSheetName = DefaultProportional #Alias
CharacterSheetSmall = MS P明朝,15,Bold,false,0
CharacterSheetLabel = Spell #Alias
HPMP = MS 明朝,24,Bold,true,0
HPMPLabel = Times New Roman,20,Regular,false,-1
AC = MS 明朝,14,Bold,true,0
Condition = MS 明朝,21,Bold,true,0
DateTime = Default #Alias




最終更新:2016年04月03日 17:51