0001: //-----------------------------------------------------------------------------
0002: // File: main.cpp
0003: //
0004: // Desc: DirectX window application created by the DirectX AppWizard
0005: //-----------------------------------------------------------------------------
0006: #define STRICT
0007: #include <windows.h>
0008: #include <commctrl.h>
0009: #include <commdlg.h>
0010: #include <basetsd.h>
0011: #include <math.h>
0012: #include <stdio.h>
0013: #include <d3dx9.h>
0014: #include <dxerr9.h>
0015: #include <tchar.h>
0016: #include "DXUtil.h"
0017: #include "D3DEnumeration.h"
0018: #include "D3DSettings.h"
0019: #include "D3DApp.h"
0020: #include "D3DFont.h"
0021: #include "D3DFile.h"
0022: #include "D3DUtil.h"
0023: #include "resource.h"
0024: #include "main.h"
0025: 
0026: 
0027: //-----------------------------------------------------------------------------
0028: // 全画面描画ポリゴン
0029: //-----------------------------------------------------------------------------
0030: const DWORD CBigSquare::FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;
0031: 
0032: //-----------------------------------------------------------------------------
0033: CBigSquare::CBigSquare()
0034: {
0035:     m_pVB=NULL;
0036: }
0037: //-----------------------------------------------------------------------------
0038: void CBigSquare::Destroy()
0039: {
0040:     SAFE_RELEASE( m_pVB );
0041: }
0042: //-----------------------------------------------------------------------------
0043: void CBigSquare::Render( LPDIRECT3DDEVICE9 pd3dDevice )
0044: {
0045:     // Draw a big, gray square
0046:     pd3dDevice->SetFVF( FVF );
0047:     pd3dDevice->SetStreamSource( 0, m_pVB, 0, sizeof(SHADOWVERTEX));
0048:     pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
0049: }
0050: //-----------------------------------------------------------------------------
0051: // メモリ確保
0052: HRESULT CBigSquare::Create( LPDIRECT3DDEVICE9 pd3dDevice )
0053: {
0054:     if( FAILED( pd3dDevice->CreateVertexBuffer(
0055:                                     4*sizeof(SHADOWVERTEX),
0056:                                     D3DUSAGE_WRITEONLY,
0057:                                     FVF,
0058:                                     D3DPOOL_MANAGED,
0059:                                     &m_pVB, NULL ) ) )
0060:         return E_FAIL;
0061: 
0062:     return S_OK;
0063: }
0064: //-----------------------------------------------------------------------------
0065: // データ生成
0066: void CBigSquare::RestoreDeviceObjects( FLOAT sx, FLOAT sy )
0067: {
0068:     SHADOWVERTEX* v;
0069:     m_pVB->Lock( 0, 0, (void**)&v, 0 );
0070:     v[0].p = D3DXVECTOR4(  0, sy, 0.0f, 1.0f );
0071:     v[1].p = D3DXVECTOR4(  0,  0, 0.0f, 1.0f );
0072:     v[2].p = D3DXVECTOR4( sx, sy, 0.0f, 1.0f );
0073:     v[3].p = D3DXVECTOR4( sx,  0, 0.0f, 1.0f );
0074:     v[0].color = D3DCOLOR_RGBA(0,0,0,0x7f);
0075:     v[1].color = D3DCOLOR_RGBA(0,0,0,0x7f);
0076:     v[2].color = D3DCOLOR_RGBA(0,0,0,0x7f);
0077:     v[3].color = D3DCOLOR_RGBA(0,0,0,0x7f);
0078:     m_pVB->Unlock();
0079: }
0080: 
0081: 
0082: //-----------------------------------------------------------------------------
0083: // Global access to the app (needed for the global WndProc())
0084: //-----------------------------------------------------------------------------
0085: CMyD3DApplication* g_pApp  = NULL;
0086: HINSTANCE          g_hInst = NULL;
0087: 
0088: 
0089: 
0090: 
0091: //-----------------------------------------------------------------------------
0092: // Name: WinMain()
0093: // Desc: Entry point to the program. Initializes everything, and goes into a
0094: //       message-processing loop. Idle time is used to render the scene.
0095: //-----------------------------------------------------------------------------
0096: INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
0097: {
0098:     CMyD3DApplication d3dApp;
0099: 
0100:     g_pApp  = &d3dApp;
0101:     g_hInst = hInst;
0102: 
0103:     InitCommonControls();
0104:     if( FAILED( d3dApp.Create( hInst ) ) )
0105:         return 0;
0106: 
0107:     return d3dApp.Run();
0108: }
0109: 
0110: 
0111: 
0112: 
0113: //-----------------------------------------------------------------------------
0114: // Name: CMyD3DApplication()
0115: // Desc: Application constructor.   Paired with ~CMyD3DApplication()
0116: //       Member variables should be initialized to a known state here.  
0117: //       The application window has not yet been created and no Direct3D device 
0118: //       has been created, so any initialization that depends on a window or 
0119: //       Direct3D should be deferred to a later stage. 
0120: //-----------------------------------------------------------------------------
0121: CMyD3DApplication::CMyD3DApplication()
0122: {
0123:     m_pBigSquare                = new CBigSquare();
0124:     m_pMeshBG                   = new CD3DMesh();               
0125:     m_pMeshBox                  = new CD3DMesh();
0126:     m_pShadowBox                = new CShadowVolume();
0127: 
0128:     m_pFx                       = NULL;
0129:     m_hmWVP                     = NULL;
0130:     m_hvPos                     = NULL;
0131: 
0132:     // 選択されるシーンの設定
0133:     m_d3dEnumeration.AppUsesDepthBuffer = TRUE;
0134:     m_d3dEnumeration.AppMinDepthBits = 15;
0135:     m_d3dEnumeration.AppMinStencilBits = 1;
0136: 
0137:     m_dwCreationWidth           = 500;
0138:     m_dwCreationHeight          = 375;
0139:     m_strWindowTitle            = TEXT( "main" );
0140:     m_d3dEnumeration.AppUsesDepthBuffer   = TRUE;
0141:     m_bStartFullscreen          = false;
0142:     m_bShowCursorWhenFullscreen = false;
0143: 
0144:     // Create a D3D font using d3dfont.cpp
0145:     m_pFont                     = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD );
0146:     m_bLoadingApp               = TRUE;
0147: 
0148:     ZeroMemory( &m_UserInput, sizeof(m_UserInput) );
0149:     m_fWorldRotX                = 0.0f;
0150:     m_fWorldRotY                = 0.0f;
0151: }
0152: 
0153: 
0154: 
0155: 
0156: //-----------------------------------------------------------------------------
0157: // Name: ~CMyD3DApplication()
0158: // Desc: Application destructor.  Paired with CMyD3DApplication()
0159: //-----------------------------------------------------------------------------
0160: CMyD3DApplication::~CMyD3DApplication()
0161: {
0162: }
0163: 
0164: 
0165: 
0166: 
0167: //-----------------------------------------------------------------------------
0168: // Name: OneTimeSceneInit()
0169: // Desc: Paired with FinalCleanup().
0170: //       The window has been created and the IDirect3D9 interface has been
0171: //       created, but the device has not been created yet.  Here you can
0172: //       perform application-related initialization and cleanup that does
0173: //       not depend on a device.
0174: //-----------------------------------------------------------------------------
0175: HRESULT CMyD3DApplication::OneTimeSceneInit()
0176: {
0177:     // TODO: perform one time initialization
0178: 
0179:     // Drawing loading status message until app finishes loading
0180:     SendMessage( m_hWnd, WM_PAINT, 0, 0 );
0181: 
0182:     m_bLoadingApp = FALSE;
0183: 
0184:     return S_OK;
0185: }
0186: 
0187: 
0188: 
0189: 
0190: 
0191: 
0192: 
0193: 
0194: 
0195: //-----------------------------------------------------------------------------
0196: // Name: ConfirmDevice()
0197: // Desc: Called during device initialization, this code checks the display device
0198: //       for some minimum set of capabilities
0199: //-----------------------------------------------------------------------------
0200: HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior,
0201: D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat )
0202: {
0203:     // シェーダのチェック
0204:     if( pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) )
0205:         if( (dwBehavior & D3DCREATE_SOFTWARE_VERTEXPROCESSING ) == 0 )
0206:             return E_FAIL;
0207:     
0208:     // 両面ステンシル機能の確認
0209:     if( !( pCaps->StencilCaps & D3DSTENCILCAPS_TWOSIDED ) ) return E_FAIL;
0210:     
0211:     // ステンシル機能をサポートしているかチェック
0212:     if( FAILED( m_pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal
0213:                                     , pCaps->DeviceType
0214:                                     , adapterFormat
0215:                                     , D3DUSAGE_RENDERTARGET
0216:                                     | D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING
0217:                                     , D3DRTYPE_SURFACE
0218:                                     , backBufferFormat ) ) )
0219:         return E_FAIL;
0220: 
0221:     return S_OK;
0222: }
0223: 
0224: 
0225: 
0226: 
0227: //-----------------------------------------------------------------------------
0228: // Name: InitDeviceObjects()
0229: // Desc: Paired with DeleteDeviceObjects()
0230: //       The device has been created.  Resources that are not lost on
0231: //       Reset() can be created here -- resources in D3DPOOL_MANAGED,
0232: //       D3DPOOL_SCRATCH, or D3DPOOL_SYSTEMMEM.  Image surfaces created via
0233: //       CreateImageSurface are never lost and can be created here.  Vertex
0234: //       shaders and pixel shaders can also be created here as they are not
0235: //       lost on Reset().
0236: //-----------------------------------------------------------------------------
0237: HRESULT CMyD3DApplication::InitDeviceObjects()
0238: {
0239:     HRESULT hr;
0240:     DWORD i;
0241: 
0242:     // Init the font
0243:     m_pFont->InitDeviceObjects( m_pd3dDevice );
0244: 
0245:     if( FAILED( D3DXCreateEffectFromFile( m_pd3dDevice, "hlsl.fx", NULL, NULL, 
0246:                                     0, NULL, &m_pFx, NULL ) ) ) return E_FAIL;
0247:     m_hmWVP = m_pFx->GetParameterByName( NULL, "mWVP" );
0248:     m_hvPos = m_pFx->GetParameterByName( NULL, "vLightPos" );
0249: 
0250:     // 全画面描画ポリゴンの初期化
0251:     if( FAILED( m_pBigSquare->Create( m_pd3dDevice ) )) return E_FAIL;
0252: 
0253:     // 背景メッシュの読み込み
0254:     if( FAILED( hr = m_pMeshBG->Create( m_pd3dDevice, "CornellNoBox.x" ) ) )
0255:         return DXTRACE_ERR( "Load Mesh", hr );
0256:     for(i=0;i<m_pMeshBG->m_dwNumMaterials;i++){
0257:         m_pMeshBG->m_pMaterials[i].Ambient.r = m_pMeshBG->m_pMaterials[i].Diffuse.r*=2;
0258:         m_pMeshBG->m_pMaterials[i].Ambient.g = m_pMeshBG->m_pMaterials[i].Diffuse.g*=2;
0259:         m_pMeshBG->m_pMaterials[i].Ambient.b = m_pMeshBG->m_pMaterials[i].Diffuse.b*=2;
0260:     }
0261:     // 箱
0262:     if( FAILED( hr = m_pMeshBox->Create( m_pd3dDevice, "box.x" ) ) )
0263:         return DXTRACE_ERR( "Load Mesh", hr );
0264:     for(i=0;i<m_pMeshBox->m_dwNumMaterials;i++){
0265:         m_pMeshBox->m_pMaterials[i].Ambient.r = m_pMeshBox->m_pMaterials[i].Diffuse.r*=1.13f;
0266:         m_pMeshBox->m_pMaterials[i].Ambient.g = m_pMeshBox->m_pMaterials[i].Diffuse.g*=0.93f;
0267:         m_pMeshBox->m_pMaterials[i].Ambient.b = m_pMeshBox->m_pMaterials[i].Diffuse.b*=0.53f;
0268:     }
0269:     
0270:     // 影ボリュームの生成
0271:     m_pShadowBox->Create( m_pd3dDevice, m_pMeshBox->GetSysMemMesh() );
0272: 
0273:     return S_OK;
0274: }
0275: 
0276: 
0277: 
0278: 
0279: //-----------------------------------------------------------------------------
0280: // Name: RestoreDeviceObjects()
0281: // Desc: Paired with InvalidateDeviceObjects()
0282: //       The device exists, but may have just been Reset().  Resources in
0283: //       D3DPOOL_DEFAULT and any other device state that persists during
0284: //       rendering should be set here.  Render states, matrices, textures,
0285: //       etc., that don't change during rendering can be set once here to
0286: //       avoid redundant state setting during Render() or FrameMove().
0287: //-----------------------------------------------------------------------------
0288: HRESULT CMyD3DApplication::RestoreDeviceObjects()
0289: {
0290:     m_LighPos = D3DXVECTOR3(0.0f, 5.488f, 2.770f);
0291: 
0292:     // Setup a material
0293:     D3DMATERIAL9 mtrl;
0294:     D3DUtil_InitMaterial( mtrl, 1.0f, 0.0f, 0.0f );
0295:     m_pd3dDevice->SetMaterial( &mtrl );
0296: 
0297:     // Set up the textures
0298:     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
0299:     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
0300:     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
0301:     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
0302:     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
0303:     m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
0304:     m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
0305:     m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
0306: 
0307:     // Set miscellaneous render states
0308:     m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE,   FALSE );
0309:     m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE );
0310:     m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,        TRUE );
0311:     m_pd3dDevice->SetRenderState( D3DRS_AMBIENT,        0x000F0F0F );
0312: 
0313:     // Set the world matrix
0314:     D3DXMATRIX matIdentity;
0315:     D3DXMatrixIdentity( &matIdentity );
0316:     m_pd3dDevice->SetTransform( D3DTS_WORLD,  &matIdentity );
0317: 
0318:     // Set up our view matrix. A view matrix can be defined given an eye point,
0319:     // a point to lookat, and a direction for which way is up. Here, we set the
0320:     // eye five units back along the z-axis and up three units, look at the
0321:     // origin, and define "up" to be in the y-direction.
0322:     D3DXVECTOR3 vFromPt   = D3DXVECTOR3( 0.0f, 0.0f, -5.0f );
0323:     D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
0324:     D3DXVECTOR3 vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0325:     D3DXMatrixLookAtLH( &m_mView, &vFromPt, &vLookatPt, &vUpVec );
0326:     m_pd3dDevice->SetTransform( D3DTS_VIEW, &m_mView );
0327: 
0328:     // Set the projection matrix
0329:     FLOAT fAspect = ((FLOAT)m_d3dsdBackBuffer.Width) / m_d3dsdBackBuffer.Height;
0330:     D3DXMatrixPerspectiveFovLH( &m_mProj, 0.21f*D3DX_PI, fAspect, 1.0f, 100.0f );
0331:     m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &m_mProj );
0332: 
0333:     // Set up lighting states
0334:     D3DLIGHT9 light;
0335:     D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, -0.0f, -1.0f, 0.2f );
0336:     light.Diffuse.r   = 0.5f;
0337:     light.Diffuse.g   = 0.5f;
0338:     light.Diffuse.b   = 0.5f;
0339:     light.Ambient.r   = 0.5f;
0340:     light.Ambient.g   = 0.5f;
0341:     light.Ambient.b   = 0.5f;
0342:     m_pd3dDevice->SetLight( 0, &light );
0343:     m_pd3dDevice->LightEnable( 0, TRUE );
0344:     m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
0345: 
0346:     // Restore the font
0347:     m_pFont->RestoreDeviceObjects();
0348: 
0349:     m_pBigSquare->RestoreDeviceObjects( (FLOAT)m_d3dsdBackBuffer.Width,
0350:                                         (FLOAT)m_d3dsdBackBuffer.Height );
0351:     m_pMeshBG->RestoreDeviceObjects(m_pd3dDevice);
0352:     m_pMeshBox->RestoreDeviceObjects(m_pd3dDevice);
0353:     if( m_pFx != NULL ) m_pFx->OnResetDevice();
0354: 
0355:     return S_OK;
0356: }
0357: 
0358: 
0359: 
0360: 
0361: //-----------------------------------------------------------------------------
0362: // Name: FrameMove()
0363: // Desc: Called once per frame, the call is the entry point for animating
0364: //       the scene.
0365: //-----------------------------------------------------------------------------
0366: HRESULT CMyD3DApplication::FrameMove()
0367: {
0368:     // Update user input state
0369:     UpdateInput( &m_UserInput );
0370: 
0371:     // Update the world state according to user input
0372:     D3DXMATRIX m;
0373:     D3DXMATRIX matRotY;
0374:     D3DXMATRIX matRotX;
0375: 
0376:     if( m_UserInput.bRotateLeft && !m_UserInput.bRotateRight )
0377:         m_fWorldRotY += m_fElapsedTime;
0378:     else if( m_UserInput.bRotateRight && !m_UserInput.bRotateLeft )
0379:         m_fWorldRotY -= m_fElapsedTime;
0380: 
0381:     if( m_UserInput.bRotateUp && !m_UserInput.bRotateDown )
0382:         m_fWorldRotX += m_fElapsedTime;
0383:     else if( m_UserInput.bRotateDown && !m_UserInput.bRotateUp )
0384:         m_fWorldRotX -= m_fElapsedTime;
0385: 
0386:     D3DXMatrixRotationX( &matRotX, m_fWorldRotX );
0387:     D3DXMatrixRotationY( &matRotY, m_fWorldRotY );
0388: 
0389:     D3DXMatrixMultiply( &m, &matRotX, &matRotY );
0390: 
0391:     D3DXVECTOR3 vFromPt   = D3DXVECTOR3( 0.0f, 2.73f, -8.0f );
0392:     D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f, 2.73f, 0.0f );
0393:     D3DXVECTOR3 vUpVec    = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
0394:     D3DXMatrixLookAtLH( &m_mView, &vFromPt, &vLookatPt, &vUpVec );
0395:     m_mView = m * m_mView;
0396:     m_pd3dDevice->SetTransform( D3DTS_VIEW, &m_mView );
0397: 
0398:     return S_OK;
0399: }
0400: 
0401: 
0402: 
0403: 
0404: //-----------------------------------------------------------------------------
0405: // Name: UpdateInput()
0406: // Desc: Update the user input.  Called once per frame 
0407: //-----------------------------------------------------------------------------
0408: void CMyD3DApplication::UpdateInput( UserInput* pUserInput )
0409: {
0410:     pUserInput->bRotateUp    = ( m_bActive && (GetAsyncKeyState( VK_UP )    & 0x8000) == 0x8000 );
0411:     pUserInput->bRotateDown  = ( m_bActive && (GetAsyncKeyState( VK_DOWN )  & 0x8000) == 0x8000 );
0412:     pUserInput->bRotateLeft  = ( m_bActive && (GetAsyncKeyState( VK_LEFT )  & 0x8000) == 0x8000 );
0413:     pUserInput->bRotateRight = ( m_bActive && (GetAsyncKeyState( VK_RIGHT ) & 0x8000) == 0x8000 );
0414: }
0415: 
0416: 
0417: 
0418: 
0419: //-----------------------------------------------------------------------------
0420: // Name: Render()
0421: // Desc: Called once per frame, the call is the entry point for 3d
0422: //       rendering. This function sets up render states, clears the
0423: //       viewport, and renders the scene.
0424: //-----------------------------------------------------------------------------
0425: HRESULT CMyD3DApplication::Render()
0426: {
0427:     D3DXMATRIX m, mW, mS, mR, mT;
0428:     D3DXVECTOR4 v;
0429: 
0430:     
0431:     //画面のクリア
0432:     m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
0433:                          0x000000ff, 1.0f, 0L );
0434: 
0435:     // 描画の開始
0436:     if( SUCCEEDED( m_pd3dDevice->BeginScene() ) ) {
0437: 
0438:         // ----------------------------------------------------------
0439:         // 下準備:影なし部分の描画
0440:         // ----------------------------------------------------------
0441:         D3DXMatrixIdentity( &m );
0442:         m_pd3dDevice->SetTransform( D3DTS_WORLD,  &m );
0443:         m_pMeshBG->Render( m_pd3dDevice );
0444: 
0445:         // 小さい箱
0446:         D3DXMatrixScaling( &mS, 1.82f,1.65f, 1.82f );
0447:         D3DXMatrixRotationY( &mR, 0.59f*D3DX_PI );
0448:         D3DXMatrixTranslation( &mT, 2.73f-1.85f, 0.f , 1.69f );
0449:         m = mS * mR * mT;
0450:         m_pd3dDevice->SetTransform( D3DTS_WORLD,  &m );
0451:         m_pMeshBox->Render( m_pd3dDevice );
0452: 
0453:         // 大きい箱
0454:         D3DXMatrixScaling( &mS, 1.69f, 3.30f, 1.69f );
0455:         D3DXMatrixRotationY( &mR, 0.91f*D3DX_PI );
0456:         D3DXMatrixTranslation( &mT, 2.73f-3.685f, 0, 3.51f );
0457:         m = mS * mR * mT;
0458:         m_pd3dDevice->SetTransform( D3DTS_WORLD,  &m );
0459:         m_pMeshBox->Render( m_pd3dDevice );
0460: 
0461:         // ----------------------------------------------------------
0462:         // パス1:影ボリュームの描画
0463:         // ----------------------------------------------------------
0464:         // 深度バッファに書き込みはしない
0465:         m_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE,  FALSE );
0466:         // レンダリングターゲットに書き込みはしない
0467:         m_pd3dDevice->SetRenderState( D3DRS_COLORWRITEENABLE,  FALSE );
0468:         // フラットシェーディングする
0469:         m_pd3dDevice->SetRenderState( D3DRS_SHADEMODE,   D3DSHADE_FLAT );
0470:         // 両面描く
0471:         m_pd3dDevice->SetRenderState( D3DRS_CULLMODE,  D3DCULL_NONE );
0472: 
0473:         // 両面ステンシルを使用する
0474:         m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, TRUE );
0475:         m_pd3dDevice->SetRenderState( D3DRS_TWOSIDEDSTENCILMODE, TRUE );
0476: 
0477:         // ステンシルテストは常に合格する(=テストしない)
0478:         m_pd3dDevice->SetRenderState( D3DRS_STENCILFUNC,  D3DCMP_ALWAYS );
0479:         m_pd3dDevice->SetRenderState( D3DRS_CCW_STENCILFUNC,  D3DCMP_ALWAYS );
0480:         // ステンシルバッファの増減を1に設定する
0481:         m_pd3dDevice->SetRenderState( D3DRS_STENCILREF,    0x1 );
0482:         m_pd3dDevice->SetRenderState( D3DRS_STENCILMASK,      0xffffffff );
0483:         m_pd3dDevice->SetRenderState( D3DRS_STENCILWRITEMASK, 0xffffffff );
0484:         // 表面は深度テストに合格したらステンシルバッファの内容を+1する
0485:         m_pd3dDevice->SetRenderState( D3DRS_STENCILPASS,  D3DSTENCILOP_INCR );
0486:         m_pd3dDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP );
0487:         m_pd3dDevice->SetRenderState( D3DRS_STENCILFAIL,  D3DSTENCILOP_KEEP );
0488:         // 裏面は深度テストに合格したらステンシルバッファの内容を-1する
0489:         m_pd3dDevice->SetRenderState( D3DRS_CCW_STENCILPASS, D3DSTENCILOP_DECR );
0490:         m_pd3dDevice->SetRenderState( D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_KEEP );
0491:         m_pd3dDevice->SetRenderState( D3DRS_CCW_STENCILFAIL,  D3DSTENCILOP_KEEP );
0492: 
0493:         // レンダリングする
0494:         if( m_pFx != NULL ){
0495:             D3DXHANDLE hTechnique = m_pFx->GetTechniqueByName( "TShader" );
0496:             m_pFx->SetTechnique( hTechnique );
0497:             m_pFx->Begin( NULL, 0 );
0498:             m_pFx->Pass( 0 );
0499: 
0500:             // 小さい箱
0501:             D3DXMatrixScaling( &mS, 1.82f,1.65f, 1.82f );
0502:             D3DXMatrixRotationY( &mR, 0.59f*D3DX_PI );
0503:             D3DXMatrixTranslation( &mT, 2.73f-1.85f, 0.f , 1.69f );
0504:             mW = mS * mR * mT;
0505:             m = mW * m_mView * m_mProj;
0506:             if( m_hmWVP != NULL ) m_pFx->SetMatrix( m_hmWVP, &m );
0507:             D3DXMatrixInverse( &m, NULL, &mW);
0508:             D3DXVec3Transform( &v, &m_LighPos, &m );
0509:             if( m_hvPos != NULL ) m_pFx->SetVector( m_hvPos, &v );
0510:             m_pShadowBox->Render( m_pd3dDevice );
0511: 
0512:             // 大きい箱
0513:             D3DXMatrixScaling( &mS, 1.69f, 3.30f, 1.69f );
0514:             D3DXMatrixRotationY( &mR, 0.91f*D3DX_PI );
0515:             D3DXMatrixTranslation( &mT, 2.73f-3.685f, 0, 3.51f );
0516:             mW = mS * mR * mT;
0517:             m = mW * m_mView * m_mProj;
0518:             if( m_hmWVP != NULL ) m_pFx->SetMatrix( m_hmWVP, &m );
0519:             D3DXMatrixInverse( &m, NULL, &mW);
0520:             D3DXVec3Transform( &v, &m_LighPos, &m );
0521:             if( m_hvPos != NULL ) m_pFx->SetVector( m_hvPos, &v );
0522:             m_pShadowBox->Render( m_pd3dDevice );
0523: 
0524:             m_pFx->End();
0525:         }
0526: 
0527:         // 状態を元に戻す
0528:         m_pd3dDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD );
0529:         m_pd3dDevice->SetRenderState( D3DRS_CULLMODE,  D3DCULL_CCW );
0530:         m_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE,    TRUE );
0531:         m_pd3dDevice->SetRenderState( D3DRS_COLORWRITEENABLE,  0xf );
0532:         m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE,  FALSE );
0533:         m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
0534:         m_pd3dDevice->SetRenderState( D3DRS_TWOSIDEDSTENCILMODE, FALSE );
0535: 
0536:         // ----------------------------------------------------------
0537:         // パス2:影の描画
0538:         // ----------------------------------------------------------
0539:         // 深度テストはしない
0540:         m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,          FALSE );
0541:         // ステンシルテストはする
0542:         m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE,  TRUE );
0543:         // アルファブレンディングは線形に掛ける
0544:         m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
0545:         m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA );
0546:         m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
0547:         // ポリゴンを描画するときには、テクスチャと頂点色の両方を見る
0548:         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
0549:         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
0550:         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
0551:         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
0552:         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
0553:         m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE );
0554: 
0555:         // ステンシルバッファの値が1以上のときに書き込む
0556:         m_pd3dDevice->SetRenderState( D3DRS_STENCILREF,  0x1 );
0557:         m_pd3dDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL );
0558:         m_pd3dDevice->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_KEEP );
0559:         
0560:         m_pBigSquare->Render( m_pd3dDevice );
0561: 
0562:         // 状態を元に戻す
0563:         m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,          TRUE );
0564:         m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE,  FALSE );
0565:         m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
0566: 
0567:         // 状態表示の文字の描画  
0568:         RenderText();
0569: 
0570:         // 描画の終了
0571:         m_pd3dDevice->EndScene();
0572:     }
0573: 
0574:     return S_OK;
0575: }
0576: 
0577: 
0578: 
0579: 
0580: //-----------------------------------------------------------------------------
0581: // Name: RenderText()
0582: // Desc: Renders stats and help text to the scene.
0583: //-----------------------------------------------------------------------------
0584: HRESULT CMyD3DApplication::RenderText()
0585: {
0586:     D3DCOLOR fontColor        = D3DCOLOR_ARGB(255,255,255,0);
0587:     TCHAR szMsg[MAX_PATH] = TEXT("");
0588: 
0589:     // Output display stats
0590:     FLOAT fNextLine = 40.0f; 
0591: 
0592:     lstrcpy( szMsg, m_strDeviceStats );
0593:     fNextLine -= 20.0f;
0594:     m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
0595: 
0596:     lstrcpy( szMsg, m_strFrameStats );
0597:     fNextLine -= 20.0f;
0598:     m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
0599: 
0600:     // Output statistics & help
0601:     fNextLine = (FLOAT) m_d3dsdBackBuffer.Height; 
0602:     wsprintf( szMsg, TEXT("Arrow keys: Up=%d Down=%d Left=%d Right=%d"), 
0603:               m_UserInput.bRotateUp, m_UserInput.bRotateDown, m_UserInput.bRotateLeft, m_UserInput.bRotateRight );
0604:     fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
0605:     lstrcpy( szMsg, TEXT("Use arrow keys to rotate object") );
0606:     fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
0607:     lstrcpy( szMsg, TEXT("Press 'F2' to configure display") );
0608:     fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
0609:     return S_OK;
0610: }
0611: 
0612: 
0613: 
0614: 
0615: //-----------------------------------------------------------------------------
0616: // Name: MsgProc()
0617: // Desc: Overrrides the main WndProc, so the sample can do custom message
0618: //       handling (e.g. processing mouse, keyboard, or menu commands).
0619: //-----------------------------------------------------------------------------
0620: LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT msg, WPARAM wParam,
0621:                                     LPARAM lParam )
0622: {
0623:     switch( msg )
0624:     {
0625:         case WM_PAINT:
0626:         {
0627:             if( m_bLoadingApp )
0628:             {
0629:                 // Draw on the window tell the user that the app is loading
0630:                 // TODO: change as needed
0631:                 HDC hDC = GetDC( hWnd );
0632:                 TCHAR strMsg[MAX_PATH];
0633:                 wsprintf( strMsg, TEXT("Loading... Please wait") );
0634:                 RECT rct;
0635:                 GetClientRect( hWnd, &rct );
0636:                 DrawText( hDC, strMsg, -1, &rct, DT_CENTER|DT_VCENTER|DT_SINGLELINE );
0637:                 ReleaseDC( hWnd, hDC );
0638:             }
0639:             break;
0640:         }
0641: 
0642:     }
0643: 
0644:     return CD3DApplication::MsgProc( hWnd, msg, wParam, lParam );
0645: }
0646: 
0647: 
0648: 
0649: 
0650: //-----------------------------------------------------------------------------
0651: // Name: InvalidateDeviceObjects()
0652: // Desc: Invalidates device objects.  Paired with RestoreDeviceObjects()
0653: //-----------------------------------------------------------------------------
0654: HRESULT CMyD3DApplication::InvalidateDeviceObjects()
0655: {
0656:     if( m_pFx != NULL ) m_pFx->OnLostDevice();
0657:     m_pMeshBG->InvalidateDeviceObjects();
0658:     m_pMeshBox->InvalidateDeviceObjects();
0659: 
0660:     m_pFont->InvalidateDeviceObjects();
0661: 
0662:     return S_OK;
0663: }
0664: 
0665: 
0666: 
0667: 
0668: //-----------------------------------------------------------------------------
0669: // Name: DeleteDeviceObjects()
0670: // Desc: Paired with InitDeviceObjects()
0671: //       Called when the app is exiting, or the device is being changed,
0672: //       this function deletes any device dependent objects.  
0673: //-----------------------------------------------------------------------------
0674: HRESULT CMyD3DApplication::DeleteDeviceObjects()
0675: {
0676:     
0677:     SAFE_RELEASE( m_pFx );
0678: 
0679:     m_pMeshBG->Destroy();
0680:     m_pMeshBox->Destroy();
0681:     m_pShadowBox->Destroy();
0682: 
0683:     m_pBigSquare->Destroy();
0684:     
0685:     m_pFont->DeleteDeviceObjects();
0686: 
0687:     return S_OK;
0688: }
0689: 
0690: 
0691: 
0692: 
0693: //-----------------------------------------------------------------------------
0694: // Name: FinalCleanup()
0695: // Desc: Paired with OneTimeSceneInit()
0696: //       Called before the app exits, this function gives the app the chance
0697: //       to cleanup after itself.
0698: //-----------------------------------------------------------------------------
0699: HRESULT CMyD3DApplication::FinalCleanup()
0700: {
0701:     SAFE_DELETE( m_pShadowBox );
0702:     SAFE_DELETE( m_pMeshBox );
0703:     SAFE_DELETE( m_pMeshBG );
0704:     SAFE_DELETE( m_pBigSquare );
0705: 
0706:     SAFE_DELETE( m_pFont );
0707: 
0708:     return S_OK;
0709: }
0710: 
0711: 
0712: 
0713: 
0714: