www.pudn.com > waterworld_src_exe.rar > waterworld.cpp
//----------------------------------------------------------------------------- // File: waterworld.cpp // // Desc: DirectX window application created by the DirectX AppWizard //----------------------------------------------------------------------------- #define STRICT #include#include #include #include #include #include #include #include #include #include "DXUtil.h" #include "D3DEnumeration.h" #include "D3DSettings.h" #include "D3DApp.h" #include "D3DFont.h" #include "D3DUtil.h" #include "resource.h" #include "waterworld.h" //----------------------------------------------------------------------------- // Global access to the app (needed for the global WndProc()) //----------------------------------------------------------------------------- CMyD3DApplication* g_pApp = NULL; HINSTANCE g_hInst = NULL; /* regular vert with tangent */ typedef struct { D3DXVECTOR3 p; D3DXVECTOR3 n; D3DXVECTOR3 p2; // Wave Height Scale FLOAT tu1, tv1, tw1; D3DXVECTOR3 t; } VERTEX; D3DVERTEXELEMENT9 decl[] = { {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, {0, 24, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, {0, 36, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, {0, 48, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT, 0}, D3DDECL_END() }; #define D3DFVF_VERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1| D3DFVF_TEXCOORDSIZE3(0)) //----------------------------------------------------------------------------- // Name: WinMain() // Desc: Entry point to the program. Initializes everything, and goes into a // message-processing loop. Idle time is used to render the scene. //----------------------------------------------------------------------------- INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ) { CMyD3DApplication d3dApp; g_pApp = &d3dApp; g_hInst = hInst; InitCommonControls(); if( FAILED( d3dApp.Create( hInst ) ) ) return 0; return d3dApp.Run(); } //----------------------------------------------------------------------------- // Name: CMyD3DApplication() // Desc: Application constructor. Paired with ~CMyD3DApplication() // Member variables should be initialized to a known state here. // The application window has not yet been created and no Direct3D device // has been created, so any initialization that depends on a window or // Direct3D should be deferred to a later stage. //----------------------------------------------------------------------------- CMyD3DApplication::CMyD3DApplication() { m_dwCreationWidth = 500; m_dwCreationHeight = 375; m_strWindowTitle = TEXT( "waterworld" ); m_d3dEnumeration.AppUsesDepthBuffer = TRUE; m_bStartFullscreen = false; m_bShowCursorWhenFullscreen = false; // Create a D3D font using d3dfont.cpp m_pFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD ); m_bLoadingApp = TRUE; ZeroMemory( &m_UserInput, sizeof(m_UserInput) ); m_fWorldRotX = 0.0f; m_fWorldRotY = 0.0f; // Read settings from registry ReadSettings(); m_bShowHelp = FALSE; m_pStatsFont = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD ); m_pSmallFont = new CD3DFont( _T("Arial"), 9, D3DFONT_BOLD ); m_pVertBuff = NULL; m_pIndxBuff = NULL; m_pSkyBoxVertBuff = NULL; m_pSkyBoxIndxBuff = NULL; m_pTex = NULL; m_pHeightTex = NULL; m_psBumpMap = NULL; m_pCubeTex = NULL; m_dwNumVerts = 0; m_dwNumFaces = 0; m_bVertexShader = TRUE; m_bPixelShader = TRUE; m_bZBuffer = TRUE; D3DXMatrixIdentity( &m_matInitial ); } //----------------------------------------------------------------------------- // Name: ~CMyD3DApplication() // Desc: Application destructor. Paired with CMyD3DApplication() //----------------------------------------------------------------------------- CMyD3DApplication::~CMyD3DApplication() { } //----------------------------------------------------------------------------- // Name: OneTimeSceneInit() // Desc: Paired with FinalCleanup(). // The window has been created and the IDirect3D9 interface has been // created, but the device has not been created yet. Here you can // perform application-related initialization and cleanup that does // not depend on a device. //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::OneTimeSceneInit() { // TODO: perform one time initialization // Drawing loading status message until app finishes loading SendMessage( m_hWnd, WM_PAINT, 0, 0 ); m_bLoadingApp = FALSE; return S_OK; } //----------------------------------------------------------------------------- // Name: ReadSettings() // Desc: Read the app settings from the registry //----------------------------------------------------------------------------- VOID CMyD3DApplication::ReadSettings() { HKEY hkey; if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, DXAPP_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) ) { // TODO: change as needed // Read the stored window width/height. This is just an example, // of how to use DXUtil_Read*() functions. DXUtil_ReadIntRegKey( hkey, TEXT("Width"), &m_dwCreationWidth, m_dwCreationWidth ); DXUtil_ReadIntRegKey( hkey, TEXT("Height"), &m_dwCreationHeight, m_dwCreationHeight ); RegCloseKey( hkey ); } } //----------------------------------------------------------------------------- // Name: WriteSettings() // Desc: Write the app settings to the registry //----------------------------------------------------------------------------- VOID CMyD3DApplication::WriteSettings() { HKEY hkey; if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, DXAPP_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) ) { // TODO: change as needed // Write the window width/height. This is just an example, // of how to use DXUtil_Write*() functions. DXUtil_WriteIntRegKey( hkey, TEXT("Width"), m_rcWindowClient.right ); DXUtil_WriteIntRegKey( hkey, TEXT("Height"), m_rcWindowClient.bottom ); RegCloseKey( hkey ); } } //----------------------------------------------------------------------------- // Name: ConfirmDevice() // Desc: Called during device initialization, this code checks the display device // for some minimum set of capabilities //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior, D3DFORMAT Format ) { UNREFERENCED_PARAMETER( Format ); UNREFERENCED_PARAMETER( dwBehavior ); UNREFERENCED_PARAMETER( pCaps ); BOOL bCapsAcceptable; // TODO: Perform checks to see if these display caps are acceptable. bCapsAcceptable = TRUE; if( bCapsAcceptable ) return S_OK; else return E_FAIL; } //----------------------------------------------------------------------------- // Name: InitDeviceObjects() // Desc: Paired with DeleteDeviceObjects() // The device has been created. Resources that are not lost on // Reset() can be created here -- resources in D3DPOOL_MANAGED, // D3DPOOL_SCRATCH, or D3DPOOL_SYSTEMMEM. Image surfaces created via // CreateOffScreenPlainSurface are never lost and can be created here. Vertex // shaders and pixel shaders can also be created here as they are not // lost on Reset(). //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::InitDeviceObjects() { // TODO: create device objects HRESULT hr; hr = D3DXCreateTextureFromFile(m_pd3dDevice, "media\\Waterbump.bmp", &m_pHeightTex); if (FAILED(hr)) return hr; hr = D3DXCreateCubeTextureFromFile(m_pd3dDevice,"media\\skybox.dds", &m_pCubeTex); if (FAILED(hr)) return hr; m_pStatsFont->InitDeviceObjects( m_pd3dDevice ); m_pSmallFont->InitDeviceObjects( m_pd3dDevice ); if( FAILED( hr = m_pd3dDevice->CreateVertexDeclaration( decl, &m_pVertexDeclaration ) ) ) { return DXTRACE_ERR( TEXT("CreateVertexDeclaration"), hr ); } // Create and fill the bumpmap if( FAILED( InitBumpMap() ) ) return E_FAIL; return S_OK; } //----------------------------------------------------------------------------- // Name: RestoreDeviceObjects() // Desc: Paired with InvalidateDeviceObjects() // The device exists, but may have just been Reset(). Resources in // D3DPOOL_DEFAULT and any other device state that persists during // rendering should be set here. Render states, matrices, textures, // etc., that don't change during rendering can be set once here to // avoid redundant state setting during Render() or FrameMove(). //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::RestoreDeviceObjects() { m_pStatsFont->RestoreDeviceObjects(); m_pSmallFont->RestoreDeviceObjects(); m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); m_fCamXPos = 0.0f; m_fCamYPos = 0.0f; m_fCamZPos = 1.0f; m_fXCenter = 0.0f; m_fYCenter = 0.0f; m_fZCenter = 0.0f; // Set the transform matrices D3DXVECTOR3 vEyePt = D3DXVECTOR3( m_fCamXPos, m_fCamYPos, m_fCamZPos ); D3DXVECTOR3 vLookatPt = D3DXVECTOR3( m_fXCenter, m_fYCenter, m_fZCenter ); D3DXVECTOR3 vUpVec = D3DXVECTOR3( 0.0f, 1.0f, 0.0f ); D3DXMatrixIdentity( &m_matWorld ); D3DXMatrixLookAtLH( &m_matView, &vEyePt, &vLookatPt, &vUpVec ); FLOAT fAspect = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height; D3DXMatrixPerspectiveFovLH( &m_matProj, D3DX_PI/2, fAspect, 1.0f, 1000.0f ); m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matWorld ); m_pd3dDevice->SetTransform( D3DTS_VIEW, &m_matView ); m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &m_matProj ); D3DXMATRIX mat; D3DXMatrixIdentity( &m_matInitial); D3DXMatrixRotationX( &mat, D3DX_PI * 0.5f); D3DXMatrixMultiply( &m_matInitial, &m_matInitial, &mat ); D3DXMatrixTranslation( &mat, 0.0f, -1.5f, -10.0f); D3DXMatrixMultiply( &m_matInitial, &m_matInitial, &mat ); float radius = 20; int hres = 120; int vres = 40; m_dwNumFaces = hres * vres * 2; m_dwNumVerts = (hres + 1) * (vres + 1); HRESULT hr; // Create index buffer { WORD* pIndices; if( FAILED( hr = m_pd3dDevice->CreateIndexBuffer( m_dwNumFaces*sizeof(WORD)*3, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pIndxBuff,NULL ) ) ) return hr; if( FAILED( hr = m_pIndxBuff->Lock( 0, m_dwNumFaces*sizeof(WORD)*3, (void **)&pIndices, 0 ) ) ) return hr; int i; for (i = 0; i < hres; i++) for (int j = 0; j < vres; j++) { *pIndices++ = (WORD) (i * (vres + 1) + j ); *pIndices++ = (WORD) ((i + 1)* (vres + 1) + j + 1); *pIndices++ = (WORD) (i * (vres + 1) + j + 1); *pIndices++ = (WORD) (i * (vres + 1) + j ); *pIndices++ = (WORD) ((i + 1)* (vres + 1) + j ); *pIndices++ = (WORD) ((i + 1)* (vres + 1) + j + 1); } if( FAILED( hr = m_pIndxBuff->Unlock() ) ) return hr; } float xmin = -30.0f; float xmax = 30.0f; float ymin = -10.0f; float ymax = 10.0f; // Create vertex buffer { VERTEX *pVertices; if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( m_dwNumVerts*sizeof(VERTEX), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_pVertBuff,NULL ) ) ) return hr; if( FAILED( hr = m_pVertBuff->Lock( 0, m_dwNumVerts*sizeof(VERTEX), (void**)&pVertices, 0 ) ) ) return hr; for (int i = 0; i <= hres; i++) for (int j = 0; j <= vres; j++) { float ii = i/(float)hres; float jj = j/(float)vres; pVertices->n[0] = 0.0f; pVertices->n[1] = 0.0f; pVertices->n[2] = -1.0f; pVertices->t[0] = 0.0f; pVertices->t[1] = -1.0f; pVertices->t[2] = 0.0f; pVertices->p[0] = xmin + ii * (xmax - xmin); pVertices->p[1] = ymin + jj * (ymax - ymin);; pVertices->p[2] = 0.0f; pVertices->tu1 = ii; pVertices->tv1 = jj; pVertices->p2[0] = (float)(2.0f * max(fabs(ii - 0.5f), fabs(jj - 0.5f))); pVertices++; } if( FAILED( hr = m_pVertBuff->Unlock() ) ) return hr; } // Create SkyBox index buffer { WORD* pIndices; if( FAILED( hr = m_pd3dDevice->CreateIndexBuffer( 12*sizeof(WORD)*3, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pSkyBoxIndxBuff,NULL ) ) ) return hr; if( FAILED( hr = m_pSkyBoxIndxBuff->Lock( 0, 12*sizeof(WORD)*3, (void**)&pIndices, 0 ) ) ) return hr; *pIndices++ = 0; *pIndices++ = 2; *pIndices++ = 6; *pIndices++ = 0; *pIndices++ = 6; *pIndices++ = 4; *pIndices++ = 1; *pIndices++ = 3; *pIndices++ = 7; *pIndices++ = 1; *pIndices++ = 7; *pIndices++ = 5; *pIndices++ = 0; *pIndices++ = 2; *pIndices++ = 3; *pIndices++ = 0; *pIndices++ = 3; *pIndices++ = 1; *pIndices++ = 4; *pIndices++ = 7; *pIndices++ = 6; *pIndices++ = 4; *pIndices++ = 5; *pIndices++ = 7; *pIndices++ = 2; *pIndices++ = 7; *pIndices++ = 3; *pIndices++ = 2; *pIndices++ = 6; *pIndices++ = 7; *pIndices++ = 0; *pIndices++ = 1; *pIndices++ = 4; *pIndices++ = 4; *pIndices++ = 1; *pIndices++ = 5; if( FAILED( hr = m_pSkyBoxIndxBuff->Unlock() ) ) return hr; } // Create SkyBox vertex buffer { VERTEX *pVertices; if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( 8*sizeof(VERTEX), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &m_pSkyBoxVertBuff,NULL ) ) ) return hr; if( FAILED( hr = m_pSkyBoxVertBuff->Lock( 0, 8*sizeof(VERTEX), (void**)&pVertices, 0 ) ) ) return hr; radius = 80; for (int i = 0; i <= 1; i++) for (int j = 0; j <= 1; j++) for (int k = 0; k <= 1; k++) { float x = (float)(i * 2 - 1); float y = (float)(j * 2 - 1); float z = (float)(k * 2 - 1); pVertices->n[0] = x; pVertices->n[1] = y; pVertices->n[2] = 1; pVertices->p[0] = x * radius; pVertices->p[1] = y * radius; pVertices->p[2] = z * radius; pVertices++; } if( FAILED( hr = m_pSkyBoxVertBuff->Unlock() ) ) return hr; } // Create vertex shader { ID3DXBuffer* shader = 0; ID3DXBuffer* errorBuffer = 0; ID3DXConstantTable* MultiTexCT = 0; hr = D3DXCompileShaderFromFile( "shaders\\OceanWater.vsh", 0, 0, "Main", // entry point function name "vs_2_0", D3DXSHADER_DEBUG, &shader, &errorBuffer, &MultiTexCT); if(FAILED(hr)) { ::MessageBox(0, "D3DXCompileShaderFromFile() - FAILED", 0, 0); return false; } // Create Pixel Shader hr = m_pd3dDevice->CreateVertexShader( (DWORD*)shader->GetBufferPointer(), &m_pVertexShader); } // Create pixel shader { ID3DXBuffer* shader = 0; ID3DXBuffer* errorBuffer = 0; ID3DXConstantTable* MultiTexCT = 0; D3DXHANDLE BumpTex0Handle = 0; D3DXHANDLE BumpTex1Handle = 0; D3DXHANDLE CubeTexHandle = 0; D3DXCONSTANT_DESC BumpTex0Desc; D3DXCONSTANT_DESC BumpTex1Desc; D3DXCONSTANT_DESC CubeTexDesc; UINT count; hr = D3DXCompileShaderFromFile( "shaders\\OceanWater.psh", 0, 0, "Main", // entry point function name "ps_2_0", D3DXSHADER_DEBUG, &shader, &errorBuffer, &MultiTexCT); if(FAILED(hr)) { ::MessageBox(0, "D3DXCompileShaderFromFile() - FAILED", 0, 0); return false; } // Create Pixel Shader hr = m_pd3dDevice->CreatePixelShader( (DWORD*)shader->GetBufferPointer(), &m_pPixelShader); BumpTex0Handle = MultiTexCT->GetConstantByName(0, "BumpTex0"); BumpTex1Handle = MultiTexCT->GetConstantByName(0, "BumpTex1"); CubeTexHandle = MultiTexCT->GetConstantByName(0, "CubeTex"); MultiTexCT->GetConstantDesc(BumpTex0Handle,&BumpTex0Desc,&count); MultiTexCT->GetConstantDesc(BumpTex1Handle,&BumpTex1Desc,&count); MultiTexCT->GetConstantDesc(CubeTexHandle,&CubeTexDesc,&count); m_pd3dDevice->SetTexture(0, m_psBumpMap); m_pd3dDevice->SetTexture(1, m_psBumpMap); m_pd3dDevice->SetTexture(2, m_pCubeTex); m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetSamplerState( 1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetSamplerState( 1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetSamplerState( 2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); m_pd3dDevice->SetSamplerState( 2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); } return S_OK; } //----------------------------------------------------------------------------- // Name: FrameMove() // Desc: Called once per frame, the call is the entry point for animating // the scene. //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::FrameMove() { m_matWorld = m_matInitial; m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matWorld ); // Set up the vertex/pixel shader constants { // c0 - Composite World-View-Projection Matrix // c4 - ModelSpace Camera Position // c5 - {waveHeight0, waveHeight1, waveHeight2, waveHeight3} (0.04, 0.05, 0.0025, 0.0025) // c6 - {waveOffset0, waveOffset1, waveOffset2, waveOffset3} (0.0, 0.2, 0.0, 0.0) // c7 - {waveSpeed0, waveSpeed1, waveSpeed2, waveSpeed3} (0.2, 0.15, 0.4, 0.4) // c8 - {waveDirX0, waveDirX1, waveDirX2, waveDirX3} (0.25, 0.0, -0.7, -0.8) // c9 - {waveDirY0, waveDirY1, waveDirY2, waveDirY3} (0.0, 0.15, -0.7, 0.1) // c10 - { time } // c11 - {basetexcoord distortion x0, y0, x1, y1} (0.031, 0.04, -0.03, 0.02) // c12 - World Martix D3DXVECTOR4 c4( m_fCamXPos, m_fCamYPos, m_fCamZPos, 1.0 ); D3DXVECTOR4 c5( 0.04f, 0.05f, 0.0025f, 0.0025f ); D3DXVECTOR4 c6( 0.0f, 0.2f, 0.0f, 0.0f ); D3DXVECTOR4 c7( 0.2f, 0.15f, 0.4f, 0.4f ); D3DXVECTOR4 c8( 2.5f, 0.5f, -7.0f, -8.0f ); D3DXVECTOR4 c9( 1.0f, 1.5f, -7.0f, 1.0f ); D3DXVECTOR4 c10( (float)m_fTime*0.75f, 0.0f, 0.0f, 0.0f); D3DXVECTOR4 c11( 0.031f, 0.04f, -0.03f, 0.02f); m_pd3dDevice->SetVertexShaderConstantF( 4, c4, 1 ); m_pd3dDevice->SetVertexShaderConstantF( 5, c5, 1 ); m_pd3dDevice->SetVertexShaderConstantF( 6, c6, 1 ); m_pd3dDevice->SetVertexShaderConstantF( 7, c7, 1 ); m_pd3dDevice->SetVertexShaderConstantF( 8, c8, 1 ); m_pd3dDevice->SetVertexShaderConstantF( 9, c9, 1 ); m_pd3dDevice->SetVertexShaderConstantF( 10, c10, 1 ); m_pd3dDevice->SetVertexShaderConstantF( 11, c11, 1 ); D3DXMATRIX mat; D3DXMatrixMultiply( &mat, &m_matView, &m_matProj ); D3DXMatrixMultiply( &mat, &m_matWorld, &mat ); D3DXMatrixTranspose( &mat, &mat ); m_pd3dDevice->SetVertexShaderConstantF( 0, (float*)&mat, 4 ); D3DXMatrixTranspose( &mat, &m_matWorld ); m_pd3dDevice->SetVertexShaderConstantF( 12, (float*)&mat, 4 ); //c0 - watercolor (0.22f, 0.548f, 0.456f, 0.0206f) //c1 - highlightColor (0.8, 0.76, 0.62, 1) D3DXVECTOR4 c0p( 0.22f, 0.548f, 0.456f, 0.0206f ); D3DXVECTOR4 c1p( 0.8f, 0.76f, 0.62f, 1.0f ); m_pd3dDevice->SetPixelShaderConstantF( 0, c0p, 1 ); m_pd3dDevice->SetPixelShaderConstantF( 1, c1p, 1 ); } return S_OK; } //----------------------------------------------------------------------------- // Name: UpdateInput() // Desc: Update the user input. Called once per frame //----------------------------------------------------------------------------- void CMyD3DApplication::UpdateInput( UserInput* pUserInput ) { pUserInput->bRotateUp = ( m_bActive && (GetAsyncKeyState( VK_UP ) & 0x8000) == 0x8000 ); pUserInput->bRotateDown = ( m_bActive && (GetAsyncKeyState( VK_DOWN ) & 0x8000) == 0x8000 ); pUserInput->bRotateLeft = ( m_bActive && (GetAsyncKeyState( VK_LEFT ) & 0x8000) == 0x8000 ); pUserInput->bRotateRight = ( m_bActive && (GetAsyncKeyState( VK_RIGHT ) & 0x8000) == 0x8000 ); } //----------------------------------------------------------------------------- // Name: Render() // Desc: Called once per frame, the call is the entry point for 3d // rendering. This function sets up render states, clears the // viewport, and renders the scene. //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::Render() { // Clear the viewport m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000080, 1.0f, 0L ); // Begin the scene if( SUCCEEDED( m_pd3dDevice->BeginScene() ) ) { // Draw the Sky Box D3DXMATRIX mat; D3DXMatrixIdentity( &mat); m_pd3dDevice->SetTransform( D3DTS_WORLD, &mat ); m_pd3dDevice->SetTexture(0, m_pCubeTex); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL); m_pd3dDevice->SetVertexShader( NULL ); m_pd3dDevice->SetFVF(D3DFVF_VERTEX); m_pd3dDevice->SetStreamSource( 0, m_pSkyBoxVertBuff, 0,sizeof(VERTEX) ); m_pd3dDevice->SetIndices( m_pSkyBoxIndxBuff); m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,0, 0, 8, 0, 12 ); // Restore state to draw ocean m_pd3dDevice->SetTexture(2, m_pCubeTex); m_pd3dDevice->SetTexture(0, m_psBumpMap); m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matWorld ); m_pd3dDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0); m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, m_bZBuffer ); if (m_pVertexShader) { m_pd3dDevice->SetVertexDeclaration( m_pVertexDeclaration ); m_pd3dDevice->SetVertexShader( m_pVertexShader ); } if (m_pPixelShader) m_pd3dDevice->SetPixelShader( m_pPixelShader ); m_pd3dDevice->SetStreamSource( 0, m_pVertBuff, 0,sizeof(VERTEX) ); m_pd3dDevice->SetIndices( m_pIndxBuff); m_pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST,0, 0, m_dwNumVerts, 0, m_dwNumFaces ); // Show frame rate m_pStatsFont->DrawText( 2, 0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats ); m_pStatsFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats ); if( m_bShowHelp ) { m_pSmallFont->DrawText( 2, 40, D3DCOLOR_ARGB(255,255,255,255), _T("Keyboard controls:") ); m_pSmallFont->DrawText( 20, 60, D3DCOLOR_ARGB(255,255,255,255), _T("Help\nChange device\nExit") ); m_pSmallFont->DrawText( 210, 60, D3DCOLOR_ARGB(255,255,255,255), _T("F1\nF2\nEsc") ); } else { m_pSmallFont->DrawText( 2, 40, D3DCOLOR_ARGB(255,255,255,255), _T("Press F1 for help") ); } // End the scene. m_pd3dDevice->EndScene(); } return S_OK; } //----------------------------------------------------------------------------- // Name: InitBumpMap() // Desc: Converts data from m_pHeightTex into m_psBumpMap. //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::InitBumpMap() { LPDIRECT3DTEXTURE9 psBumpSrc = m_pHeightTex; D3DSURFACE_DESC d3dsd; D3DLOCKED_RECT d3dlr; psBumpSrc->GetLevelDesc( 0, &d3dsd ); // Create the bumpmap's surface and texture objects if( FAILED( m_pd3dDevice->CreateTexture( d3dsd.Width, d3dsd.Height, 1, 0, D3DFMT_V8U8, D3DPOOL_MANAGED, &m_psBumpMap,NULL ) ) ) { return E_FAIL; } // Fill the bits of the new texture surface with bits from // a private format. psBumpSrc->LockRect( 0, &d3dlr, 0, 0 ); DWORD dwSrcPitch = (DWORD)d3dlr.Pitch; BYTE* pSrcTopRow = (BYTE*)d3dlr.pBits; BYTE* pSrcCurRow = pSrcTopRow; BYTE* pSrcBotRow = pSrcTopRow + (dwSrcPitch * (d3dsd.Height - 1) ); m_psBumpMap->LockRect( 0, &d3dlr, 0, 0 ); DWORD dwDstPitch = (DWORD)d3dlr.Pitch; BYTE* pDstTopRow = (BYTE*)d3dlr.pBits; BYTE* pDstCurRow = pDstTopRow; //BYTE* pDstBotRow = pDstTopRow + (dwDstPitch * (d3dsd.Height - 1) ); for( DWORD y=0; y UnlockRect(0); psBumpSrc->UnlockRect(0); return S_OK; } //----------------------------------------------------------------------------- // Name: RenderText() // Desc: Renders stats and help text to the scene. //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::RenderText() { D3DCOLOR fontColor = D3DCOLOR_ARGB(255,255,255,0); TCHAR szMsg[MAX_PATH] = TEXT(""); // Output display stats FLOAT fNextLine = 40.0f; lstrcpy( szMsg, m_strDeviceStats ); fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); lstrcpy( szMsg, m_strFrameStats ); fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); // Output statistics & help fNextLine = (FLOAT) m_d3dsdBackBuffer.Height; wsprintf( szMsg, TEXT("Arrow keys: Up=%d Down=%d Left=%d Right=%d"), m_UserInput.bRotateUp, m_UserInput.bRotateDown, m_UserInput.bRotateLeft, m_UserInput.bRotateRight ); fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); sprintf( szMsg, TEXT("World State: %0.3f, %0.3f"), m_fWorldRotX, m_fWorldRotY ); fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); lstrcpy( szMsg, TEXT("Use arrow keys to update input") ); fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); lstrcpy( szMsg, TEXT("Press 'F2' to configure display") ); fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); return S_OK; } //----------------------------------------------------------------------------- // Name: MsgProc() // Desc: Overrrides the main WndProc, so the sample can do custom message // handling (e.g. processing mouse, keyboard, or menu commands). //----------------------------------------------------------------------------- LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) { // Trap context menu if( WM_CONTEXTMENU == msg ) return 0; // Perform commands when keys are released if( WM_KEYUP == msg ) { switch( wParam ) { case VK_F1: m_bShowHelp = !m_bShowHelp; break; } } return CD3DApplication::MsgProc( hWnd, msg, wParam, lParam ); } //----------------------------------------------------------------------------- // Name: InvalidateDeviceObjects() // Desc: Invalidates device objects. Paired with RestoreDeviceObjects() //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::InvalidateDeviceObjects() { // TODO: Cleanup any objects created in RestoreDeviceObjects() SAFE_RELEASE( m_pVertBuff ); SAFE_RELEASE( m_pIndxBuff ); SAFE_RELEASE( m_pSkyBoxVertBuff ); SAFE_RELEASE( m_pSkyBoxIndxBuff ); SAFE_RELEASE( m_pVertexShader ); SAFE_RELEASE( m_pPixelShader ); m_pStatsFont->InvalidateDeviceObjects(); m_pSmallFont->InvalidateDeviceObjects(); return S_OK; } //----------------------------------------------------------------------------- // Name: DeleteDeviceObjects() // Desc: Paired with InitDeviceObjects() // Called when the app is exiting, or the device is being changed, // this function deletes any device dependent objects. //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::DeleteDeviceObjects() { // TODO: Cleanup any objects created in InitDeviceObjects() SAFE_RELEASE( m_pVertBuff ); SAFE_RELEASE( m_pIndxBuff ); SAFE_RELEASE( m_pSkyBoxVertBuff ); SAFE_RELEASE( m_pSkyBoxIndxBuff ); m_pd3dDevice->SetTexture(0, NULL); m_pd3dDevice->SetTexture(1, NULL); SAFE_RELEASE( m_pTex ); SAFE_RELEASE( m_pHeightTex ); SAFE_RELEASE( m_psBumpMap ); SAFE_RELEASE( m_pCubeTex ); SAFE_RELEASE( m_pVertexDeclaration); m_pStatsFont->DeleteDeviceObjects(); m_pSmallFont->DeleteDeviceObjects(); return S_OK; } //----------------------------------------------------------------------------- // Name: FinalCleanup() // Desc: Paired with OneTimeSceneInit() // Called before the app exits, this function gives the app the chance // to cleanup after itself. //----------------------------------------------------------------------------- HRESULT CMyD3DApplication::FinalCleanup() { // TODO: Perform any final cleanup needed // Cleanup D3D font SAFE_DELETE( m_pStatsFont ); SAFE_DELETE( m_pSmallFont ); return S_OK; }