D3D9学习笔记之字体

学习目标:

  • 了解如何用 ID3DXFont 接口绘制文本
  • 了解如何使用 CD3DFont 类绘制文本
  • 了解如何计算应用程序每秒所绘制的帧数
  • 了解如何用 D3DXCreateText 函数创建并绘制 3D 文本

ID3DXFont 接口

D3DX 库提供接口 ID3DXFont ,该接口用于在 Direct3D 应用程序中绘制文本。该接口内部使用 GDI(图像设备接口)来绘制文本,因此该接口在性能上略有损失。然而正是由于该接口使用了 GDI,所以才能够处理一些复杂的字体和格式。

创建一个 ID3DXFont 接口对象
我们可以用 D3DXCreateFontIndirect 函数来创建一个 ID3DXFont 接口对象。

HRESULT D3DXCreateFontIndirect(
	LPDIRECT3DDEVICE9 pDevice,			//要与字体关联的设备
	const D3DXFONT_DESC* pDesc,			//D3DXFONT_DESC字符串结构
	LPD3DXFONT* ppFont					//返回创建的字体
);

下面的代码段演示了如何使用该函数

D3DXFONT_DESC df;
ZeroMemory(& df, sizeof(D3DXFONT_DESC));
df.Height = 25;							//高度,逻辑单位
df.Width = 12;							//宽度,逻辑单位
df.Weight = 500;						//粗体范围
df.MipLevels = D3DX_DEFAULT;			
df.Italic = false;
df.CharSet = DEFAULT_CHARSET;
df.OutputPrecision = 0;
df.Quality = 0;
df.PitchAndFamily = 0;
strcpy(df.FaceName, "Times New Roman");//字体样式

ID3DXFont* font = 0;
D3DXCreateFontIndirect(Device, & df, & font);

为了对我们想要创建的字体进行描述,必须先填充 D3DXFONT_DESC 结构。

绘制文本:
一旦获取了 ID3DXFont 接口的指针,只需调用方法 ID3DXFont::DrawText 即可轻而易举的完成文本的绘制。

INT ID3DXFont::DrawText(
	LPD3DXSPRITE pSprite,	//指定字符串所属的ID3DXSprite对象接口,可设为0或NULL,表示在当前中绘制字符串
	LPCSTR pString,			//指向将要绘制的字符串的指针
	INT Count,				//字符串中的字符个数,若该值为-1,则认为参数pString指向一个以NULL结尾的字符串。ID3DXFont::DrawText 方法将自动对字符个数进行统计。
	LPRECT pRect,			//指定字符串绘制的矩形区域的位置
	DWORD Format,			//指定了字符串在pRect指定的矩形区域中的格式化方法,该方法是一系列可选标记的某一个或某种组合,详情参阅SDK文档
	D3DCOLOR Color			//文本颜色
);

例:

Font->DrawText(
	NULL,
	"Hello, World",
	-1,
	& rect,
	DT_TOP | DT_LEFT,
	0xff000000
);

CD3DFont

该类无法使用

由于 CD3DFont 类绘制文本时使用的是 Direct3D 而非 GDI,所以其绘制的速度比 ID3DXFont 要快的多,但该类也有缺陷,CD3DFont 类不支持 ID3DXFont 所支持的那些复杂的字体和格式。如果您很在意速度,而且简单字体即能满足需求,CD3DFont 类便是一个很好的选择。

创建 CD3DFont 类的实例
要创建 CD3DFont 类的实例,我们只需要像普通C++对象那样进行实例化即可,下面是该类的构造函数原型:

	CD3DFont(const TCHAR * strFontName, DWORD dwHeight, DWORD dwFlags = 0L)
  • StrFontName 一个以 NULL 结尾的字符串,它指定了字体的名称
  • dwHeight 字体的高度
  • dwFlags 创建标记,可选,该参数为0或以下标记的组合:
    D3DFONT_BOLD , D3DFONT_ITALIC , D3DFONT_ZENABLE

当我们实例化一个CD3DFont 类的对象后,必须调用如下方法来对字体进行初始化:

Font = new CD3DFont("Times New Roman",16,0);
Font->InitDeviceObject(Device);
Font->RestoreDeviceObjects();

