分享
 
 
 

在DirectX 9.0中渲染文字

王朝other·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

9. 字体

本文翻译自《Introduction to 3D Game Programming with DirectX 9.0》第九章“Fonts”,敬请斧正!

在游戏中,文字信息的显示是必不可少的。本章将讨论在D3D中使用的三种显示字体的方法。同样,这里只列出每种方法的演示程序的主体框架。学完本章将达到如下目标:

l 学习如何使用ID3DXFont接口渲染文字

l 学习如何使用CD3DFont类渲染文字

l 学习计算游戏帧速度的方法

l 学习使用D3DXCreateText函数创建3D文字

9.1. ID3DXFont

要在D3D程序输出文字,使用D3DX库提供的ID3DXFont接口很方便。其实该接口是使用GDI实现的,所以,其执行效率有所降低,但是它可以很方便地处理复杂的字体和格式。

9.1.1. 创建一个ID3DXFont

可使用D3DXCreateFontIndirect函数创建ID3DXFont:

HRESULT WINAPI D3DXCreateFontIndirect(

LPDIRECT3DDEVICE9 pDevice,

CONST D3DXFONT_DESC *pDesc,

LPD3DXFONT *ppFont

);

译者注:我所使用的DirectX SDK是Microsoft DirectX 9.0 SDK Update (Summer 2004),也就是使用DirectX 9.0c的那个版本,在较早的版本里,该函数的原型有所不同:第二个参数为CONST LOGFONT *pLogFont,它是GDI中的结构。以后,如无特别说明,将以DirectX 9.0 SDK Update (Summer 2004)中声明的函数原型为准,特此声明!

使用这个函数时,需要一个D3DXFONT_DESC结构:

D3DXFONT_DESC d3dFont;

memset(&d3dFont,0,sizeof(d3dFont));

d3dFont.Height=25; // in logical units

d3dFont.Width=12; // in logical units

d3dFont.Weight=500;// boldness, range 0(light) - 1000(bold)

d3dFont.Italic=FALSE;

d3dFont.CharSet=DEFAULT_CHARSET;

strcpy(d3dFont.FaceName,"Times New Roman");

ID3DXFont* font=0;

D3DXCreateFontIndirect(Device,&d3dFont,&font);

如果你使用的是LOGFONT结构,则:

LOGFONT lf;

ZeroMemory(&lf, sizeof(LOGFONT));

lf.lfHeight = 25; // in logical units

lf.lfWidth = 12; // in logical units

lf.lfWeight = 500; // boldness, range 0(light) - 1000(bold)

lf.lfItalic = false;

lf.lfUnderline = false;

lf.lfStrikeOut = false;

lf.lfCharSet = DEFAULT_CHARSET;

strcpy(lf.lfFaceName, "Times New Roman"); // font style

ID3DXFont* font = 0;

D3DXCreateFontIndirect(Device, &lf, &font);

另外,还可以使用D3DXCreateFont函数创建ID3DXFont的对象。

9.1.2. 绘制文字

得到ID3DXFont接口后,绘制文字就很简单了,只需要调用ID3DXFont::DrawText方法:

INT ID3DXFont::DrawText(

LPD3DXSPRITE pSprite,

LPCTSTR pString,

INT Count,

LPRECT pRect,

DWORD Format,

D3DCOLOR Color

);

l pSprite –输出目标,为ID3DXSprite对象指针,可以为NULL值,此时字符串输出到默认对象

l pString –需要输出的字符串

l Count –字符串的字符数,如果为-1,则以0字符为结束标志

l pRect –绘制字符串的区域

l Format –文字的输出格式

l Color –文字颜色

例如,可以这样使用该方法:

Font->DrawText(NULL,

"Hello World", // String to draw.

-1, // Null terminating string.

&rect, // Rectangle to draw the string in.

DT_TOP | DT_LEFT, // Draw in top-left corner of rect.

0xff000000); // Black.

9.1.3. 计算帧速率

帧速率用FPS(Frame per Second)表示。首先声明三个全局变量:

DWORD FrameCnt; // The number of frames that have occurred.

float TimeElapsed; // The time that has elapsed so far.

float FPS; // The frames rendered per second.

每秒计算一次FPS,这里计算的是平均值。我们也可以有足够的时间去读FPS值,而不至于因FPS的快速变化而产生较大误差。

每渲染一帧,累加一次帧数和所用的时间值:

FrameCnt++;

TimeElapsed += timeDelta;

这里的timeDelta表示两帧间的时间间隔。每过去一秒,就可以使用下面的公式计算FPS了:

FPS = (float)FrameCnt / TimeElapsed;

计算完成后,需要将FrameCnt和TimeElapsed重新置0,这样下一次的计算结果才正确:

void CalcFPS(float timeDelta)

{

FrameCnt++;

TimeElapsed += timeDelta;

if(TimeElapsed >= 1.0f)

{

FPS = (float)FrameCnt / TimeElapsed;

TimeElapsed = 0.0f;

FrameCnt = 0;

}

}

9.2. CD3DFont

