フォントが崩れるのの調査(終わり)
(①~⑤は下に掲載)
ようやく新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