绘制文本
既然我们已经创建来一个 CD3DFont 对象并对其进行了初始化,现在我们就可绘制一些文本,可用如下函数实现文本的绘制:

HRESULT CD3DFont::DrawText(	
	FLOAT x, 					//屏幕坐标系中绘制起点的x坐标
	FLOAT y,					//屏幕坐标系中绘制起点的y坐标
	DWORD dwColor,				//文本的颜色
	const TCHAR* strText, 		//指向所要绘制文本的指针
	DWORD dwFlags = 0);			//绘制标记,可选,该参数为0或下列标记的组合
			D3DFONT_CENTERED	D3DFONT_TWOSIDED	D3DFONT_FILTERED

清理
在删除一个 CD3DFont 类的对象之前,我们必须首先调用一些清理函数,如下面的代码段所示:

Font->InvalidateDeviceObjects();
Font->DeleteDeviceObjects();
delete Font;

D3DXCreateText函数

该函数用于创建文本的 3D网格
D3DXCreateText 函数的原型为:

HRESULT D3DXCreateText(
	LPDIRECT3DDEVICE9 pDevice,				//指向与网格相关的设备
	HDC hDC,								//一个设备环境句柄,它包含了将用来创建网格的字体的相关信息
	LPCTSTR pText,							//指向确定所要用于生成文本的字符串指针
	FLOAT Deviation,						//True Type 字体轮廓的最大弦偏差,该值必须为负,弦偏差等于原始字体的一个设计单位
	FLOAT Extrusion,						//沿Z轴负方向度量的字体深度
	LPD3DXMESH* ppMesh,						//返回所创建的网格
	LPD3DXBUFFER* ppAdjacency,				//返回所创建的网格的邻接信息,如果不需要,指定为NULL
	LPGLYPHMETRICSFLOAT pGlyphMetrics		//指向LPGLYPHMETRICSFLOAT 类型结构数组的指针,该结构包含了字形的度量数据,如果不关心字形的度量数据,可将该值设为0
);
//如果调用成功,该函数返回 D3D_OK

例程代码

//获取设备上下文的句柄
HDC hdc = CreateCompatibleDC(0);
HFONT hFont;
HFONT hFontOld;

//填写描述字体属性的logFont结构
LOGFONT lf;
ZeroMemory(&lf, sizeof(LOGFONT));

lf.lfHeight 		=25;		//以逻辑单位表示
lf.lfWidth			=12;		//以逻辑单位表示
lf.lfEscapement		=0;
lf.lfOrientation	=0;
lf.lfWeight			=500;		//粗体,范围0(浅色)-1000(粗体)
lf.lfItalic			=false;
lf.lfUnderline 		=false;
lf.lfStrikeOut		=false;
lf.lfCharSet		=DEFAULT_CHARSET;	
lf.lfOutPrecision	=0;
lf.lfClipPrecision	=0;
lf.lfQuality		=0;
lf.lfPitchAndFamily	=0;
strcpy(lf.lfFaceName, "Times New Roman");	//字体样式

//创建字体并使用设备上下文选择该字体
hFont = CreateFontIndirect(&lf);
hFontOld = (HFONT)SelectObject(hdc, hFont);

//基于hdc中选定的字体创建文本网格
D3DXCreateText(Device, hdc, "Direct3D", 0.001f, 0.4f, &Text, 0, 0);

//重置旧字体并释放资源
SelectObject(hdc, hFontOld);
DeleteObject(Hfont);
DeleteDC(hdc);

//绘制3D文本网格仅需要调用网格的 DrawSubset 方法即可
Text->DrawSubset(0);

总结

  • 当需要支持复杂的字体和格式时,可使用 ID3DXFont 接口来绘制文本,该接口使用 GDI 绘制文本,相应的在性能上会有一定的损失
  • DC3DFont 类可实现简单文本的快速绘制,该类使用了Direct3D,所以速度比 ID3DXFont 快许多
  • D3DXCreateText 函数可用来创建3D的文本字符串网格,可以像模型一样操作

你可能感兴趣的:(D3D9学习笔记之字体)