Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //-----------------------------------------------------------------------------
- // Name: dx9_swap_chains.cpp
- // Author: Kevin Harris
- // Modified by: Seb (2012/11/04)
- // Description: This sample demonstrates how to render to multiple windows
- // using swap chains under DirectX 9.0. This is far more
- // efficient than creating multiple Direct3D devices.
- //
- // Control Keys: Left Mouse Button - Spin the teapot
- //-----------------------------------------------------------------------------
- #define STRICT
- #define WIN32_LEAN_AND_MEAN
- #include <windows.h>
- #include <mmsystem.h>
- #include <stdio.h>
- #include <d3d9.h>
- #include <d3dx9.h>
- #include "resource.h"
- #include <vector>
- using namespace std;
- const int NUM_WINDOWS = 15;
- //-----------------------------------------------------------------------------
- // GLOBALS
- //-----------------------------------------------------------------------------
- LPDIRECT3D9 g_pD3D = NULL;
- HWND g_hWnd_0 = NULL; // Handle to the first window
- vector<HWND> g_hwnds; // Handle to the second window
- LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; // For efficiency, we'll create a single
- LPDIRECT3DSWAPCHAIN9 g_swapChain_0 = NULL; // Direct3D device, which supports
- vector<LPDIRECT3DSWAPCHAIN9> g_swapChains;
- LPD3DXMESH g_pTeapotMesh = NULL;
- D3DMATERIAL9 g_teapotMtrl;
- D3DLIGHT9 g_pLight0;
- LPD3DXFONT g_pd3dxFont = NULL;
- float g_fSpinX = 0.0f;
- float g_fSpinY = 0.0f;
- double g_dElpasedFrameTime = 0.0f;
- double g_dElpasedAppTime = 0.0f;
- double g_dCurrentTime = 0.0f;
- double g_dLastTime = 0.0f;
- struct Vertex
- {
- float x, y, z; // Position of vertex in 3D space
- float nx, ny, nz; // Normal for lighting calculations
- DWORD diffuse; // Diffuse color of vertex
- enum FVF
- {
- FVF_Flags = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE
- };
- };
- //-----------------------------------------------------------------------------
- // PROTOTYPES
- //-----------------------------------------------------------------------------
- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
- LPSTR lpCmdLine, int nCmdShow);
- LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
- void init(void);
- void shutDown(void);
- void createFont(void);
- void renderToWindow_0(void);
- void renderWindow(HWND hwnd, LPDIRECT3DSWAPCHAIN9 swapchain);
- //-----------------------------------------------------------------------------
- // Name: WinMain()
- // Desc: The application's entry point
- //-----------------------------------------------------------------------------
- int WINAPI WinMain( HINSTANCE hInstance,
- HINSTANCE hPrevInstance,
- LPSTR lpCmdLine,
- int nCmdShow )
- {
- WNDCLASSEX winClass;
- MSG uMsg;
- memset(&uMsg,0,sizeof(uMsg));
- winClass.lpszClassName = "MY_WINDOWS_CLASS";
- winClass.cbSize = sizeof(WNDCLASSEX);
- winClass.style = CS_HREDRAW | CS_VREDRAW;
- winClass.lpfnWndProc = WindowProc;
- winClass.hInstance = hInstance;
- winClass.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON);
- winClass.hIconSm = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON);
- winClass.hCursor = LoadCursor(NULL, IDC_ARROW);
- winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
- winClass.lpszMenuName = NULL;
- winClass.cbClsExtra = 0;
- winClass.cbWndExtra = 0;
- if( !RegisterClassEx(&winClass) )
- return E_FAIL;
- //
- // Create window #0...
- //
- g_hWnd_0 = CreateWindowEx( NULL, "MY_WINDOWS_CLASS",
- "Direct3D (DX9) - Swap Chains (Window #0)",
- WS_OVERLAPPEDWINDOW | WS_VISIBLE,
- 0, 0, 640, 480, NULL, NULL, hInstance, NULL );
- if( g_hWnd_0 == NULL )
- return E_FAIL;
- ShowWindow( g_hWnd_0, nCmdShow );
- UpdateWindow( g_hWnd_0 );
- for (int i = 0; i < NUM_WINDOWS; i++)
- {
- HWND hwnd = CreateWindowEx( NULL, "MY_WINDOWS_CLASS",
- "Direct3D (DX9) - Swap Chains",
- WS_OVERLAPPEDWINDOW | WS_VISIBLE,
- 200, 200, 640, 480, NULL, NULL, hInstance, NULL );
- g_hwnds.push_back(hwnd);
- if (g_hwnds[i] == NULL)
- return E_FAIL;
- ShowWindow(hwnd, nCmdShow);
- UpdateWindow(hwnd);
- }
- init();
- g_dLastTime = timeGetTime();
- while( uMsg.message != WM_QUIT )
- {
- if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) )
- {
- TranslateMessage( &uMsg );
- DispatchMessage( &uMsg );
- }
- else
- {
- g_dCurrentTime = timeGetTime();
- g_dElpasedFrameTime = g_dCurrentTime - g_dLastTime; // How much time has passed since the last frame?
- g_dElpasedAppTime += g_dElpasedFrameTime; // How much time has passed overall for the application?
- g_dLastTime = g_dCurrentTime;
- //
- // Use the swap chains to render something to both windows...
- //
- renderToWindow_0();
- for (int i = 0; i < NUM_WINDOWS; i++)
- {
- renderWindow(g_hwnds[i], g_swapChains[i]);
- }
- //renderToWindow_1();
- /* renderWindow(g_hWnd_1, g_swapChain_1);
- renderWindow(g_hWnd_2, g_swapChain_2);*/
- }
- }
- shutDown();
- UnregisterClass( "MY_WINDOWS_CLASS", winClass.hInstance );
- return uMsg.wParam;
- }
- //-----------------------------------------------------------------------------
- // Name: WindowProc()
- // Desc: The window's message handler
- //-----------------------------------------------------------------------------
- LRESULT CALLBACK WindowProc( HWND hWnd,
- UINT msg,
- WPARAM wParam,
- LPARAM lParam )
- {
- static POINT ptLastMousePosit;
- static POINT ptCurrentMousePosit;
- static bool bMousing;
- switch( msg )
- {
- case WM_KEYDOWN:
- {
- switch( wParam )
- {
- case VK_ESCAPE:
- PostQuitMessage(0);
- break;
- }
- }
- break;
- case WM_LBUTTONDOWN:
- {
- ptLastMousePosit.x = ptCurrentMousePosit.x = LOWORD (lParam);
- ptLastMousePosit.y = ptCurrentMousePosit.y = HIWORD (lParam);
- bMousing = true;
- }
- break;
- case WM_LBUTTONUP:
- {
- bMousing = false;
- }
- break;
- case WM_MOUSEMOVE:
- {
- ptCurrentMousePosit.x = LOWORD (lParam);
- ptCurrentMousePosit.y = HIWORD (lParam);
- if( bMousing )
- {
- g_fSpinX -= (ptCurrentMousePosit.x - ptLastMousePosit.x);
- g_fSpinY -= (ptCurrentMousePosit.y - ptLastMousePosit.y);
- }
- ptLastMousePosit.x = ptCurrentMousePosit.x;
- ptLastMousePosit.y = ptCurrentMousePosit.y;
- }
- break;
- case WM_CLOSE:
- {
- PostQuitMessage(0);
- }
- case WM_DESTROY:
- {
- PostQuitMessage(0);
- }
- break;
- default:
- {
- return DefWindowProc( hWnd, msg, wParam, lParam );
- }
- break;
- }
- return 0;
- }
- //-----------------------------------------------------------------------------
- // Name: createFont()
- // Desc:
- //-----------------------------------------------------------------------------
- void createFont( void )
- {
- //
- // To create a Windows friendly font using only a point size, an
- // application must calculate the logical height of the font.
- //
- // This is because functions like CreateFont() and CreateFontIndirect()
- // only use logical units to specify height.
- //
- // Here's the formula to find the height in logical pixels:
- //
- // -( point_size * LOGPIXELSY )
- // height = ----------------------------
- // 72
- //
- HRESULT hr;
- HDC hDC;
- //HFONT hFont;
- int nHeight;
- int nPointSize = 9;
- //char strFontName[] = "Arial";
- hDC = GetDC( NULL );
- nHeight = -( MulDiv( nPointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72 ) );
- ReleaseDC( NULL, hDC );
- // Create a font for statistics and help output
- hr = D3DXCreateFont( g_pd3dDevice, nHeight, 0, FW_BOLD, 0, FALSE,
- DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
- DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"),
- &g_pd3dxFont );
- if( FAILED( hr ) )
- MessageBox(NULL,"Call to D3DXCreateFont failed!", "ERROR",MB_OK|MB_ICONEXCLAMATION);
- }
- //-----------------------------------------------------------------------------
- // Name: init()
- // Desc:
- //-----------------------------------------------------------------------------
- void init( void )
- {
- g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
- D3DDISPLAYMODE d3ddm;
- g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm );
- D3DPRESENT_PARAMETERS d3dpp;
- ZeroMemory( &d3dpp, sizeof(d3dpp) );
- d3dpp.Windowed = TRUE;
- d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
- d3dpp.BackBufferFormat = d3ddm.Format;
- d3dpp.EnableAutoDepthStencil = TRUE;
- d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
- d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
- g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
- g_hWnd_0, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
- &d3dpp, &g_pd3dDevice );
- createFont();
- //
- // Create additional swap chains for use by multiple windows...
- //
- // After CreateDevice, the first swap chain already exists, so just get it...
- g_pd3dDevice->GetSwapChain( 0, &g_swapChain_0 );
- // But the second one will need to be explicitly created...
- for (int i = 0; i < NUM_WINDOWS; i++)
- {
- LPDIRECT3DSWAPCHAIN9 sc;
- g_pd3dDevice->CreateAdditionalSwapChain( &d3dpp, &sc);
- g_swapChains.push_back(sc);
- }
- //g_pd3dDevice->CreateAdditionalSwapChain( &d3dpp, &g_swapChain_1 );
- //g_pd3dDevice->CreateAdditionalSwapChain( &d3dpp, &g_swapChain_2 );
- //
- // Continue to set up the Direct3D device like you normally would...
- //
- D3DXMATRIX matProj;
- D3DXMatrixPerspectiveFovLH( &matProj, D3DXToRadian( 45.0f ),
- 640.0f / 480.0f, 0.1f, 100.0f );
- g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
- g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
- // Setup a material for the teapot
- ZeroMemory( &g_teapotMtrl, sizeof(D3DMATERIAL9) );
- g_teapotMtrl.Diffuse.r = 1.0f;
- g_teapotMtrl.Diffuse.g = 1.0f;
- g_teapotMtrl.Diffuse.b = 1.0f;
- g_teapotMtrl.Diffuse.a = 1.0f;
- // Setup a simple directional light and some ambient...
- g_pLight0.Type = D3DLIGHT_DIRECTIONAL;
- g_pLight0.Direction = D3DXVECTOR3( 1.0f, 0.0f, 1.0f );
- g_pLight0.Diffuse.r = 1.0f;
- g_pLight0.Diffuse.g = 1.0f;
- g_pLight0.Diffuse.b = 1.0f;
- g_pLight0.Diffuse.a = 1.0f;
- g_pLight0.Specular.r = 1.0f;
- g_pLight0.Specular.g = 1.0f;
- g_pLight0.Specular.b = 1.0f;
- g_pLight0.Specular.a = 1.0f;
- g_pd3dDevice->SetLight( 0, &g_pLight0 );
- g_pd3dDevice->LightEnable( 0, TRUE );
- g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_COLORVALUE( 0.2f, 0.2f, 0.2f, 1.0f ) );
- // Load up the teapot mesh...
- D3DXLoadMeshFromX( "teapot.x", D3DXMESH_SYSTEMMEM, g_pd3dDevice,
- NULL, NULL, NULL, NULL, &g_pTeapotMesh );
- }
- //-----------------------------------------------------------------------------
- // Name: shutDown()
- // Desc:
- //-----------------------------------------------------------------------------
- void shutDown( void )
- {
- if( g_pTeapotMesh != NULL )
- g_pTeapotMesh->Release();
- if( g_swapChain_0 != NULL )
- g_swapChain_0->Release();
- for (int i = 0; i < NUM_WINDOWS; i++)
- {
- if (g_swapChains[i] != NULL)
- {
- g_swapChains[i]->Release();
- }
- }
- //if( g_swapChain_1 != NULL )
- // g_swapChain_1->Release();
- //if( g_swapChain_2 != NULL )
- // g_swapChain_2->Release();
- if( g_pd3dDevice != NULL )
- g_pd3dDevice->Release();
- if( g_pD3D != NULL )
- g_pD3D->Release();
- }
- //-----------------------------------------------------------------------------
- // Name: renderToWindow_0()
- // Desc:
- //-----------------------------------------------------------------------------
- void renderToWindow_0( void )
- {
- D3DXMATRIX matView;
- D3DXMATRIX matWorld;
- D3DXMATRIX matRotation;
- D3DXMATRIX matTranslation;
- // Tell the Direct3D device to render to the first swap chain’s back buffer
- LPDIRECT3DSURFACE9 pBackBuffer = NULL;
- g_swapChain_0->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
- g_pd3dDevice->SetRenderTarget( 0, pBackBuffer );
- // Clear the target buffer to red...
- g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
- D3DCOLOR_COLORVALUE( 1.0f, 0.0f, 0.0f, 1.0f ), 1.0f, 0 );
- g_pd3dDevice->BeginScene();
- {
- // For window #0, leave the view at the origin...
- D3DXMatrixIdentity( &matView );
- g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
- // ... and use the world matrix to spin and translate the teapot
- // out where we can see it...
- D3DXMatrixRotationYawPitchRoll( &matRotation, D3DXToRadian(g_fSpinX), D3DXToRadian(g_fSpinY), 0.0f );
- D3DXMatrixTranslation( &matTranslation, 0.0f, 0.0f, 4.0f );
- matWorld = matRotation * matTranslation;
- g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
- g_pd3dDevice->SetMaterial( &g_teapotMtrl );
- g_pTeapotMesh->DrawSubset(0);
- }
- g_pd3dDevice->EndScene();
- //Report frames per second and the number of objects culled...
- static int nFrameCount = 0;
- ++nFrameCount;
- static double nTimeOfLastFPSUpdate = 0.0;
- static char fpsString[50] = "Frames Per Second = ";
- if( g_dElpasedAppTime - nTimeOfLastFPSUpdate > 1000 ) // Update once a second
- {
- sprintf( fpsString, "Frames Per Second = %4.2f",
- nFrameCount*1000.0/(g_dElpasedAppTime - nTimeOfLastFPSUpdate) );
- nTimeOfLastFPSUpdate = g_dElpasedAppTime;
- nFrameCount = 0;
- }
- RECT destRect;
- SetRect( &destRect, 5, 5, 0, 0 );
- g_pd3dxFont->DrawText( NULL, fpsString, -1, &destRect, DT_NOCLIP,
- D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
- //Present swap chain #0 to window #0
- g_swapChain_0->Present( NULL, NULL, g_hWnd_0, NULL, 0 );
- pBackBuffer->Release();
- }
- void renderWindow(HWND hwnd, LPDIRECT3DSWAPCHAIN9 swapchain)
- {
- D3DXMATRIX matView;
- D3DXMATRIX matWorld;
- D3DXMATRIX matRotation;
- D3DXMATRIX matTranslation;
- // Tell the Direct3D device to render to the second swap chain’s back buffer
- LPDIRECT3DSURFACE9 pBackBuffer = NULL;
- swapchain->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
- g_pd3dDevice->SetRenderTarget( 0, pBackBuffer );
- // Clear the target buffer to green...
- g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
- D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f ), 1.0f, 0 );
- g_pd3dDevice->BeginScene();
- {
- D3DXMatrixRotationYawPitchRoll( &matRotation, D3DXToRadian(g_fSpinX), D3DXToRadian(g_fSpinY), 0.0f );
- D3DXMatrixTranslation( &matTranslation, 0.0f, 0.0f, 4.0f );
- matView = matRotation * matTranslation;
- g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
- // ... and don't bother with the world matrix at all.
- D3DXMatrixIdentity( &matWorld );
- g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
- g_pd3dDevice->SetMaterial( &g_teapotMtrl );
- g_pTeapotMesh->DrawSubset(0);
- }
- g_pd3dDevice->EndScene();
- swapchain->Present( NULL, NULL, hwnd, NULL, 0 );
- pBackBuffer->Release();
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement