今回は画像の背景領域を切り抜いて描画します
Direct3Dには3つのテストが存在します
SIZE(20){ COLOR(#ffaa00){・アルファテスト}}
SIZE(20){ COLOR(#ffaa00){・ステンシルテスト}}
SIZE(20){ COLOR(#ffaa00){・Zテスト}}
この3つのテストに合格したピクセルが描画されます
透明領域を描画しないかのテストがアルファテストとなります
つまり、SIZE(20){COLOR(#ffaa00){画像の背景領域を透明にしておき、アルファテストを行えば背景領域は描画されません}}

今回使うファイルは次のようになってます。どぞー(-ω-)つ旦
・&ref(direct3d.h);
・&ref(direct3d.cpp);
・&ref(texture.h);
・&ref(texture.cpp);
・&ref(sprite.h);
・&ref(sprite.cpp);
・&ref(alphatest.cpp);

今回使う画像はこちら
・&ref(sky.bmp);
・shooter.png
&ref(shooter.png);
(↑右クリックして画像を保存)

SIZE(20){ COLOR(#ffaa00){背景領域を透明にしたい画像は画像編集ソフトであらかじめ背景領域を透明にしておいて}}
SIZE(20){ COLOR(#ffaa00){gifやpngなどの透明領域を保存できる画像形式で保存します}}

zipでほしい人はこちら
・&ref(alphatest.zip);

WinMain関数はalphatest.cppにあります
alphatest.cpp以外のプログラムファイルは前回と変更ありません
前回作ったサウンド系のプログラムファイルは今回使いません

 #include <Windows.h>
 #include <tchar.h>
 
 #include "direct3d.h"
 #include "texture.h"
 #include "sprite.h"
 
 //////////////////////////////////////////////////////////////////////////////////////////////
 
 // レンダーステートの設定
 enum RENDERSTATE
 {
	RENDER_DEFAULT,		// デフォルト(不透明)
	RENDER_ALPHATEST	// αテスト
 };
 
 // レンダーステートの変更
 void SetRenderState(IDirect3DDevice9* pD3DDevice,RENDERSTATE RenderState){
  
	switch(RenderState)
	{
	case RENDER_DEFAULT:
		{
			// 不透明オブジェクト
			pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);		//アルファテストの無効化
		}
		break;
	case RENDER_ALPHATEST:
		{
			// αテストによる透明領域の切り抜き
			pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);		//アルファテストの有効化
			pD3DDevice->SetRenderState(D3DRS_ALPHAREF, 0x01);			//アルファ参照値
			pD3DDevice->SetRenderState(D3DRS_ALPHAREF, 0x80);			//アルファ参照値
			pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);	//アルファテスト合格基準
 			
		}
		break;
	}
 }
 //////////////////////////////////////////////////////////////////////
 
 // ウィンドウプロシージャ、ウィンドウに対するメッセージ処理を行う
 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam){
 	
	switch(msg){
		// ウィンドウが破棄されたとき
	case WM_DESTROY:
		PostQuitMessage(0);	// WM_QUITメッセージをメッセージキューに送る
		return 0;
	}
	// デフォルトのメッセージ処理を行う
	return DefWindowProc(hWnd, msg, wParam, lParam);
 }
 
 // WinMain関数(アプリケーションの開始関数)
 // コンソールアプリケーションと違い、コンソールを開かない
 int _stdcall WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
 {
	const TCHAR* WC_BASIC = _T("BASIC_WINDOW");
	// シンプルウィンドウクラス設定
	WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS,WndProc, 0,0,hInstance,
		(HICON)LoadImage(NULL,MAKEINTRESOURCE(IDI_APPLICATION),IMAGE_ICON,0,0,LR_DEFAULTSIZE | LR_SHARED),
		(HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(IDC_ARROW),IMAGE_CURSOR,0,0,LR_DEFAULTSIZE | LR_SHARED), 
		(HBRUSH)GetStockObject(WHITE_BRUSH), NULL, WC_BASIC , NULL};
 
	// シンプルウィンドウクラス作成
	if(!RegisterClassEx(&wcex)) 
		return false;
 
	// ウィンドウ幅、高さはディスプレイに依存する。普通は4:3
	const int WINDOW_WIDTH = 640;
	const int WINDOW_HEIGHT = 480;
	// ウィンドウの作成
	HWND hWnd = CreateWindowEx(0,WC_BASIC,
		_T("Application"), WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_VISIBLE,
		CW_USEDEFAULT,CW_USEDEFAULT,WINDOW_WIDTH,WINDOW_HEIGHT,NULL,NULL,hInstance,NULL);
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
	////////////////////////////////////
	//	Direct3Dの初期化
	////////////////////////////////////
	Direct3D direct3d;
	direct3d.Create(hWnd,WINDOW_WIDTH,WINDOW_HEIGHT);
 
	////////////////////////////////
	// テクスチャ作成
	////////////////////////////////
	Texture skytex;
	Texture cartex;
	skytex.Load(direct3d.pDevice3D,_T("sky.bmp"));
	cartex.Load(direct3d.pDevice3D,_T("shooter.png"));
 
	////////////////////////////////
	// スプライト作成
	////////////////////////////////
	Sprite sprite[2];
 
	sprite[0].SetPos(WINDOW_WIDTH/2.0f,WINDOW_HEIGHT/2.0f);
	sprite[0].SetWidth(WINDOW_WIDTH,WINDOW_HEIGHT);
	sprite[1].SetPos(300,300);
	sprite[1].SetWidth(128,128);
 	
 ///////////////////////////////////////////////////////////////////////////////////////////////
  		
	// メッセージループ
	MSG msg = {}; 
	while(msg.message != WM_QUIT) {
		// アプリケーションに送られてくるメッセージをメッセージキューから取得する
		if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
			DispatchMessage(&msg);	// アプリケーションの各ウィンドウプロシージャにメッセージを転送する
		}
		// メッセージ処理をしていないとき
		else{
			//(ここにDirectXの処理を書く)
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
 
			// 描画開始
			if(SUCCEEDED(direct3d.pDevice3D->BeginScene()))
			{
				DWORD ClearColor = 0xff808080;	// 背景クリア色
				// 背景クリア
				direct3d.pDevice3D->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_STENCIL | D3DCLEAR_ZBUFFER, ClearColor, 1.0f, 0 );
 				
				// 透明領域を描画時切り抜きする設定
				SetRenderState(direct3d.pDevice3D,RENDER_ALPHATEST);
 
				// スプライト描画
				sprite[0].Draw(direct3d.pDevice3D,skytex.pTexture);
 				sprite[1].Draw(direct3d.pDevice3D,cartex.pTexture);
 			
				// 描画終了
				direct3d.pDevice3D->EndScene();
			}
			// 描画反映
			direct3d.pDevice3D->Present( NULL, NULL, NULL, NULL );
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
		}
	}	
	return 0;
 }


今回の実行結果は次のようになります
飛行機(shooter.png)の画像の背景が切り抜かれていると思います
&ref(alphatest.jpg);

アルファテストの設定がSetRenderState関数内にあります

 // αテストによる透明領域の切り抜き
 pD3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);	          //アルファテストの有効化
 pD3DDevice->SetRenderState(D3DRS_ALPHAREF, 0x01);		//アルファ参照値
 pD3DDevice->SetRenderState(D3DRS_ALPHAREF, 0x80);		//アルファ参照値
 pD3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);	//アルファテスト合格基準

アルファ参照値にアルファ値(0〜255)の値を入れます
この参照値と描画しようとしている画像のピクセルのアルファ値を比較する基準をALPHAFUNCの設定で設定します
この参照値と描画しようとしている画像のピクセルのアルファ値(透明度)を比較する基準をALPHAFUNCの設定で設定します
D3DCMP_GREATEREQUALでアルファ参照値よりも画像のピクセルのアルファ値が大きい場合、そのピクセルは描画されます
この設定により画像の背景はあらかじめ透明にしているため、背景領域は描画されません


今回はアルファテスト有効を描画直前にしています

 // 透明領域を描画時切り抜きする設定
 SetRenderState(direct3d.pDevice3D,RENDER_ALPHATEST);


前:DirectX講座15回
次:DirectX講座17回

#vote(完璧に理解した俺に死角はなかった(キリッ[0],どうゆうことなの・・・?[0],なんぞこれ?[0])
|完璧に理解した俺に死角はなかった(キリッ|5|
|どうゆうことなの・・・?|10|
|なんぞこれ?|2|


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS