ホーム < ゲームつくろー! < DirectX技術編 < 高速フォント表示:サンプルプログラム(デバッグ版)
その5 高速フォント表示:サンプルプログラム(デバッグ版)
こちらは高速フォント表示のサンプルプログラムのデバッグ版です。
以下のプログラムを空のプロジェクトにコピペし、実行してください。実行後作成される「Log.txt」というテキストファイルに停止理由が書かれていると思われますので、その内容を掲示板にてご報告して下さい。エラーを検討後直ちに対処致します。
(このプログラムをお試し頂かなくてはならないすべての皆様にお詫び申し上げます)
// 高速フォント表示サンプルプログラム(デバッグ用) #pragma comment(lib, "dxguid.lib") #pragma comment(lib, "d3d9.lib") #include <windows.h> #include <tchar.h> #include <d3d9.h> #include <d3dx9.h> #include <fstream> using namespace std; TCHAR gName[100] = _T("高速フォント表示サンプルプログラム(デバッグ用)"); /// 頂点関係 /// #define FVF_CUSTOM ( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 ) // 座標変換済み頂点 struct CUSTOMVERTEX{ float x,y,z; // 頂点座標 float rhw; // 除算数 DWORD dwColor; // 頂点の色 float u, v; // テクスチャ座標 }; LRESULT CALLBACK WndProc(HWND hWnd, UINT mes, WPARAM wParam, LPARAM lParam){ if(mes == WM_DESTROY) {PostQuitMessage(0); return 0;} return DefWindowProc(hWnd, mes, wParam, lParam); } int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { // デバック出力用ファイル ofstream ofs; ofs.open( _T("Log.txt") ); if(!ofs.is_open()) return 0; ofs << "高速フォント表示サンプルプログラム(デバッグ用)エラーログファイル" << endl << endl; // アプリケーションの初期化 MSG msg; HWND hWnd; WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, WndProc, 0, 0, hInstance, NULL, NULL, (HBRUSH)(COLOR_WINDOW+1), NULL, (TCHAR*)gName, NULL}; if(!RegisterClassEx(&wcex)){ ofs << "ウィンドウクラスの登録に失敗しました" << endl; return 0; } if(!(hWnd = CreateWindow(gName, gName, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL))){ ofs << "ウィンドウハンドルの取得に失敗しました" << endl; return 0; } // Direct3Dの初期化 LPDIRECT3D9 g_pD3D; LPDIRECT3DDEVICE9 g_pD3DDev; if( !(g_pD3D = Direct3DCreate9( D3D_SDK_VERSION )) ){ ofs << "IDirect3D9インターフェイスの取得に失敗しました" << endl; return 0; } D3DPRESENT_PARAMETERS d3dpp = {0,0,D3DFMT_UNKNOWN,0,D3DMULTISAMPLE_NONE,0, D3DSWAPEFFECT_DISCARD,NULL,TRUE,0,D3DFMT_UNKNOWN,0,0}; if( FAILED( g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pD3DDev ) ) ){ ofs << "IDirect3DDevice9インターフェイスの取得に失敗しました" << endl; g_pD3D->Release(); return 0; } ShowWindow(hWnd, nCmdShow); // フォントの生成 int fontsize = 500; LOGFONT lf = {fontsize, 0, 0, 0, 0, 0, 0, 0, SHIFTJIS_CHARSET, OUT_TT_ONLY_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FIXED_PITCH | FF_MODERN, _T("MS 明朝")}; HFONT hFont; if(!(hFont = CreateFontIndirect(&lf))){ ofs << "フォントハンドルの生成に失敗しました" << endl; g_pD3DDev->Release(); g_pD3D->Release(); return 0; } // デバイスコンテキスト取得 // デバイスにフォントを持たせないとGetGlyphOutline関数はエラーとなる HDC hdc = GetDC(NULL); HFONT oldFont = (HFONT)SelectObject(hdc, hFont); // 文字コード取得 TCHAR *c = _T("あ"); UINT code = 0; #if _UNICODE // unicodeの場合、文字コードは単純にワイド文字のUINT変換です code = (UINT)*c; #else // マルチバイト文字の場合、 // 1バイト文字のコードは1バイト目のUINT変換、 // 2バイト文字のコードは[先導コード]*256 + [文字コード]です if(IsDBCSLeadByte(*c)) code = (BYTE)c[0]<<8 | (BYTE)c[1]; else code = c[0]; #endif // フォントビットマップ取得 TEXTMETRIC TM; GetTextMetrics( hdc, &TM ); GLYPHMETRICS GM; CONST MAT2 Mat = {{0,1},{0,0},{0,0},{0,1}}; DWORD size = GetGlyphOutline(hdc, code, GGO_GRAY4_BITMAP, &GM, 0, NULL, &Mat); BYTE *ptr = new BYTE[size]; GetGlyphOutline(hdc, code, GGO_GRAY4_BITMAP, &GM, size, ptr, &Mat); // デバイスコンテキストとフォントハンドルの開放 SelectObject(hdc, oldFont); DeleteObject(hFont); ReleaseDC(NULL, hdc); // 頂点情報 float a = 1.0f; // テクスチャの縮尺 float fTexW = GM.gmCellIncX * a; // テクスチャの横幅 float fTexH = TM.tmHeight * a; // テクスチャの高さ DWORD FontColor = 0x88ffffff; // テクスチャカラー(透明度50%) CUSTOMVERTEX v[]= { { fTexW, 0.0f, 0.0f, 1.0f, FontColor, 1.0f, 0.0f}, { fTexW, fTexH, 0.0f, 1.0f, FontColor, 1.0f, 1.0f}, { 0.0f, 0.0f, 0.0f, 1.0f, FontColor, 0.0f, 0.0f}, { 0.0f, fTexH, 0.0f, 1.0f, FontColor, 0.0f, 1.0f} }; // 頂点バッファ作成 IDirect3DVertexBuffer9* pVertex; if(FAILED(g_pD3DDev->CreateVertexBuffer(sizeof(CUSTOMVERTEX)*4, D3DUSAGE_WRITEONLY, FVF_CUSTOM, D3DPOOL_MANAGED, &pVertex, NULL))){ ofs << "頂点バッファの生成に失敗しました" << endl; g_pD3DDev->Release(); g_pD3D->Release(); delete[] ptr; return 0; } // 頂点情報の書き込み void *pData; if(FAILED(pVertex->Lock(0, sizeof(CUSTOMVERTEX)*4, (void**)&pData, 0))){ ofs << "頂点バッファのロックに失敗しました" << endl; g_pD3DDev->Release(); g_pD3D->Release(); delete[] ptr; return 0; } memcpy(pData, v, sizeof(CUSTOMVERTEX)*4); pVertex->Unlock(); // テクスチャ作成 LPDIRECT3DTEXTURE9 pTex; if(FAILED(g_pD3DDev->CreateTexture( GM.gmCellIncX, TM.tmHeight, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTex, NULL))){ ofs << "テクスチャの作成に失敗しました" << endl; g_pD3DDev->Release(); g_pD3D->Release(); delete[] ptr; return 0; } // テクスチャにフォントビットマップ書き込み D3DLOCKED_RECT LockedRect; if(FAILED(pTex->LockRect(0, &LockedRect, NULL, D3DLOCK_DISCARD))){ ofs << "テクスチャサーフェイスのロックに失敗しました" << endl; g_pD3DDev->Release(); g_pD3D->Release(); delete[] ptr; return 0; } // フォント情報の書き込み // iOfs_x, iOfs_y : 書き出し位置(左上) // iBmp_w, iBmp_h : フォントビットマップの幅高 // Level : α値の段階 (GGO_GRAY4_BITMAPなので17段階) int iOfs_x = GM.gmptGlyphOrigin.x; int iOfs_y = TM.tmAscent - GM.gmptGlyphOrigin.y; int iBmp_w = GM.gmBlackBoxX + (4-(GM.gmBlackBoxX%4))%4; int iBmp_h = GM.gmBlackBoxY; int Level = 17; int x, y; DWORD Alpha, Color; FillMemory(LockedRect.pBits , LockedRect.Pitch * TM.tmHeight, 0); for(y=iOfs_y; y<iOfs_y+iBmp_h; y++) for(x=iOfs_x; x<iOfs_x+iBmp_w; x++){ Alpha = (255 * ptr[x-iOfs_x + iBmp_w*(y-iOfs_y)]) / (Level-1); Color = 0x00ffffff | (Alpha<<24); memcpy((BYTE*)LockedRect.pBits + LockedRect.Pitch*y + 4*x, &Color, sizeof(DWORD)); } pTex->UnlockRect(0); delete[] ptr; // テクスチャセット g_pD3DDev->SetTexture(0, pTex); g_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); g_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP , D3DTOP_MODULATE ); g_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); g_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); g_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP , D3DTOP_MODULATE ); g_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); // 板ポリのα値を利用 // レンダリングステート g_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); g_pD3DDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_pD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); // メッセージ ループ do{ Sleep(1); if( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ){ DispatchMessage(&msg);} else{ // Direct3Dの処理 g_pD3DDev->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,255), 1.0f, 0 ); g_pD3DDev->BeginScene(); // 描画 g_pD3DDev->SetStreamSource(0, pVertex, 0, sizeof(CUSTOMVERTEX)); g_pD3DDev->SetFVF(FVF_CUSTOM); g_pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); g_pD3DDev->EndScene(); g_pD3DDev->Present( NULL, NULL, NULL, NULL ); } }while(msg.message != WM_QUIT); pVertex->Release(); pTex->Release(); g_pD3DDev->Release(); g_pD3D->Release(); ofs << "正常終了..." << endl; return 0; }