在DirectX SDK的安装目录下,提供了很多有用的代码CD3DFont类就位于其中。该类使用纹理三角形和Direct3D渲染文字,而不是通过GDI渲染,所以,其效率高于ID3DXFont。但是,CD3DFont不支持复杂的字体和文本格式,如果只需要高速渲染简单的字体,CD3DFont应是首选。

使用CD3DFont类时,需要加入以下源文件:d3dfont.h,d3dfont.cpp,d3dutil.h,d3dutil.cpp,dxutil.h,dxutil.cpp。这些文件可在DirectX SDK的安装目录下找到。在DirectX 9.0 SDK Update (Summer 2004)中,该类却消失了,所以,该节内容只适用于较早的DirectX 9.0 SDK版本!

9.2.1. 创建CD3DFont对象

创建CD3DFont的对象,就像创建一个普通的C++对象一样,其构造函数如下:

CD3DFont(const TCHAR* strFontName, DWORD dwHeight, DWORD dwFlags=0L);

l strFontName –所使用的字体名称

l dwHeight –字体高度

l dwFlags –可选的标志,如D3DFONT_BOLD、D3DFONT_ITALIC、D3DFONT_ZENABLE等。

得到CD3DFont对象后,还需按顺序进行初始化,如:

Font = new CD3DFont("Times New Roman", 16, 0); // instantiate

Font->InitDeviceObjects( Device );

Font->RestoreDeviceObjects();

9.2.2. 绘制文字

使用CD3DFont对象的如下方法渲染文字:

HRESULT CD3DFont::DrawText(FLOAT x, FLOAT y, DWORD dwColor,

const TCHAR* strText, DWORD dwFlags=0L);

l x –屏幕的x坐标

l y –屏幕的y坐标

l dwColor –文字的颜色

l strText –要绘制的字符串

l dwFlags –可选的渲染标志,可为0或下面的值:D3DFONT_CENTERED、D3DFONT_TWOSIDED、D3DFONT_FILTERED。

例如:

Font->DrawText(20, 20, 0xff000000, “Hello, World”);

9.2.3. 资源清除

在删除CD3DFont对象前,还需作一些清除的工作:

Font->InvalidateDeviceObjects();

Font->DeleteDeviceObjects();

delete Font;

9.3. 函数D3DXCreateText

该函数用于创建3D文字Mesh,原型如下:

HRESULT WINAPI D3DXCreateText(

LPDIRECT3DDEVICE9 pDevice,

HDC hDC,

LPCTSTR pText,

FLOAT Deviation,

FLOAT Extrusion,

LPD3DXMESH *ppMesh,

LPD3DXBUFFER *ppAdjacency,

LPGLYPHMETRICSFLOAT pGlyphMetrics

);

l pDevice –D3D设备

l hDC –描述字体的设备上下文句柄

l pText –要渲染的字符串

l Deviation –TrueType字体的一个属性,该值不能小于0。如果为0,则使用字体的默认值

l Extrusion –字体的深度,相对于Z坐标轴

l ppMesh –返回生成的Mesh对象指针

l ppAdjacency –返回邻接信息。如果不需要该信息,可使用NULL指针

l pGlyphMetrics –结构GLYPHMETRICSFLOAT的数组,返回轮廓矩阵数据。如果不需要该数据,可以设该参数为NULL

下面就举例说明如何使用该函数创建3D文字的Mesh对象。

// Obtain a handle to a device context.

HDC hdc = CreateCompatibleDC( 0 );

// Fill out a LOGFONT structure that describes the font’s properties.

LOGFONT lf;

ZeroMemory(&lf, sizeof(LOGFONT));

lf.lfHeight = 25; // in logical units

lf.lfWidth = 12; // in logical units

lf.lfWeight = 500; // boldness, range 0(light) - 1000(bold)

lf.lfItalic = false;

lf.lfUnderline = false;

lf.lfStrikeOut = false;

lf.lfCharSet = DEFAULT_CHARSET;

strcpy(lf.lfFaceName, "Times New Roman"); // font style

// Create a font and select that font with the device context.

HFONT hFont;

HFONT hFontOld;

hFont = CreateFontIndirect(&lf);

hFontOld = (HFONT)SelectObject(hdc, hFont);

// Create the 3D mesh of text.

ID3DXMesh* Text = 0;

D3DXCreateText(_device, hdc, "Direct3D", 0.001f, 0.4f, &Text, 0, 0);

// Reselect the old font, and free resources.

SelectObject(hdc, hFontOld);

DeleteObject( hFont );

DeleteDC( hdc );

这时,Mesh对象已经得到了。最后,直接使用DrawSubset方法渲染即可:

Text->DrawSubset( 0 );

译者注:上面的例子代码,使用的是较早的DirectX 9.0 SDK,不是Summer 2004版本。

9.4. 总结

l 如果需要渲染较复杂的字体和格式,使用ID3DXFont接口会很方便。但是该接口是使用GDI实现的,故效率较低。

l CD3DFont类可以快速的渲染简单的字体。该类实用D3D的纹理三角形渲染文字,故速度较ID3DXFont为快。

l 使用D3DXCreateText函数可以创建文字的3D网格模型。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有