XNA:システムフォントでのテキスト出力

XNAは、事前に準備されたビットマップフォントでのみテキスト出力を想定しています。 そして、そうです。 OSに依存しない高速で予測可能なテキストサイズ。
私の場合、正反対が必要でした。 ヘッドセットとフォントサイズの任意の選択、および低パフォーマンス要件。 タスクは非常に困難でした。 インターネットにはほとんど情報がなく、非常に断片化されていました。


条件:2Dアプリケーション、ユーザーはいつでもヘッドセット、スタイル、フォントサイズを変更できる必要があります。

解決策は非常に簡単です。 目的のテキストでビットマップを作成し、それからテクスチャを作成して表示します。

GDIツールを使用してビットマップを作成します。
/// <summary> Draw text on bitmap </summary> /// <returns>Bitmap with text</returns> private System.Drawing.Bitmap Layout() { // Get font var font = new System.Drawing.Font( fontName, fontSize, fontStyle); // Get text size var bitmap = new System.Drawing.Bitmap( 1, 1 ); var graphics = System.Drawing.Graphics.FromImage( bitmap ); var textSize = graphics.MeasureString( text, font ); // Draw text on bitmap bitmap = new System.Drawing.Bitmap( (int) textSize.Width, (int) textSize.Height ); graphics = System.Drawing.Graphics.FromImage( bitmap ); graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; graphics.DrawString( text, font, new System.Drawing.SolidBrush( this.color ), 0f, 0f ); return bitmap; } 


ビットマップをテクスチャに変換
 /// <summary> Create texture from bitmap </summary> /// <param name="gdev">Graphic device</param> /// <param name="bmp">Bitmap</param> /// <returns>Texture</returns> private static Texture2D TextureFromBitmap(GraphicsDevice gdev, System.Drawing.Bitmap bmp) { Stream fs = new MemoryStream(); bmp.Save(fs, System.Drawing.Imaging.ImageFormat.Png); var tex = Texture2D.FromStream(gdev, fs); fs.Close(); fs.Dispose(); return tex; } 


テクスチャを表示します
 public void Draw() { var spriteBatch = new SpriteBatch( graphicsDevice ); spriteBatch.Begin(); spriteBatch.Draw( texture, coordinate, new Rectangle(0, 0, texture.Width, texture.Height), Color.White, 0f, new Vector2(0, 0), 1.0f / textureDownsizeRatio, SpriteEffects.None, 0); spriteBatch.End(); } 


その結果、エッジが破れたテキストが得られ、スムージングが完全に欠けています。


ビットマップをテクスチャに変換するのは簡単な手順ではありませんでした。
ここにあるメソッド

アルファチャネルを正しく転送するには、TextureFromBitmapメソッドで追加の手順が必要です。
最初に、ビットマップの色に関するデータをテクスチャに描画し、次にアルファチャネルに関する情報を描画します。
 /// <summary> Create texture from bitmap </summary> /// <param name="gdev">Graphic device</param> /// <param name="bmp">Bitmap</param> /// <returns>Texture</returns> private static Texture2D TextureFromBitmap(GraphicsDevice gdev, System.Drawing.Bitmap bmp) { Stream fs = new MemoryStream(); bmp.Save(fs, System.Drawing.Imaging.ImageFormat.Png); var tex = Texture2D.FromStream(gdev, fs); fs.Close(); fs.Dispose(); // Setup a render target to hold our final texture which will have premulitplied alpha values var res = new RenderTarget2D(gdev, tex.Width, tex.Height); gdev.SetRenderTarget(res); gdev.Clear(Color.Black); // Multiply each color by the source alpha, and write in just the color values into the final texture var blendColor = new BlendState { ColorWriteChannels = ColorWriteChannels.Red | ColorWriteChannels.Green | ColorWriteChannels.Blue, AlphaDestinationBlend = Blend.Zero, ColorDestinationBlend = Blend.Zero, AlphaSourceBlend = Blend.SourceAlpha, ColorSourceBlend = Blend.SourceAlpha }; var spriteBatch = new SpriteBatch(gdev); spriteBatch.Begin(SpriteSortMode.Immediate, blendColor); spriteBatch.Draw(tex, tex.Bounds, Color.White); spriteBatch.End(); // Now copy over the alpha values from the PNG source texture to the final one, without multiplying them var blendAlpha = new BlendState { ColorWriteChannels = ColorWriteChannels.Alpha, AlphaDestinationBlend = Blend.Zero, ColorDestinationBlend = Blend.Zero, AlphaSourceBlend = Blend.One, ColorSourceBlend = Blend.One }; spriteBatch.Begin(SpriteSortMode.Immediate, blendAlpha); spriteBatch.Draw(tex, tex.Bounds, Color.White); spriteBatch.End(); // Release the GPU back to drawing to the screen gdev.SetRenderTarget(null); return res; } 


これで満足のいく結果が得られました。


ソースコード

問題は次のとおりです。
1.ゆっくり。 ゲームでこの方法を使用してはいけません。さらに、モバイルデバイスでも使用してください。
2.信頼できません。 必要なフォントがシステムにない可能性があります。
3.画面に表示されるテキストの量を追跡し、非表示のテキストをトリミングすることをお勧めします。 最大テクスチャサイズは2048x2048です。 ビットマップサイズが大きい場合、テクスチャは最大サイズで作成され、ビデオカードによって目的のサイズに引き伸ばされます。 テキストはぼやけます。

アンマネージコードを使用すると、TextureFromBitmapでPNGに変換する必要がなくなります。 ここに例を見ることができます

Source: https://habr.com/ru/post/J135851/


All Articles