这次的例子是输出文字,包括UNICODE,2D和3D文字显示。
首先看看新增的全局变量:
ID3DXFont* g_pFont = NULL;
ID3DXFont* g_pFont2 = NULL;
ID3DXFont* g_pStatsFont = NULL;
ID3DXMesh* g_pMesh3DText = NULL;
WCHAR* g_strTextBuffer = NULL;
TCHAR g_strFont[LF_FACESIZE];
int g_nFontSize;
3种字体,一个网格,一个文字缓冲区,一个字体大小,还有一个文字字体数组。
沿袭上一次的习惯,每一个函数分别解析。
1
//--------------------------------------------------------------------------------------
// Initialize the app
//--------------------------------------------------------------------------------------
void InitApp()
{
wcscpy_s( g_strFont, 32, L"Arial" );
这是个字体的名称啦~
rsrc = FindResource( NULL, MAKEINTRESOURCE( IDR_TXT ), L"TEXT" );
if( rsrc != NULL )
{
cbData = SizeofResource( NULL, rsrc );
if( cbData > 0 )
{
hgData = LoadResource( NULL, rsrc );
if( hgData != NULL )
{
pvData = LockResource( hgData );
if( pvData != NULL )
{
int nSize = cbData / sizeof( WCHAR ) + 1;
g_strTextBuffer = new WCHAR[nSize];
memcpy( g_strTextBuffer, ( WCHAR* )pvData, cbData );
g_strTextBuffer[nSize - 1] = 0;
}
}
}
}
这一段代码载入了一段UNICODE编码的文字资源,其实就是“Text3D.txt”文件。
2
HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
void* pUserContext )
HDC hDC = GetDC( NULL );
int nLogPixelsY = GetDeviceCaps( hDC, LOGPIXELSY );
ReleaseDC( NULL, hDC );
int nHeight = -g_nFontSize * nLogPixelsY / 72;
hr = D3DXCreateFont( pd3dDevice, // D3D device
nHeight, // Height
0, // Width
FW_BOLD, // Weight
1, // MipLevels, 0 = autogen mipmaps
FALSE, // Italic
DEFAULT_CHARSET, // CharSet
OUT_DEFAULT_PRECIS, // OutputPrecision
DEFAULT_QUALITY, // Quality
DEFAULT_PITCH | FF_DONTCARE, // PitchAndFamily
g_strFont, // pFaceName
&g_pFont ); // ppFont
这一段代码创建了一个字体,注意,这里的字体高度值的算法是一个通用的算法,具体百度。
if( FAILED( hr = D3DXCreateFont( pd3dDevice, -12, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
L"System", &g_pFont2 ) ) )
return hr;
if( FAILED( hr = D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
L"Arial", &g_pStatsFont ) ) )
return hr;
if( FAILED( hr = D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) ) )
return hr;
再创建两个字体,然后创建了一个精灵,用来绘制字体。
3
HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice,
const D3DSURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
提醒一下,这个函数在上面的函数执行完毕后执行,类型为D3DPOOL_DEFAULT的资源应该放在这里,具体就是不需要经常更新,可以一直放在显存的,静态的资源。
SAFE_RELEASE( g_pMesh3DText );
if( FAILED( CreateD3DXTextMesh( pd3dDevice, &g_pMesh3DText, g_strFont, g_nFontSize, FALSE, FALSE ) ) )
return E_FAIL;
这里主要调用了一个函数来创建字体的3D网格,下面解释这个函数。
4
HRESULT CreateD3DXTextMesh( IDirect3DDevice9* pd3dDevice,
LPD3DXMESH* ppMesh,
TCHAR* pstrFont, DWORD dwSize,
BOOL bBold, BOOL bItalic )
hFont = CreateFont( nHeight, 0, 0, 0, bBold ? FW_BOLD : FW_NORMAL, bItalic, FALSE, FALSE, DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE,
pstrFont );
hFontOld = ( HFONT )SelectObject( hdc, hFont );
又创建了一个字体,注意,pstrFont中的是字体种类。然后将字体选进DC中,以后的内容均采用这种字体绘制。
hr = D3DXCreateText( pd3dDevice, hdc, L"怎么了你累了",
0.001f, 0.4f, &pMeshNew, NULL, NULL );
SelectObject( hdc, hFontOld );
DeleteObject( hFont );
DeleteDC( hdc );
if( SUCCEEDED( hr ) )
*ppMesh = pMeshNew;
调用API D3DXCreateText来创建3D字体网格,注意这里先将网格放进指针pMeshNew,后面再将指针值赋值给ppMesh。
5
void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
基本上很多文字都放在这里渲染,这里就只放其中一段。
if( g_pMesh3DText != NULL )
{
CDXUTPerfEventGenerator g( DXUT_PERFEVENTCOLOR, L"Demonstration Part 4" );
ZeroMemory( &mtrl, sizeof( D3DMATERIAL9 ) );
mtrl.Diffuse.r = mtrl.Ambient.r = 0.0f;
mtrl.Diffuse.g = mtrl.Ambient.g = 0.0f;
mtrl.Diffuse.b = mtrl.Ambient.b = 1.0f;
mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
pd3dDevice->SetMaterial( &mtrl );
pd3dDevice->SetTransform( D3DTS_WORLD, &g_matObj2 );
g_pMesh3DText->DrawSubset( 0 );
}
这一段就是绘制3D字体的代码,其实就是绘制网格。