Microsoft DirectX 8.1 (C++) |
The Microsoft® DirectX® 8.1 and Microsoft® Direct3D® Software Development Kit (SDK) graphics sample framework is an evolution from the DirectX 7.0 graphics sample framework. The SDK samples are installed by default in \Dxsdk\Samples\Multimedia. The folders of interest are Common and Direct3D. The sample framework is contained in the Common folder and the Direct3D samples based on the graphics framework are contained in the Direct3D folder.
The graphics framework consists of five source modules.
Corresponding header files are located in the Common\Include folder.
Each sample implements a subclass of CD3DApplication, which is typically named CMyD3DApplication, and set of overridables that are shown below.
// Overridable functions for the 3 dimensional scene created by the application virtual HRESULT ConfirmDevice(D3DCAPS8*,DWORD,D3DFORMAT) { return S_OK; } virtual HRESULT OneTimeSceneInit() { return S_OK; } virtual HRESULT InitDeviceObjects() { return S_OK; } virtual HRESULT RestoreDeviceObjects() { return S_OK; } virtual HRESULT FrameMove() { return S_OK; } virtual HRESULT Render() { return S_OK; } virtual HRESULT InvalidateDeviceObjects() { return S_OK; } virtual HRESULT DeleteDeviceObjects() { return S_OK; } virtual HRESULT FinalCleanup() { return S_OK; } The prototypes for these methods are contained in d3dapp.h in the
CD3Dapplication class. The samples create a new Direct3D application and override
those methods that are needed by the application.
This example uses a subset of the overrideable methods. The class CMyD3DApplication contains the following methods. Each of these methods is explained below.
class CMyD3DApplication : public CD3DApplication { public: CMyD3DApplication(); protected: HRESULT ConfirmDevice( D3DCAPS8*, DWORD, D3DFORMAT ); HRESULT DeleteRestoreDeviceObjects(); HRESULT RestoreDeviceObjects(); HRESULT FrameMove(); HRESULT Render(); private: LPDIRECT3DVERTEXBUFFER8 m_pVB; // Vertex buffer to hold vertices };
The constructor initializes the window title, enables depth buffering and initializes the vertex buffer.
CMyD3DApplication::CMyD3DApplication() { m_strWindowTitle = _T("D3D Example"); // title bar string m_bUseDepthBuffer = TRUE; // enable depth buffer m_pVB = NULL; // initialize }
The window title is a wide character string that is visible in the title bar or the window class when the application is invoked. It is optional.
The base class contains a member variable for enabling depth buffering. The default value for this boolean variable is FALSE, which disables depth buffering.
The window title is a wide character string that is visible in the title bar or the window class when the application is invoked. It is optional.
DeleteDeviceObjects is called when the application is exiting, or if the device is being changed. You use this method to delete device dependent objects, such as the vertex buffer.
HRESULT CVShader1::DeleteDeviceObjects() { m_pQuadVB->Release(); m_pQuadVB = NULL; return S_OK; }
This method is called when the application needs to restore device memory objects and device states. This is required after a DirectX device is created or resized. This method does most of the work of creating objects and initializing render states.
HRESULT CMyD3DApplication::RestoreDeviceObjects() { // Create the vertex buffer. Allocate enough memory (from the default pool) // to hold the custom vertices. Specify the flexible vertex format (FVF), so the vertex buffer knows what // data it contains. if( FAILED( m_pd3dDevice->CreateVertexBuffer( NUM_VERTS*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &m_pVB ) ) ) { return E_FAIL; } // Fill the vertex buffer. First, lock the vertex buffer to get access to the // vertices. This mechanism is required because vertex buffers may be in device // memory. Then use memcpy to do a fast data copy. VOID* pVertices; if( FAILED( m_pVB->Lock( 0, sizeof(g_Vertices), (BYTE**)&pVertices, 0 ) ) ) return E_FAIL; memcpy( pVertices, g_Vertices, sizeof(g_Vertices) ); m_pVB->Unlock(); // Set the projection matrix. The size of the back buffer comes from the base // class D3DXMATRIX matProj; FLOAT fAspect = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, fAspect, 1.0f, 100.0f ); m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj ); // Set up the view matrix. A view matrix can be defined from an eye // point, a look at point and an up direction vector. In this example, // the eye position is (0,1,-4) the look at point is (0,0,0) and the // up vector is (0,1,0. D3DXMATRIX matView; D3DXMatrixLookAtLH( &matView, &D3DXVECTOR3( 0.0f, 1.0f,-4.0f ), &D3DXVECTOR3( 0.0f, 0.0f, 0.0f ), &D3DXVECTOR3( 0.0f, 1.0f, 0.0f ) ); m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView ); // Set up default texture states // Set up render states ( this is only one example renderstate ) m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); return S_OK; }
This method creates the vertex buffer and copies the vertex data into it. It creates the view and projection matrices, which define the camera orientation to the object in the vertex buffer. Texture stage states can be set in this method although none are present in this example. Render states that are not likely to change are set. These determine how the scene renders.
This method contains actions that happen every frame such as animation. In this example, it adds a y axis rotation to the world transform.
HRESULT CMyD3DApplication::FrameMove() { // For our world matrix, just rotate the object about the y-axis. D3DXMATRIX matWorld; D3DXMatrixRotationY( &matWorld, ::TimeGetTime()/150.0f ); m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld ); return S_OK; }
The Windows method ::TimeGetTime() is used to return the current time. Once it is divided by 150, this generates a incremental angle to rotate the object.
This method is called when it is time to render the output. This function clears the view port and render the scene. It also renders state changes.
HRESULT CMyD3DApplication::Render() { // Clear the viewport m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0,0,0), 1.0f, 0L ); // Begin the scene if( SUCCEEDED( m_pd3dDevice->BeginScene() ) ) { m_pd3dDevice->SetStreamSource( 0, m_pVB, sizeof(CUSTOMVERTEX) ); m_pd3dDevice->SetVertexShader( D3DFVF_CUSTOMVERTEX ); m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, NUM_TRIS ); m_pd3dDevice->EndScene(); } return S_OK; }
The Render method first clears the viewport using Clear. Then, within the BeginScne/EndScene pair it uses SetStreamSource to inform the runtime that it uses vertex buffer m_pVB with a stride of the size of the custom vertex type. Then, it informs the runtime that it uses a flexible vertex format (FVF) shader, the simplest type. Finally it invokes DrawPrimitive to render the quad.
DeleteDeviceObjects is called when the application exits, or if the device changes. You use this method to delete device dependent objects.
ConfirmDevice checks the device for some minimum set of capabilities. It is called during the device initialization.
InvalidateDeviceObjects is called when the device dependent objects might be removed. Device dependent objects such as vertex buffers are usually added to this method.
OneTimeSceneInit is provided for code that needs to run during the initial application startup.
DirectXDev for graphics, networking, and input at http://DISCUSS.MICROSOFT.COM/archives/DIRECTXDEV.html.