★ DirectX Class ★ * Chapter 03: 画像の表示 *
< 2D描画の基礎 >
まずは画像を表示してみます。
3Dよりも簡単ですし、3Dゲームを作るときでも2D画像はよく使います。
例えば、メニュー画面やステータス等は3Dよりも2Dで描画したほうが圧倒的に楽です。
そんなこの記事の執筆時はGW☆
< 画像の読み込み >
Direct3Dでは、画像をテクスチャとして扱います。
テクスチャの意味が分からない人は、まぁそのまま画像と思っておいてもらって結構です。
私もうまく説明できません。
所詮人間ですので。

テクスチャを読み込むには、まずテクスチャ用のクラス変数を宣言しなければなりません。

LPDIRECT3DTEXTURE9 g_pTexture = NULL;

そして、テクスチャは以下の関数を利用して読み込むことが可能です。

HRESULT D3DXCreateTextureFromFile(
  LPDIRECT3DDEVICE9 ,
  LPCTSTR ,
  LPDIRECT3DTEXTURE9 *
);

LPCTSTRはファイル名です。
LPDIRECT3DTEXTURE9はテクスチャを格納するクラスへのポインタです。
実際には次のように使います。

D3DXCreateTextureFromFile( g_pd3dDevice , "sample0003.bmp" , &g_pTexture );

これでテクスチャの読み込みは完了しました。
< スプライト >
2Dの描画を制御するには『スプライト』と呼ばれるものを使います。
直訳的な意味は、テクスチャを貼り付けるための板といった感じでしょうか。
作成したウィンドウにそんな透明な板がぴったりと張り付いているようなイメージです。
スプライトも変数として宣言しなくてはなりません。

LPD3DXSPRITE g_pSprite = NULL;

そして実際にスプライトを作成します。

D3DXCreateSprite( g_pd3dDevice , &g_pSprite );

これでスプライトの作成は完了です。
< テクスチャ / スプライトの開放 >
他のデバイス等と同様、アプリケーションの終了時には開放しなくてはなりません。

g_pTexture->Release();
g_pSprote->Release();

スプライトとテクスチャの開放順番は互いにどちらからでも結構ですが、
デバイスの開放よりも前に行ってください。
< 描画 >
前章の描画処理で、描画の開始/終了をすると書きましたが、
その中でさらにスプライト描画の開始/終了を行わなくてはなりません。

スプライトの描画開始/終了は以下の関数を利用することによって実現できまっせ。

g_pSprite->Begin( NULL );

// スプライトの描画処理

g_pSprite->End();

『 g_pSprite->Begin( NULL ) 』の引数にNULLを指定していますが、
ここには各種フラグを設定することができます。
半透明やクリッピング等、20数種類用意されています。
今回は特に必要なかったのでNULLを指定しました。
興味がおありの方は説明書をご覧くださいませ。

そして実際に描画する関数は以下の通りです。

HRESULT Draw(
  LPDIRECT3DTEXTURE9,
  CONST RECT *,
  CONST D3DXVECTOR3 *,
  CONST D3DXVECTOR3 *,
  D3DCOLOR Color
);

『RECT』とは矩形を表すために用意されたWINAPI用の構造体です。
数値型変数left、top、right、bottomを持っています。
ここでは、読み込んだテクスチャの切り出し範囲を指定するために使います。
( x , y ) = ( 16 , 32 )から( x , y ) = ( 128 , 256 )の範囲を切り出したい場合には、
以下のように記述します。

RECT rc;

rc.left   = 16;
rc.top    = 32;
rc.right  = 128;
rc.bottom = 256;

『D3DXVECTOR3』はベクトルや3次元空間における位置を表すための構造体です。
浮動小数型変数x、y、zを持っています。
最初のD3DXVECTOR3には、先ほど切り出したテクスチャの中心位置を、
次のD3DXVECTOR3には、配置場所を設定します。
『中心位置』が『配置場所』にくるよう『先程切り出したテクスチャ』が描画されます。
今回は2Dですので、zの値は使用しません。
後で2Dでも使いますけど。

『D3DCOLOR』はテクスチャの色を設定します。
前章で扱ったように、D3DCOLOR_XRGB関数を使っても良いですし、8桁の16進数を使うことも可能です。
通常は0xFFFFFFFFを設定すればそのまま表示されますが、この白以外の数値を指定することによって、
テクスチャをその色を強くして表示することができます。
例えば、0xFFFF00FFを指定すれば、テクスチャが全体的にピンクがかって表示されます。
詳しい実行結果をご覧になりたい方は、サンプルプログラムの該当場所を変更してお試しください。

実際には以下のようにして実行することになります。

D3DXVECTOR3 center , position;

g_pSprite->Draw(
  g_pTexture ,
  &rc ,
  &center ,
  &position,
  0xFFFFFFFF
);
< サンプル >
このサンプルを実行すると、クライアント領域に画像が表示されます。
画像は以下のものを使用しました。
実行ファイルと同じディレクトリに保存して実行してください。

sample03.bmp

この画像は五月に御所と梨木神社の間の道で撮りました。

前章からの変更点はピンク色で示してあります。

//-----------------------------------------------------------------
//
//    DirectX 3D Sprite Sample.
//
//-----------------------------------------------------------------
#define sqrtf sqrt
#define sinf  sin
#define cosf  cos
#define tanf  tan

#include <stdio.h>
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>

#pragma comment( lib , "d3d9.dll" );
#pragma comment( lib , "d3dx9.dll" );



