📄 d3dfont.cs
字号:
//-----------------------------------------------------------------------------
// File: D3DFont.cs
//
// Desc: Shortcut functions for using DX objects
//
// Copyright (c) 2001-2002 Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
using System;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Direct3D=Microsoft.DirectX.Direct3D;
/// <summary>
/// A generic font class
/// </summary>
public class GraphicsFont
{
public const int MaxNumfontVertices = 50*6;
// Font rendering flags
[System.Flags]
public enum RenderFlags
{
Centered = 0x0001,
TwoSided = 0x0002,
Filtered = 0x0004,
}
private System.Drawing.Font systemFont;
private bool isZEnable = false;
public bool ZBufferEnable { get { return isZEnable; } set { isZEnable = value; } }
string ourFontName; // Font properties
int ourFontHeight;
public int LineHeight { get { return ourFontHeight*2; } }
private Direct3D.Device device;
private TextureState textureState0;
private TextureState textureState1;
private Sampler samplerState0;
private RenderStates renderState;
private Direct3D.Texture fontTexture;
private Direct3D.VertexBuffer vertexBuffer;
private CustomVertex.TransformedColoredTextured[] fontVertices = new CustomVertex.TransformedColoredTextured[MaxNumfontVertices];
private int textureWidth; // Texture dimensions
private int textureHeight;
private float textureScale;
public int spacingPerChar;
private float[,] textureCoords = new float[128-32,4];
// Stateblocks for setting and restoring render states
private StateBlock savedStateBlock;
private StateBlock drawTextStateBlock;
/// <summary>
/// Create a new font object
/// </summary>
/// <param name="f">The font to use</param>
public GraphicsFont(System.Drawing.Font f)
{
ourFontName = f.Name;
ourFontHeight = (int)f.Size;
systemFont = f;
}
public GraphicsFont(string fontName) : this(fontName, FontStyle.Regular, 12){}
public GraphicsFont(string fontName, FontStyle style) : this(fontName, style, 12){}
/// <summary>
/// Create a new font object
/// </summary>
/// <param name="fontName">The name of the font</param>
/// <param name="style">The style</param>
/// <param name="size">Size of the font</param>
public GraphicsFont(string fontName, FontStyle style, int size)
{
ourFontName = fontName;
ourFontHeight = size;
systemFont = new System.Drawing.Font( fontName, ourFontHeight, style);
}
/// <summary>
/// Initialize the device objects
/// </summary>
/// <param name="dev">The grpahics device used to initialize</param>
public void InitializeDeviceObjects(Device dev)
{
if (dev != null)
{
// Set up our events
dev.DeviceReset += new System.EventHandler(this.RestoreDeviceObjects);
}
// Keep a local copy of the device
device = dev;
textureState0 = device.TextureState[0];
textureState1 = device.TextureState[1];
samplerState0 = device.SamplerState[0];
renderState = device.RenderState;
// Establish the font and texture size
textureScale = 1.0f; // Draw fonts into texture without scaling
// Large fonts need larger textures
if( ourFontHeight > 60 )
textureWidth = textureHeight = 2048;
else if( ourFontHeight > 30 )
textureWidth = textureHeight = 1024;
else if( ourFontHeight > 15 )
textureWidth = textureHeight = 512;
else
textureWidth = textureHeight = 256;
// If requested texture is too big, use a smaller texture and smaller font,
// and scale up when rendering.
Direct3D.Caps d3dCaps = device.DeviceCaps;
if( textureWidth > d3dCaps.MaxTextureWidth )
{
textureScale = (float)d3dCaps.MaxTextureWidth / (float)textureWidth;
textureWidth = textureHeight = d3dCaps.MaxTextureWidth;
}
Bitmap bmp = new Bitmap( textureWidth, textureHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb );
Graphics g = Graphics.FromImage( bmp );
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
g.TextContrast = 0;
string str;
float x = 0;
float y = 0;
Point p = new Point(0, 0);
Size size = new Size(0,0);
// Calculate the spacing between characters based on line height
size = g.MeasureString( " ", systemFont).ToSize();
x = spacingPerChar = (int) Math.Ceiling( size.Height * 0.3 );
for( char c = (char)32; c < (char)127; c++ )
{
str = c.ToString();
// We need to do some things here to get the right sizes. The default implemententation of MeasureString
// will return a resolution independant size. For our height, this is what we want. However, for our width, we
// want a resolution dependant size.
Size resSize = g.MeasureString( str, systemFont).ToSize();
size.Height = resSize.Height + 1;
// Now the Resolution independent width
if (c != ' ') // We need the special case here because a space has a 0 width in GenericTypoGraphic stringformats
{
resSize = g.MeasureString( str, systemFont, p, StringFormat.GenericTypographic).ToSize();
size.Width = resSize.Width;
}
else
size.Width = resSize.Width;
if( ( x + size.Width + spacingPerChar ) > textureWidth )
{
x = spacingPerChar;
y += size.Height;
}
if (c != ' ') // We need the special case here because a space has a 0 width in GenericTypoGraphic stringformats
g.DrawString( str, systemFont, Brushes.White, new Point((int)x, (int)y), StringFormat.GenericTypographic);
else
g.DrawString( str, systemFont, Brushes.White, new Point((int)x, (int)y));
textureCoords[c-32,0] = ((float) ( x + 0 - spacingPerChar )) / textureWidth;
textureCoords[c-32,1] = ((float) ( y + 0 + 0 )) / textureHeight;
textureCoords[c-32,2] = ((float) ( x + size.Width + spacingPerChar )) / textureWidth;
textureCoords[c-32,3] = ((float) ( y + size.Height + 0 )) / textureHeight;
x += size.Width + (2 * spacingPerChar);
}
// Create a new texture for the font from the bitmap we just created
fontTexture = Texture.FromBitmap(device, bmp, 0, Pool.Managed);
RestoreDeviceObjects(null, null);
}
/// <summary>
/// Restore the font after a device has been reset
/// </summary>
public void RestoreDeviceObjects(object sender, EventArgs e)
{
vertexBuffer = new VertexBuffer( typeof(CustomVertex.TransformedColoredTextured), MaxNumfontVertices,
device, Usage.WriteOnly | Usage.Dynamic, 0, Pool.Default );
// Create the state blocks for rendering text
for( int which=0; which < 2; which++ )
{
device.BeginStateBlock();
device.SetTexture( 0, fontTexture );
if ( isZEnable )
renderState.ZBufferEnable = true;
else
renderState.ZBufferEnable = false;
renderState.AlphaBlendEnable = true;
renderState.SourceBlend = Blend.SourceAlpha;
renderState.DestinationBlend = Blend.InvSourceAlpha;
renderState.AlphaTestEnable = true;
renderState.ReferenceAlpha = 0x08;
renderState.AlphaFunction = Compare.GreaterEqual;
renderState.FillMode = FillMode.Solid;
renderState.CullMode = Cull.CounterClockwise;
renderState.StencilEnable = false;
renderState.Clipping = true;
device.ClipPlanes.DisableAll();
renderState.VertexBlend = VertexBlend.Disable;
renderState.IndexedVertexBlendEnable = false;
renderState.FogEnable = false;
renderState.ColorWriteEnable = ColorWriteEnable.RedGreenBlueAlpha;
textureState0.ColorOperation = TextureOperation.Modulate;
textureState0.ColorArgument1 = TextureArgument.TextureColor;
textureState0.ColorArgument2 = TextureArgument.Diffuse;
textureState0.AlphaOperation = TextureOperation.Modulate;
textureState0.AlphaArgument1 = TextureArgument.TextureColor;
textureState0.AlphaArgument2 = TextureArgument.Diffuse;
textureState0.TextureCoordinateIndex = 0;
textureState0.TextureTransform = TextureTransform.Disable; // REVIEW
textureState1.ColorOperation = TextureOperation.Disable;
textureState1.AlphaOperation = TextureOperation.Disable;
samplerState0.MinFilter = TextureFilter.Point;
samplerState0.MagFilter = TextureFilter.Point;
samplerState0.MipFilter = TextureFilter.None;
if( which==0 )
savedStateBlock = device.EndStateBlock();
else
drawTextStateBlock = device.EndStateBlock();
}
}
/// <summary>
/// Draw some text on the screen
/// </summary>
public void DrawText( float xpos, float ypos, Color color, string text)
{
DrawText( xpos, ypos, color, text, RenderFlags.Filtered );
}
/// <summary>
/// Draw some text on the screen
/// </summary>
public void DrawText( float xpos, float ypos, Color color, string text, RenderFlags flags)
{
if( text == null )
return;
// Setup renderstate
savedStateBlock.Capture();
try
{
drawTextStateBlock.Apply();
device.SetTexture( 0, fontTexture );
device.VertexFormat = CustomVertex.TransformedColoredTextured.Format;
device.PixelShader = null;
device.SetStreamSource( 0, vertexBuffer, 0);
// Set filter states
if( (flags & RenderFlags.Filtered) != 0 )
{
samplerState0.MinFilter = TextureFilter.Linear;
samplerState0.MagFilter = TextureFilter.Linear;
}
// Adjust for character spacing
xpos -= spacingPerChar;
float fStartX = xpos;
// Fill vertex buffer
int iv = 0;
int dwNumTriangles = 0;
foreach( char c in text )
{
if( c == '\n' )
{
xpos = fStartX;
ypos += (textureCoords[0,3]-textureCoords[0,1])*textureHeight;
}
if( (c-32) < 0 || (c-32) >= 128-32 )
continue;
float tx1 = textureCoords[c-32,0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -