D3DMで2D描画(色加算)

Main.cpp

#include <windows.h>
#include <d3dm.h.>
#include <d3dmx.h>
#include "resource.h"

#pragma comment(lib, "d3dm.lib")
#pragma comment(lib, "d3dmx.lib")

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
#define	PROC_NAME	L"ProcSample12"
bool	InitD3dm( HWND );
void	ExitD3dm( void );
void	Render( void );
//----------------------------------------------------------------
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPreInst, LPWSTR lpszCmdLine, int nCmdShow )
{
	HWND	hwnd;
	MSG		msg;
	WNDCLASS myProg;

	if (!hPreInst) {
		myProg.style			= CS_HREDRAW | CS_VREDRAW;
		myProg.lpfnWndProc		= WndProc;
		myProg.cbClsExtra		= 0;
		myProg.cbWndExtra		= 0;
		myProg.hInstance		= hInstance;
		myProg.hIcon			= NULL;
		myProg.hCursor			= NULL;
		myProg.hbrBackground	= (HBRUSH)COLOR_WINDOW;
		myProg.lpszMenuName		= NULL;
		myProg.lpszClassName	= PROC_NAME;		
		if (!RegisterClass( &myProg )){
			return FALSE;
		}
	}
	hwnd = CreateWindow( PROC_NAME,
		L"Sample12",
		WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL);
	if( InitD3dm( hwnd ) == false )
		return	FALSE;
	ShowWindow( hwnd, nCmdShow );
	UpdateWindow( hwnd );

	do{
		if(PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE )) {
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		}else{
			Render();
		}
	} while(msg.message != WM_QUIT);
	ExitD3dm();
	return (int)( msg.wParam );
}

//----------------------------------------------------------------
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
	switch (msg) {
		case WM_DESTROY:
			ExitD3dm();
			PostQuitMessage( 0 );
			break;
		default:
		return(DefWindowProc( hwnd, msg, wParam, lParam ));
	}
	return (0L);
}

//================================================================
//

#define	BALL_MAX	45
struct BALL
{
	FLOAT	x,y;
	FLOAT	ax,ay;
};
BALL	ballData[ BALL_MAX ];

//================================================================
//D3DM 関係

// 頂点配列
struct VERTEX
{
	FLOAT	x, y, z;
	FLOAT	rhw;
	FLOAT	u, v;

	static const DWORD	FVF;
};
const DWORD VERTEX::FVF = D3DMFVF_XYZRHW_FLOAT | D3DMFVF_TEX1;

#define SAFE_RELEASE(o) {if(o){o->Release();o = NULL;}}

IDirect3DMobile*				gPd3d			= NULL;		// Direct3Dオブジェクト
IDirect3DMobileDevice*			gPd3dmDevice	= NULL;		// Direct3Dデバイス
IDirect3DMobileVertexBuffer*	gPVB			= NULL;		// 頂点バッファ
IDirect3DMobileTexture*			gPTexture		= NULL;		// テクスチャ

//----------------------------------------------------------------
void	SetVertecCal( VERTEX *ballVertex, float u, float v )
{
	ballVertex->u	= u;
	ballVertex->v	= v;
	ballVertex->z	= 0.0f;
	ballVertex->rhw	= 1.0f;
}

//----------------------------------------------------------------
bool	InitD3dm( HWND hwnd)
{
	if(!(gPd3d = Direct3DMobileCreate( D3DM_SDK_VERSION )))
		return false;

	D3DMPRESENT_PARAMETERS d3dmpp; 
	memset( &d3dmpp, 0, sizeof(d3dmpp) );
	d3dmpp.Windowed		= true;			// ウィンドウモード
	d3dmpp.SwapEffect	= D3DMSWAPEFFECT_DISCARD;

	// フォーマット
	d3dmpp.BackBufferFormat			= D3DMFMT_R5G6B5;
	d3dmpp.EnableAutoDepthStencil	= TRUE;
	d3dmpp.AutoDepthStencilFormat	= D3DMFMT_D16;		// Zバッファが16bit

	// デバイスの生成
	if( gPd3d->CreateDevice( D3DMADAPTER_DEFAULT, D3DMDEVTYPE_DEFAULT, hwnd, 0, &d3dmpp, &gPd3dmDevice ) != S_OK )
		return	true;
	//テクスチャ設定
	D3DMCAPS caps;
	gPd3dmDevice->GetDeviceCaps(&caps);
	D3DMPOOL texpool;
	if (caps.SurfaceCaps & D3DMSURFCAPS_VIDTEXTURE){
		texpool = D3DMPOOL_VIDEOMEM;	// VRAM
	}else{
		texpool = D3DMPOOL_SYSTEMMEM;	// システムRAM
	}
	if( FAILED( D3DMXCreateTextureFromResourceEx( gPd3dmDevice, GetModuleHandle(NULL), 
		MAKEINTRESOURCE(IDB_BITMAP1), D3DMX_DEFAULT, D3DMX_DEFAULT, 1, 0, 
		D3DMFMT_UNKNOWN, texpool, D3DMX_FILTER_POINT, D3DMX_FILTER_POINT, 
		0, NULL, NULL, &gPTexture ) ) ){
		return false;
	}        
	//-------------------------------------------
	gPd3dmDevice->SetRenderState( D3DMRS_LIGHTING, FALSE );			//ライトOFF
	gPd3dmDevice->SetRenderState( D3DMRS_CULLMODE, D3DMCULL_NONE );	//両面
	//-------------------------------------------
	int	i;
	D3DMPOOL vbpool;
	vbpool = D3DMPOOL_SYSTEMMEM;
	VERTEX	*ballVertex;
	// 頂点バッファの作成
	if(FAILED(gPd3dmDevice->CreateVertexBuffer( sizeof(VERTEX)*BALL_MAX*6, 0, VERTEX::FVF, vbpool, &gPVB )))
		return false;
	if(FAILED(gPVB->Lock( 0, 0, (void**)&ballVertex, 0)))
		return false;
	for( i = 0 ; i < BALL_MAX ; i++ ){
		SetVertecCal( ballVertex++, 0.0f, 0.0f );
		SetVertecCal( ballVertex++, 1.0f, 0.0f );
		SetVertecCal( ballVertex++, 1.0f, 1.0f );
		SetVertecCal( ballVertex++, 0.0f, 0.0f );
		SetVertecCal( ballVertex++, 1.0f, 1.0f );
		SetVertecCal( ballVertex++, 0.0f, 1.0f );
	}
	gPVB->Unlock();
	for( i = 0 ; i < BALL_MAX ; i++ ){
		ballData[ i ].x		= rand()*400.0f/32767.0f;
		ballData[ i ].y		= rand()*600.0f/32767.0f;
		ballData[ i ].ax	= rand()*8.0f/32767.0f-4.0f;
		ballData[ i ].ay	= rand()*8.0f/32767.0f-4.0f;
	}
	return	true;
}