//-----------------------------------------------------------------
//    Grobal Variables.
//-----------------------------------------------------------------
LPDIRECT3D9        g_pD3D       = NULL;
LPDIRECT3DDEVICE9  g_pd3dDevice = NULL;
LPD3DXSPRITE       g_pSprite    = NULL;
LPDIRECT3DTEXTURE9 g_pTexture   = NULL;



//-----------------------------------------------------------------
//    Prototypes.
//-----------------------------------------------------------------
HWND    InitApp( HINSTANCE , int );
BOOL    InitDirect3D( HWND );
BOOL    CleanupDirect3D();
BOOL    RenderDirect3D();
LRESULT CALLBACK WndProc( HWND , UINT , WPARAM , LPARAM );



//-----------------------------------------------------------------
//    Main.
//-----------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hInst , HINSTANCE hPrevinst , LPSTR nCmdLine , int nCmdShow )
{
	MSG msg;
	HWND hWnd;
	
	hWnd = InitApp( hInst , nCmdShow );
	if ( !hWnd ) return FALSE;
	
	if ( !InitDirect3D( hWnd ) ) return FALSE;
	
	while( msg.message != WM_QUIT ){
		if ( PeekMessage( &msg , NULL , 0 , 0 , PM_REMOVE ) ){
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}else{
			RenderDirect3D();
		}
		Sleep( 1 );
	}
	
	return msg.wParam;
}



//-----------------------------------------------------------------
//    Initialize Application.
//-----------------------------------------------------------------
HWND InitApp( HINSTANCE hInst , int nCmdShow )
{
	WNDCLASS wc;
	HWND hWnd;
	char szClassName[] = "Direct3D Test";
	
	wc.style         = CS_HREDRAW | CS_VREDRAW;
	wc.hInstance     = hInst;
	wc.hCursor       = LoadCursor( NULL , IDC_ARROW );
	wc.hIcon         = LoadIcon( NULL , IDI_APPLICATION );
	wc.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );
	wc.lpszClassName = szClassName;
	wc.lpszMenuName  = NULL;
	wc.lpfnWndProc   = WndProc;
	wc.cbWndExtra    = 0;
	wc.cbClsExtra    = 0;
	if ( !RegisterClass( &wc ) ) return FALSE;
	
	hWnd = CreateWindow( szClassName , "Direct3D Test" , WS_OVERLAPPEDWINDOW ,
						CW_USEDEFAULT , CW_USEDEFAULT , 640 , 480,
						NULL , NULL , hInst , NULL );
	if ( !hWnd ) return FALSE;
	
	ShowWindow( hWnd , nCmdShow );
	UpdateWindow( hWnd );
	
	return hWnd;
}



//-----------------------------------------------------------------
//    Initialize Direct3D.
//-----------------------------------------------------------------
BOOL InitDirect3D( HWND hWnd )
{
	D3DPRESENT_PARAMETERS d3dpp;
	HRESULT hr;
	
	if ( NULL == ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ){
		MessageBox( hWnd , "Can't create Direct3D." , "Error" , MB_OK );
		return FALSE;
	}
	ZeroMemory( &d3dpp , sizeof( d3dpp ) );
	d3dpp.Windowed         = TRUE;
	d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
	
	hr = g_pD3D->CreateDevice( D3DADAPTER_DEFAULT , D3DDEVTYPE_HAL , hWnd ,
	                           D3DCREATE_SOFTWARE_VERTEXPROCESSING ,
	                           &d3dpp , &g_pd3dDevice );
	if ( FAILED( hr ) ){
		MessageBox( hWnd , "Can't create device." , "Error" , MB_OK );
		return FALSE;
	}
	
	D3DXCreateSprite( g_pd3dDevice , &g_pSprite );
	D3DXCreateTextureFromFile( g_pd3dDevice , "sample0003.bmp" , &g_pTexture );
	
	return TRUE;
}



//-----------------------------------------------------------------
//    Cleanup Direct3D.
//-----------------------------------------------------------------
BOOL CleanupDirect3D()
{
	if ( g_pTexture != NULL )
		g_pTexture->Release();
	
	if ( g_pSprite != NULL )
		g_pSprite->Release();
	
	if ( g_pd3dDevice != NULL )
		g_pd3dDevice->Release();
	
	if ( g_pD3D != NULL )
		g_pD3D->Release();
	
	return TRUE;
}



//-----------------------------------------------------------------
//    Window Proc.
//-----------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd , UINT msg , WPARAM wp , LPARAM lp )
{
	switch( msg ){
		case WM_DESTROY:
			CleanupDirect3D();
			PostQuitMessage( 0 );
			break;
		default:
			return DefWindowProc( hWnd , msg , wp , lp );
	}
	
	return 0L;
}



//-----------------------------------------------------------------
//    Render Direct3D.
//-----------------------------------------------------------------
BOOL RenderDirect3D()
{
	RECT rc;
	D3DXVECTOR3 center , position;
	
	g_pd3dDevice->Clear( 0 , NULL , D3DCLEAR_TARGET ,
	                     D3DCOLOR_XRGB( 0 , 0 , 0 ) , 1.0f , 0 );
	
	g_pd3dDevice->BeginScene();
	
	g_pSprite->Begin( NULL );
	
	rc.left    = 0;
	rc.top     = 0;
	rc.right   = 256;
	rc.bottom  = 256;
	center.x   = 0;
	center.y   = 0;
	position.x = 20;
	position.y = 10;
	
	g_pSprite->Draw( g_pTexture , &rc , &center , &position , 0xFFFFFFFF );
	
	g_pSprite->End();
	
	g_pd3dDevice->EndScene();
	
	g_pd3dDevice->Present( NULL , NULL , NULL , NULL );
	
	return TRUE;
}

実行結果

クリックすると実物大で表示されます。
執筆: 2008/05/05 (MON)