#include #include #include #include #include #pragma warning( disable : 4996 ) // 無駄な警告を出さなくする #include #pragma warning( default : 4996 ) //メモリリークを調べるために必要。 #if _DEBUG #include #define new ::new( _NORMAL_BLOCK, __FILE__, __LINE__ ) #endif #define WINDOW_WIDTH (640) // ウィンドウの幅 #define WINDOW_HEIGHT (480) // ウィンドウの高さ #define WINDOW_X ((WINDOW_WIDTH + GetSystemMetrics( SM_CXSIZEFRAME )*2)) #define WINDOW_Y ((WINDOW_HEIGHT + GetSystemMetrics( SM_CYSIZEFRAME )*2 + GetSystemMetrics( SM_CYCAPTION ))) #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } HINSTANCE g_hInstance = NULL; // インスタンス・ハンドル HWND g_hWindow = NULL; // ウインドウ・ハンドル LPDIRECT3D9 g_pD3D = NULL; // Direct3Dインタフェース LPDIRECT3DDEVICE9 g_pD3DDevice = NULL; // Direct3DDeviceインタフェース #define MY_VERTEX_FVF ( D3DFVF_XYZ | D3DFVF_DIFFUSE ) struct MY_VERTEX{ float px, py, pz; DWORD color; }; #define MY_VERTEX_FVF2 ( D3DFVF_XYZRHW | D3DFVF_DIFFUSE ) struct MY_VERTEX2{ float px, py, pz; float rhw; DWORD color; }; #define DIF_X 325 #define DIF_Y 250 //円 MY_VERTEX2 g_circle[] = { { DIF_X + 0.0f, DIF_Y + 0.0f, 0.0f,1.0f, 0xffffffff}, { DIF_X + 0.0f, DIF_Y + 100.0f, 0.0f,1.0f, 0xffffffff}, { DIF_X + cos(D3DXToRadian(60.0f))*100, DIF_Y + sin(D3DXToRadian(60.0f))*100, 0.0f, 1.0f, 0xffffffff}, { DIF_X + cos(D3DXToRadian(30.0f))*100, DIF_Y + sin(D3DXToRadian(30.0f))*100, 0.0f, 1.0f, 0xffffffff}, { DIF_X + 100.0f, DIF_Y + 0.0f, 0.0f, 1.0f, 0xffffffff}, { DIF_X + cos(D3DXToRadian(-30.0f))*100, DIF_Y + sin(D3DXToRadian(-30.0f))*100, 0.0f, 1.0f, 0xffffffff}, { DIF_X + cos(D3DXToRadian(-60.0f))*100, DIF_Y + sin(D3DXToRadian(-60.0f))*100, 0.0f, 1.0f, 0xffffffff}, { DIF_X + 0.0f, DIF_Y - 100.0f, 0.0f,1.0f, 0xffffffff}, { DIF_X + cos(D3DXToRadian(-120.0f))*100, DIF_Y + sin(D3DXToRadian(-120.0f))*100, 0.0f, 1.0f, 0xffffffff}, { DIF_X + cos(D3DXToRadian(-150.0f))*100, DIF_Y + sin(D3DXToRadian(-150.0f))*100, 0.0f, 1.0f, 0xffffffff}, { DIF_X - 100.0f, DIF_Y + 0.0f, 0.0f, 1.0f, 0xffffffff}, { DIF_X + cos(D3DXToRadian(-210.0f))*100, DIF_Y + sin(D3DXToRadian(-210.0f))*100, 0.0f, 1.0f, 0xffffffff}, { DIF_X + cos(D3DXToRadian(-240.0f))*100, DIF_Y + sin(D3DXToRadian(-240.0f))*100, 0.0f, 1.0f, 0xffffffff}, { DIF_X + 0.0f, DIF_Y + 100.0f, 0.0f,1.0f, 0xffffffff}, }; MY_VERTEX2 g_visibility[] = { { 0.0f, 0.0f, 0.0f, 1.0f, 0x55ff6666}, { 640.0f, 0.0f, 0.0f, 1.0f, 0x55ff6666}, { 0.0f, 480.0f, 0.0f, 1.0f, 0x55ff6666}, { 640.0f, 480.0f, 0.0f, 1.0f, 0x55ff6666}, }; //正方形 MY_VERTEX g_floor[] = { {-4.0f, -2.0f, 4.0f, 0xff0000ff}, { 4.0f, -2.0f, 4.0f, 0xff9999ff}, {-4.0f, -2.0f,-4.0f, 0xff6666ff}, { 4.0f, -2.0f,-4.0f, 0xff0000ff}}; MY_VERTEX g_wall[] = { {-0.5f, 0.5f, 0.0f, 0xffff0000}, { 0.5f, 0.5f, 0.0f, 0xff00ff00}, {-0.5f, -0.5f, 0.0f, 0xff0000ff}, { 0.5f, -0.5f, 0.0f, 0xffffffff}}; //----------------------------------------------------------------------------- // Name: MsgProc() // Desc: The window's message handler //----------------------------------------------------------------------------- LRESULT WINAPI MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { switch( msg ) { case WM_DESTROY: PostQuitMessage( 0 ); return 0; } return DefWindowProc( hWnd, msg, wParam, lParam ); } //----------------------------------------------------------------------------- // Name: InitApp() // Desc: Initialize Window //----------------------------------------------------------------------------- HRESULT InitApp(HINSTANCE hInstance) { g_hInstance = hInstance; WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VREDRAW, MsgProc, 0, 0, g_hInstance, NULL, NULL, (HBRUSH)(COLOR_WINDOW+1), NULL, L"D3D Tutorial", NULL}; if( !RegisterClassEx( &wcex )){ return DXTRACE_ERR(L"InitApp", GetLastError()); } // Create the application's window g_hWindow = CreateWindow( L"D3D Tutorial", L"ゲームプログラミング", WS_OVERLAPPEDWINDOW ^WS_THICKFRAME ^ WS_MAXIMIZEBOX ^ WS_MINIMIZEBOX, 100, 100, WINDOW_X, WINDOW_Y, NULL, NULL, wcex.hInstance, NULL ); if (g_hWindow == NULL) return DXTRACE_ERR(L"InitApp", GetLastError()); return S_OK; } //----------------------------------------------------------------------------- // Name: InitDirectX() // Desc: Initialize DirectX //----------------------------------------------------------------------------- HRESULT InitDirectX(void){ g_pD3D = Direct3DCreate9(D3D_SDK_VERSION); if(g_pD3D == NULL){ DXTRACE_MSG(L"DirectXDeviceの初期化に失敗しました"); return E_FAIL; } D3DDISPLAYMODE d3ddm; if(FAILED(g_pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))) { DXTRACE_MSG(L"DirectX3DDeviceの初期化に失敗しました"); return E_FAIL; } D3DPRESENT_PARAMETERS d3dpp; ZeroMemory(&d3dpp, sizeof(d3dpp)); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_UNKNOWN; d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; d3dpp.EnableAutoDepthStencil = TRUE; d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;//D3DFMT_D16; HRESULT hr = g_pD3D->CreateDevice( D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,g_hWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp,&g_pD3DDevice); if(FAILED(hr)) { hr = g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,g_hWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp,&g_pD3DDevice); if(FAILED(hr)) { hr = g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_REF,g_hWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp,&g_pD3DDevice); if(FAILED(hr)){ DXTRACE_MSG(L"DirectX3DDeviceの初期化に失敗しました"); return E_FAIL; } } } //セットアップ レンダーステート g_pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); g_pD3DDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE ); g_pD3DDevice->SetRenderState( D3DRS_ZENABLE, TRUE ); g_pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); g_pD3DDevice->SetRenderState( D3DRS_AMBIENT, 0x33333333 ); g_pD3DDevice->SetRenderState( D3DRS_NORMALIZENORMALS, TRUE ); g_pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA ); g_pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA ); g_pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); g_pD3DDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); g_pD3DDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); //ビュー行列作成 D3DXVECTOR3 vEyePt( 0.0f, 0.0f,-4.0f ); D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f ); D3DXMATRIXA16 matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); g_pD3DDevice->SetTransform( D3DTS_VIEW, &matView ); //射影行列作成 D3DXMATRIXA16 matProj; D3DXMatrixPerspectiveFovLH( &matProj, D3DXToRadian(90.0f), (float)640/480, 1.0f, 100.0f ); g_pD3DDevice->SetTransform( D3DTS_PROJECTION, &matProj ); return S_OK; } //----------------------------------------------------------------------------- // Name: Uninitialize() // Desc: UnInitialize DirectX //----------------------------------------------------------------------------- void Uninitialize(void) { //デバイスなどを開放 SAFE_RELEASE(g_pD3DDevice); SAFE_RELEASE(g_pD3D); } void DrawNormalWall() { D3DXMATRIX mat; D3DXMatrixIdentity(&mat); mat._42 = -1.5f; mat._41 = -1.5f; //ステンシル参照値の設定************************************ g_pD3DDevice->SetRenderState( D3DRS_STENCILREF, 0x07 ); //0x05にする //条件設定。(0x07では無い部分に描画する。)****************** //0x05と、0x00の部分しか無い為、描画領域全体が0x07では無い = 確実に壁が描画される g_pD3DDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_NOTEQUAL ); g_pD3DDevice->SetTransform(D3DTS_WORLD ,&mat); g_pD3DDevice->SetFVF(MY_VERTEX_FVF); g_pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_wall, sizeof(MY_VERTEX)); } void DrawUnTrueWall() { D3DXMATRIX mat; static int ragian = 0; D3DXMatrixRotationY(&mat,D3DXToRadian(ragian = (ragian + 1) % 360)); mat._42 = -1.5f; mat._41 = 0.0f; //ステンシル参照値の設定************************************ g_pD3DDevice->SetRenderState( D3DRS_STENCILREF, 0x05 ); //0x05にする //条件設定。(値が0x05では無い部分にのみ、描画する)********** g_pD3DDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_NOTEQUAL ); g_pD3DDevice->SetTransform(D3DTS_WORLD ,&mat); g_pD3DDevice->SetFVF(MY_VERTEX_FVF); g_pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_wall, sizeof(MY_VERTEX)); } void DrawInvisibleWall() { D3DXMATRIX mat; static int ragian = 0; D3DXMatrixRotationY(&mat,D3DXToRadian(ragian = (ragian + 1) % 360)); mat._42 = -1.5; mat._41 = 1.5; //ステンシル参照値の設定************************************ g_pD3DDevice->SetRenderState( D3DRS_STENCILREF, 0x05 ); //0x05にする //条件設定。(値が0x05の部分にのみ、描画する)**************** g_pD3DDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_EQUAL ); g_pD3DDevice->SetTransform(D3DTS_WORLD ,&mat); g_pD3DDevice->SetFVF(MY_VERTEX_FVF); g_pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_wall, sizeof(MY_VERTEX)); } void DrawFloor(){ D3DXMATRIX mat; D3DXMatrixIdentity(&mat); //ステンシル参照値の設定************************************ g_pD3DDevice->SetRenderState( D3DRS_STENCILREF, 0x07); //0x07にする //条件設定。(0x07では無い部分に描画する。)****************** //0x05と、0x00の部分しか無い為、描画領域全体が0x07では無い = 確実に床が描画される g_pD3DDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_NOTEQUAL ); g_pD3DDevice->SetTransform(D3DTS_WORLD ,&mat); g_pD3DDevice->SetFVF(MY_VERTEX_FVF); g_pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_floor, sizeof(MY_VERTEX)); }; void DrawVisibility() { g_pD3DDevice->SetRenderState( D3DRS_STENCILREF, 0x0); g_pD3DDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_EQUAL ); g_pD3DDevice->SetFVF(MY_VERTEX_FVF2); g_pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, g_visibility, sizeof(MY_VERTEX2)); } void SetScope() { //ステンシルテストの設定*********************************** g_pD3DDevice->SetRenderState( D3DRS_STENCILENABLE, TRUE ); //有効 //深度テストの設定****************************************** g_pD3DDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_NEVER ); //必ず不合格 //ステンシルマスクの設定************************************ g_pD3DDevice->SetRenderState( D3DRS_STENCILMASK, 0xffffffff ); //0xffffffffにする g_pD3DDevice->SetRenderState( D3DRS_STENCILWRITEMASK, 0xffffffff ); //0xffffffffにする //ステンシルバッファに書き込む条件(比較関数)の設定******** g_pD3DDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_ALWAYS ); //絶対に書き込む。 //書き込む値の設定****************************************** g_pD3DDevice->SetRenderState( D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP ); //何もしない g_pD3DDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE ); //ステンシル参照値を書き込む。 g_pD3DDevice->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_KEEP ); //何もしない //ステンシル参照値の設定************************************ g_pD3DDevice->SetRenderState( D3DRS_STENCILREF, 0x05 ); //0x05にする //ステンシルバッファに円を描画。(円の部分・・・0x05、その他・・・0x00) g_pD3DDevice->SetFVF(MY_VERTEX_FVF2); g_pD3DDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 12, g_circle, sizeof(MY_VERTEX2)); } //----------------------------------------------------------------------------- // Name: WinMain() // Desc: The application's entry point //----------------------------------------------------------------------------- int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { #ifdef _DEBUG _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); #endif HRESULT hr; if(FAILED(hr = InitApp(hInstance))) { return(0); } // Initialize Direct3D if( SUCCEEDED(hr = InitDirectX()) ) { MSG msg; ZeroMemory( &msg, sizeof(msg) ); ShowWindow(g_hWindow, SW_SHOWDEFAULT); UpdateWindow(g_hWindow); // Enter the message loop while( msg.message!=WM_QUIT ) { if( PeekMessage( &msg, NULL, 0U, 0U, PM_REMOVE ) ) { TranslateMessage( &msg ); DispatchMessage( &msg ); }else{ g_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, D3DCOLOR_XRGB(0,0,60), 1.0f, 0 ); g_pD3DDevice->BeginScene(); if(GetKeyState(VK_RIGHT) < 0){ //ステンシルバッファの中央の円の部分を、0x05にする。 SetScope(); //深度テストの設定***************************************** g_pD3DDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL ); //書き込む値の設定*********************************** g_pD3DDevice->SetRenderState( D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP ); //何もしない g_pD3DDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP ); //何もしない g_pD3DDevice->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_KEEP ); //何もしない DrawInvisibleWall();//通常は見えない壁(実は存在する) DrawUnTrueWall();//通常は見える壁 (実は存在しない) DrawNormalWall();//通常の壁 (普通に存在する) DrawFloor();//通常の床 DrawVisibility();//中央の円以外を、若干赤くする }else{ /***********ステンシルテスト無効************/ g_pD3DDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE ); //有効 DrawUnTrueWall();//通常は見える壁 (実は存在しない) DrawNormalWall();//通常の壁 (普通に存在する) DrawFloor();//通常の床 } g_pD3DDevice->EndScene(); g_pD3DDevice->Present( NULL, NULL, NULL, NULL ); Sleep(1); } } } Uninitialize(); UnregisterClass( L"D3D Tutorial", g_hInstance ); return 0; }