//----------------------------------------------------------------
void	ExitD3dm()
{
	SAFE_RELEASE( gPTexture );
	SAFE_RELEASE( gPVB );
	SAFE_RELEASE( gPd3dmDevice );
	SAFE_RELEASE( gPd3d );
}

//----------------------------------------------------------------
//	BALL計算
void	BallCal( BALL *ball )
{
	ball->x	+= ball->ax;
	ball->y	+= ball->ay;
	if( ball->x < 2 || ball->x > 400 )
		ball->ax	= -ball->ax;
	if( ball->y < 2 || ball->y > 600 )
		ball->ay	= -ball->ay;
}

//----------------------------------------------------------------
//頂点登録
void	VertecCal( VERTEX *ballVertex, float x, float y )
{
	//----------------------------
	ballVertex->x	= x;
	ballVertex->y	= y;
	ballVertex++;
	ballVertex->x	= x+128;
	ballVertex->y	= y;
	ballVertex++;
	ballVertex->x	= x+128;
	ballVertex->y	= y+128;
	ballVertex++;
	//----------------------------
	ballVertex->x	= x;
	ballVertex->y	= y;
	ballVertex++;
	ballVertex->x	= x+128;
	ballVertex->y	= y+128;
	ballVertex++;
	ballVertex->x	= x;
	ballVertex->y	= y+128;
}

//----------------------------------------------------------------
void	Render()
{
	VERTEX	*ballVertex;
	int	i;

	//BALL計算
	for( i = 0 ; i < BALL_MAX ; i++ )
		BallCal( &ballData[ i ] );
	//BALL頂点登録
	gPVB->Lock( 0, 0, (void**)&ballVertex, 0);
	for( i = 0 ; i < BALL_MAX ; i++ ){
		VertecCal( ballVertex, ballData[ i ].x, ballData[ i ].y );
		ballVertex	+=6;
	}
	gPVB->Unlock();

	// バックバッファとZバッファのクリア
	gPd3dmDevice->Clear(0, NULL, D3DMCLEAR_TARGET | D3DMCLEAR_ZBUFFER, D3DMCOLOR_XRGB(0,0,0), 1.0f, 0);

	// 描画開始
	if(SUCCEEDED(gPd3dmDevice->BeginScene()))
	{
		//ブレンディング設定
		gPd3dmDevice->SetRenderState(D3DMRS_ALPHABLENDENABLE, TRUE);
		gPd3dmDevice->SetRenderState(D3DMRS_SRCBLEND, D3DMBLEND_SRCCOLOR);
		gPd3dmDevice->SetRenderState(D3DMRS_DESTBLEND,D3DMBLEND_ONE);
		// テクスチャ設定
		gPd3dmDevice->SetTexture( 0, gPTexture );

		// 頂点バッファからレンダリング
		gPd3dmDevice->SetStreamSource(0, gPVB, sizeof(VERTEX));
		gPd3dmDevice->DrawPrimitive(D3DMPT_TRIANGLELIST, 0, BALL_MAX * 2);

		gPd3dmDevice->SetTexture( 0, NULL );
		gPd3dmDevice->EndScene();
	}
	// スクリーンへの転送
	gPd3dmDevice->Present(NULL, NULL, NULL, NULL);
}

テクスチャはこれを使用しました。(BMPファイル、アルファなし)

■これを実行すると、こんな感じ
エミュレータでは遅くてしょうがないのですが、T01Aではサクサクうごくからいいですかね