今回とある事情に迫られてDirectXによるノベルエンジンを作ることになったのですが
便宜のために文字の表示を行うプロセスをクラス化したところ
画面に描画されなくなってしまいました
どなたか助けていただけないでしょうか?
開発環境
OS[tab=30][tab=30]Windows XP Professional SP3
コンパイラ[tab=30][tab=30]Visual Studio 2010 C++ Express
開発ライブラリバージョン[tab=30]Microsoft DirectX SDK June 2010 (ENG)
文字エンコード[tab=30][tab=30]Unicode
以下はそのコードです
Class D3DTextをGrobal.hにて定義
Metius.cppよりD3DTextをddtとして使用
DirectXの描画処理は_tWinMain内のメインループで行っています
Struct.h(一部抜粋)
//多重インクルードガード
#ifndef STRUCT_H
#define STRUCT_H
struct CUSTOMVERTEX{
float x, y, z; // 頂点座標
float rhw; // 除算数
float u, v; // テクスチャ座標
};
struct CUSTOMVERTEX_T{
float x,y,z; // 頂点座標
float rhw; // 除算数
DWORD dwColor; // 頂点の色
float u, v; // テクスチャ座標
};
struct STRALPHA{
DWORD color;//予約変数
LPDIRECT3DTEXTURE9 tex;
IDirect3DVertexBuffer9 * pVertex_t;
};
#endif
#include "Struct.h"
/*グローバルな定義*/
/*定義固定値*/
#define DEFWIDTH 1028
#define DEFHEIGHT 576
/*構造体最大数*/
#define IMGS 256
/*DirctXのための定義*/
#define MAX_LOADSTRING 100
#define RELEASE(p) { if(p){(p)->Release();p=NULL;} }
/// 頂点関係 ///
#define FVF_CUSTOM ( D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 ) // 座標変換済み頂点
/*型定義*/
#define STRALPHA_NEW(N) (STRALPHA *)malloc(sizeof(STRALPHA)*N);
#define STRALPHA_RELEASE(_X) {free(_X);}
#define STRALPHA_SIZE_T size_t
#ifndef GLOBAL_DECLARE
#define GLOBAL
#else
#define GLOBAL extern
#endif
//PC操作関数
//レジストリの文字列を取得します
GLOBAL void GetRegStr(HKEY OpenKey , LPCWSTR KeyRoot , LPCWSTR ValueName, TCHAR& Dest);
GLOBAL int DrawImageForAll(IDirect3DDevice9 * &SrcDev,int Width = DEFWIDTH,int Height = DEFHEIGHT);
GLOBAL BOOL SetPos(IDirect3DVertexBuffer9* vtx, float Cx, float Cy, float width, float height);
/*グローバル変数*/
/*グローバル構造体変数*/
GLOBAL ImageLoad_t imgset[IMGS];
//GLOBAL
GLOBAL class D3DText{
public:
//IDirect3DVertexBuffer9* pVertex_t;
DWORD dwColor; //A,R,G,Bとデータが入っているため
/*テキスト関数群*/
float TextSet(IDirect3DDevice9 * &SrcDev,TCHAR *c,LPDIRECT3DTEXTURE9 *Dest,IDirect3DVertexBuffer9 * &pVertex_dest,float x = 0.0f,float y = 0.0f,DWORD FontColor = 0xffffffff);//文字単体を描画する
void _Draw(IDirect3DDevice9 * &SrcDev,IDirect3DVertexBuffer9 * &pVertex_t);
int _DrawString(IDirect3DDevice9 * &SrcDev,TCHAR *c,STRALPHA * &stralpha,STRALPHA_SIZE_T size,float x = 0.0f,float y = 0.0f,DWORD Color = 0xffffffff);//Colorにはアルファ情報を含みます
void _AlphaChange(IDirect3DDevice9 * &SrcDev,LPDIRECT3DTEXTURE9 &Src,DWORD Color);
};
#include "stdafx.h"
#include <d3d9.h>
#include <d3dx9.h>
#include <d3dx9tex.h>
#include "Global.h"
float D3DText::TextSet(IDirect3DDevice9 * &SrcDev,TCHAR *c,LPDIRECT3DTEXTURE9 *Dest,IDirect3DVertexBuffer9 * &pVertex_dest,float x,float y,DWORD FontColor)
{
// フォントの生成
int fontsize = 60;
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 UI Gothic")};
HFONT hFont;
if(!(hFont = CreateFontIndirect(&lf))){
SrcDev->Release();
return -1.0f;
}
// デバイスコンテキスト取得
// デバイスにフォントを持たせないと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 = 0xffffffff; // テクスチャカラー(透明度50%)
CUSTOMVERTEX_T v[]=
{
{ fTexW + x, y, 0.0f, 1.0f, FontColor, 1.0f, 0.0f},
{ fTexW + x, fTexH + y, 0.0f, 1.0f, FontColor, 1.0f, 1.0f},
{ x, y, 0.0f, 1.0f, FontColor, 0.0f, 0.0f},
{ x, fTexH + y, 0.0f, 1.0f, FontColor, 0.0f, 1.0f}
};
// 頂点バッファ作成
if(FAILED(SrcDev->CreateVertexBuffer(sizeof(CUSTOMVERTEX_T)*4, D3DUSAGE_WRITEONLY, FVF_CUSTOM,
D3DPOOL_MANAGED, &pVertex_dest, NULL))){
SrcDev->Release();delete[] ptr;
return -1.0f;
}
// 頂点情報の書き込み
void *pData;
if(FAILED(pVertex_dest->Lock(0, sizeof(CUSTOMVERTEX_T)*4, (void**)&pData, 0))){
SrcDev->Release();delete[] ptr;
return -1.0f;
}
memcpy(pData, v, sizeof(CUSTOMVERTEX_T)*4);
pVertex_dest->Unlock();
// テクスチャ作成
LPDIRECT3DTEXTURE9 pTex;
if(FAILED(SrcDev->CreateTexture( GM.gmCellIncX, TM.tmHeight, 1, D3DUSAGE_DYNAMIC, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &pTex, NULL))){
if(FAILED(SrcDev->CreateTexture( GM.gmCellIncX, TM.tmHeight, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pTex, NULL)))
{
SrcDev->Release();delete[] ptr;
return -1.0f;
}
}
// テクスチャにフォントビットマップ書き込み
D3DLOCKED_RECT LockedRect;
if(FAILED(pTex->LockRect(0, &LockedRect, NULL, D3DLOCK_DISCARD))){
if(FAILED(pTex->LockRect(0, &LockedRect, NULL, 0)))
{
SrcDev->Release();delete[] ptr;
return -1.0f;
}
}
// フォント情報の書き込み
// 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;
// テクスチャセット
SrcDev->SetTexture(0, pTex);
// テクスチャアルファセット
SrcDev->SetRenderState(D3DRS_TEXTUREFACTOR,Color);
SrcDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
SrcDev->SetTextureStageState(0, D3DTSS_COLOROP , D3DTOP_MODULATE );
SrcDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
SrcDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
SrcDev->SetTextureStageState(0, D3DTSS_ALPHAOP , D3DTOP_MODULATE );
SrcDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR ); // 板ポリのα値を利用
// レンダリングステート
SrcDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
SrcDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
SrcDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
/*
pD3Device->SetStreamSource(0, pVertex_t, 0, sizeof(CUSTOMVERTEX_T));
pD3Device->SetFVF(FVF_CUSTOM);
pD3Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
*/
if(Dest != NULL)*Dest = pTex;
return fTexW;
}
void D3DText::_Draw(IDirect3DDevice9 * &SrcDev,IDirect3DVertexBuffer9 * &pVertex_t)
{
SrcDev->SetStreamSource(0, pVertex_t, 0, sizeof(CUSTOMVERTEX_T));
SrcDev->SetFVF(FVF_CUSTOM);
SrcDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
}
void _AlphaChange(IDirect3DDevice9 * &SrcDev,LPDIRECT3DTEXTURE9 &Src,DWORD Color)
{
// テクスチャセット
SrcDev->SetTexture(0, Src);
// テクスチャアルファセット
SrcDev->SetRenderState(D3DRS_TEXTUREFACTOR,Color);
SrcDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
SrcDev->SetTextureStageState(0, D3DTSS_COLOROP , D3DTOP_MODULATE );
SrcDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
SrcDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
SrcDev->SetTextureStageState(0, D3DTSS_ALPHAOP , D3DTOP_MODULATE );
SrcDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR ); // 板ポリのα値を利用
// レンダリングステート
SrcDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
SrcDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
SrcDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
}
int D3DText::_DrawString(IDirect3DDevice9 * &SrcDev,TCHAR *c,STRALPHA * &stralpha,STRALPHA_SIZE_T size,float x,float y,DWORD Color)
{
LPDIRECT3DTEXTURE9 Dest;
float currentwidth = 0.0f;
int j = 0;
TCHAR k[256];
ZeroMemory(k,_tcslen(k)-1);
for(TCHAR * i = c; *i; ++i)
{
k[0] = *i;
if((currentwidth = D3DText::TextSet(SrcDev,&k[0],&stralpha[j].tex,stralpha[j].pVertex_t,x + currentwidth,y,Color)) == -1)return -1;
j++;
}
return 1;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_METIUS));
imgset[0].flag=TRUE;
_tcscpy(imgset[0].Src,L"Water lilies.jpg");
imgset[0].x=32;
ShowWindow(hWnd,nCmdShow);
D3DText ddt;
static IDirect3DVertexBuffer9 * dest_v;
ddt.TextSet(pD3Device,_T("あ"),NULL,dest_v);
/*
int w = _tcslen(_T("てすとてすと"));
STRALPHA * stralpha = STRALPHA_NEW(w);
ddt._DrawString(pD3Device,_T("てすとてすと"),stralpha,w);
*/
// メッセージ ループ
do{
Sleep(1);
if( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) ){ DispatchMessage(&msg);}
else{
// Direct3Dの処理
pD3Device->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,0,0), 1.0f, 0 );
pD3Device->BeginScene();
// 描画
DrawImageForAll(pD3Device);
ddt._Draw(pD3Device,dest_v);
/*
for(int i = 0; i < w; i++)ddt._Draw(pD3Device,stralpha[i].pVertex_t);
*/
pD3Device->EndScene();
pD3Device->Present( NULL, NULL, NULL, NULL );
}
}while(msg.message != WM_QUIT);
// 解放
RELEASE( pD3Device );
RELEASE( pDirect3D );
return 0;
}