Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

DirectX9 Multi-window test

By: a guest on Nov 3rd, 2012  |  syntax: C++  |  size: 15.37 KB  |  views: 153  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. //-----------------------------------------------------------------------------
  2. //           Name: dx9_swap_chains.cpp
  3. //         Author: Kevin Harris
  4. //    Modified by: Seb (2012/11/04)
  5. //    Description: This sample demonstrates how to render to multiple windows
  6. //                 using swap chains under DirectX 9.0. This is far more
  7. //                 efficient than creating multiple Direct3D devices.
  8. //
  9. //   Control Keys: Left Mouse Button - Spin the teapot
  10. //-----------------------------------------------------------------------------
  11.  
  12. #define STRICT
  13. #define WIN32_LEAN_AND_MEAN
  14.  
  15. #include <windows.h>
  16. #include <mmsystem.h>
  17. #include <stdio.h>
  18. #include <d3d9.h>
  19. #include <d3dx9.h>
  20. #include "resource.h"
  21. #include <vector>
  22.  
  23. using namespace std;
  24.  
  25. const int NUM_WINDOWS = 15;
  26.  
  27. //-----------------------------------------------------------------------------
  28. // GLOBALS
  29. //-----------------------------------------------------------------------------
  30. LPDIRECT3D9 g_pD3D   = NULL;
  31. HWND        g_hWnd_0 = NULL; // Handle to the first window
  32. vector<HWND> g_hwnds; // Handle to the second window
  33.  
  34. LPDIRECT3DDEVICE9    g_pd3dDevice  = NULL; // For efficiency, we'll create a single
  35. LPDIRECT3DSWAPCHAIN9 g_swapChain_0 = NULL; // Direct3D device, which supports
  36. vector<LPDIRECT3DSWAPCHAIN9> g_swapChains;
  37.  
  38. LPD3DXMESH   g_pTeapotMesh = NULL;
  39. D3DMATERIAL9 g_teapotMtrl;
  40. D3DLIGHT9    g_pLight0;
  41.  
  42. LPD3DXFONT g_pd3dxFont = NULL;
  43.  
  44. float g_fSpinX = 0.0f;
  45. float g_fSpinY = 0.0f;
  46.  
  47. double g_dElpasedFrameTime = 0.0f;
  48. double g_dElpasedAppTime   = 0.0f;
  49. double g_dCurrentTime      = 0.0f;
  50. double g_dLastTime         = 0.0f;
  51.  
  52. struct Vertex
  53. {
  54.     float x, y, z;    // Position of vertex in 3D space
  55.     float nx, ny, nz; // Normal for lighting calculations
  56.     DWORD diffuse;    // Diffuse color of vertex
  57.  
  58.         enum FVF
  59.         {
  60.                 FVF_Flags = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE
  61.         };
  62. };
  63.  
  64. //-----------------------------------------------------------------------------
  65. // PROTOTYPES
  66. //-----------------------------------------------------------------------------
  67. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  68.                                    LPSTR lpCmdLine, int nCmdShow);
  69. LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
  70. void init(void);
  71. void shutDown(void);
  72. void createFont(void);
  73. void renderToWindow_0(void);
  74. void renderWindow(HWND hwnd, LPDIRECT3DSWAPCHAIN9 swapchain);
  75.  
  76. //-----------------------------------------------------------------------------
  77. // Name: WinMain()
  78. // Desc: The application's entry point
  79. //-----------------------------------------------------------------------------
  80. int WINAPI WinMain(     HINSTANCE hInstance,
  81.                                         HINSTANCE hPrevInstance,
  82.                                         LPSTR     lpCmdLine,
  83.                                         int       nCmdShow )
  84. {
  85.         WNDCLASSEX winClass;
  86.         MSG        uMsg;
  87.  
  88.     memset(&uMsg,0,sizeof(uMsg));
  89.    
  90.         winClass.lpszClassName = "MY_WINDOWS_CLASS";
  91.         winClass.cbSize        = sizeof(WNDCLASSEX);
  92.         winClass.style         = CS_HREDRAW | CS_VREDRAW;
  93.         winClass.lpfnWndProc   = WindowProc;
  94.         winClass.hInstance     = hInstance;
  95.         winClass.hIcon         = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON);
  96.     winClass.hIconSm       = LoadIcon(hInstance, (LPCTSTR)IDI_DIRECTX_ICON);
  97.         winClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
  98.         winClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
  99.         winClass.lpszMenuName  = NULL;
  100.         winClass.cbClsExtra    = 0;
  101.         winClass.cbWndExtra    = 0;
  102.  
  103.         if( !RegisterClassEx(&winClass) )
  104.                 return E_FAIL;
  105.  
  106.     //
  107.     // Create window #0...
  108.     //
  109.  
  110.         g_hWnd_0 = CreateWindowEx( NULL, "MY_WINDOWS_CLASS",
  111.                                "Direct3D (DX9) - Swap Chains (Window #0)",
  112.                                                        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
  113.                                                    0, 0, 640, 480, NULL, NULL, hInstance, NULL );
  114.  
  115.         if( g_hWnd_0 == NULL )
  116.                 return E_FAIL;
  117.  
  118.     ShowWindow( g_hWnd_0, nCmdShow );
  119.     UpdateWindow( g_hWnd_0 );
  120.  
  121.  
  122.         for (int i = 0; i < NUM_WINDOWS; i++)
  123.         {
  124.                 HWND hwnd = CreateWindowEx( NULL, "MY_WINDOWS_CLASS",
  125.                                "Direct3D (DX9) - Swap Chains",
  126.                                                        WS_OVERLAPPEDWINDOW | WS_VISIBLE,
  127.                                                    200, 200, 640, 480, NULL, NULL, hInstance, NULL );
  128.  
  129.                 g_hwnds.push_back(hwnd);
  130.  
  131.                 if (g_hwnds[i] == NULL)
  132.                         return E_FAIL;
  133.  
  134.                 ShowWindow(hwnd, nCmdShow);
  135.                 UpdateWindow(hwnd);
  136.         }
  137.  
  138.         init();
  139.  
  140.     g_dLastTime = timeGetTime();
  141.  
  142.         while( uMsg.message != WM_QUIT )
  143.         {
  144.                 if( PeekMessage( &uMsg, NULL, 0, 0, PM_REMOVE ) )
  145.                 {
  146.                         TranslateMessage( &uMsg );
  147.                         DispatchMessage( &uMsg );
  148.                 }
  149.         else
  150.         {
  151.             g_dCurrentTime = timeGetTime();
  152.             g_dElpasedFrameTime = g_dCurrentTime - g_dLastTime; // How much time has passed since the last frame?
  153.             g_dElpasedAppTime += g_dElpasedFrameTime; // How much time has passed overall for the application?
  154.             g_dLastTime = g_dCurrentTime;
  155.  
  156.             //
  157.             // Use the swap chains to render something to both windows...
  158.             //
  159.  
  160.                     renderToWindow_0();
  161.  
  162.                         for (int i = 0; i < NUM_WINDOWS; i++)
  163.                         {
  164.                                 renderWindow(g_hwnds[i], g_swapChains[i]);
  165.                         }
  166.  
  167.             //renderToWindow_1();
  168.                 /*      renderWindow(g_hWnd_1, g_swapChain_1);
  169.                         renderWindow(g_hWnd_2, g_swapChain_2);*/
  170.         }
  171.         }
  172.  
  173.     shutDown();
  174.  
  175.     UnregisterClass( "MY_WINDOWS_CLASS", winClass.hInstance );
  176.  
  177.         return uMsg.wParam;
  178. }
  179.  
  180. //-----------------------------------------------------------------------------
  181. // Name: WindowProc()
  182. // Desc: The window's message handler
  183. //-----------------------------------------------------------------------------
  184. LRESULT CALLBACK WindowProc( HWND   hWnd,
  185.                                                          UINT   msg,
  186.                                                          WPARAM wParam,
  187.                                                          LPARAM lParam )
  188. {
  189.         static POINT ptLastMousePosit;
  190.         static POINT ptCurrentMousePosit;
  191.         static bool bMousing;
  192.        
  193.     switch( msg )
  194.         {
  195.         case WM_KEYDOWN:
  196.                 {
  197.                         switch( wParam )
  198.                         {
  199.                                 case VK_ESCAPE:
  200.                                         PostQuitMessage(0);
  201.                                         break;
  202.                         }
  203.                 }
  204.         break;
  205.  
  206.                 case WM_LBUTTONDOWN:
  207.                 {
  208.                         ptLastMousePosit.x = ptCurrentMousePosit.x = LOWORD (lParam);
  209.             ptLastMousePosit.y = ptCurrentMousePosit.y = HIWORD (lParam);
  210.                         bMousing = true;
  211.                 }
  212.                 break;
  213.  
  214.                 case WM_LBUTTONUP:
  215.                 {
  216.                         bMousing = false;
  217.                 }
  218.                 break;
  219.  
  220.                 case WM_MOUSEMOVE:
  221.                 {
  222.                         ptCurrentMousePosit.x = LOWORD (lParam);
  223.                         ptCurrentMousePosit.y = HIWORD (lParam);
  224.  
  225.                         if( bMousing )
  226.                         {
  227.                                 g_fSpinX -= (ptCurrentMousePosit.x - ptLastMousePosit.x);
  228.                                 g_fSpinY -= (ptCurrentMousePosit.y - ptLastMousePosit.y);
  229.                         }
  230.  
  231.                         ptLastMousePosit.x = ptCurrentMousePosit.x;
  232.             ptLastMousePosit.y = ptCurrentMousePosit.y;
  233.                 }
  234.                 break;
  235.  
  236.                 case WM_CLOSE:
  237.                 {
  238.                         PostQuitMessage(0);
  239.                 }
  240.                
  241.         case WM_DESTROY:
  242.                 {
  243.             PostQuitMessage(0);
  244.                 }
  245.         break;
  246.  
  247.                 default:
  248.                 {
  249.                         return DefWindowProc( hWnd, msg, wParam, lParam );
  250.                 }
  251.                 break;
  252.         }
  253.  
  254.         return 0;
  255. }
  256.  
  257. //-----------------------------------------------------------------------------
  258. // Name: createFont()
  259. // Desc:
  260. //-----------------------------------------------------------------------------
  261. void createFont( void )
  262. {
  263.     //
  264.     // To create a Windows friendly font using only a point size, an
  265.     // application must calculate the logical height of the font.
  266.     //
  267.     // This is because functions like CreateFont() and CreateFontIndirect()
  268.     // only use logical units to specify height.
  269.     //
  270.     // Here's the formula to find the height in logical pixels:
  271.     //
  272.     //             -( point_size * LOGPIXELSY )
  273.     //    height = ----------------------------
  274.     //                          72
  275.     //
  276.  
  277.     HRESULT hr;
  278.     HDC hDC;
  279.     //HFONT hFont;
  280.     int nHeight;
  281.     int nPointSize = 9;
  282.     //char strFontName[] = "Arial";
  283.  
  284.     hDC = GetDC( NULL );
  285.  
  286.     nHeight = -( MulDiv( nPointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72 ) );
  287.  
  288.     ReleaseDC( NULL, hDC );
  289.  
  290.  
  291.     // Create a font for statistics and help output
  292.     hr = D3DXCreateFont( g_pd3dDevice, nHeight, 0, FW_BOLD, 0, FALSE,
  293.                          DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
  294.                          DEFAULT_PITCH | FF_DONTCARE, TEXT("Arial"),
  295.                          &g_pd3dxFont );
  296.  
  297.     if( FAILED( hr ) )
  298.         MessageBox(NULL,"Call to D3DXCreateFont failed!", "ERROR",MB_OK|MB_ICONEXCLAMATION);
  299. }
  300.  
  301. //-----------------------------------------------------------------------------
  302. // Name: init()
  303. // Desc:
  304. //-----------------------------------------------------------------------------
  305. void init( void )
  306. {
  307.     g_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
  308.  
  309.     D3DDISPLAYMODE d3ddm;
  310.  
  311.     g_pD3D->GetAdapterDisplayMode( D3DADAPTER_DEFAULT, &d3ddm );
  312.  
  313.     D3DPRESENT_PARAMETERS d3dpp;
  314.     ZeroMemory( &d3dpp, sizeof(d3dpp) );
  315.        
  316.     d3dpp.Windowed               = TRUE;
  317.     d3dpp.SwapEffect             = D3DSWAPEFFECT_DISCARD;
  318.     d3dpp.BackBufferFormat       = d3ddm.Format;
  319.     d3dpp.EnableAutoDepthStencil = TRUE;
  320.     d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
  321.     d3dpp.PresentationInterval   = D3DPRESENT_INTERVAL_ONE;
  322.  
  323.     g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
  324.                                                   g_hWnd_0, D3DCREATE_SOFTWARE_VERTEXPROCESSING,
  325.                                                   &d3dpp, &g_pd3dDevice );
  326.  
  327.     createFont();
  328.  
  329.         //
  330.         // Create additional swap chains for use by multiple windows...
  331.         //
  332.  
  333.         // After CreateDevice, the first swap chain already exists, so just get it...
  334.         g_pd3dDevice->GetSwapChain( 0, &g_swapChain_0 );
  335.  
  336.         // But the second one will need to be explicitly created...
  337.  
  338.         for (int i = 0; i < NUM_WINDOWS; i++)
  339.         {
  340.                 LPDIRECT3DSWAPCHAIN9 sc;
  341.                 g_pd3dDevice->CreateAdditionalSwapChain( &d3dpp, &sc);
  342.                 g_swapChains.push_back(sc);
  343.         }
  344.  
  345.         //g_pd3dDevice->CreateAdditionalSwapChain( &d3dpp, &g_swapChain_1 );
  346.  
  347.         //g_pd3dDevice->CreateAdditionalSwapChain( &d3dpp, &g_swapChain_2 );
  348.  
  349.         //
  350.         // Continue to set up the Direct3D device like you normally would...
  351.         //
  352.  
  353.     D3DXMATRIX matProj;
  354.         D3DXMatrixPerspectiveFovLH( &matProj, D3DXToRadian( 45.0f ),
  355.                                 640.0f / 480.0f, 0.1f, 100.0f );
  356.     g_pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
  357.  
  358.     g_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
  359.     g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
  360.     g_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
  361.  
  362.     // Setup a material for the teapot
  363.     ZeroMemory( &g_teapotMtrl, sizeof(D3DMATERIAL9) );
  364.     g_teapotMtrl.Diffuse.r = 1.0f;
  365.     g_teapotMtrl.Diffuse.g = 1.0f;
  366.     g_teapotMtrl.Diffuse.b = 1.0f;
  367.     g_teapotMtrl.Diffuse.a = 1.0f;
  368.  
  369.     // Setup a simple directional light and some ambient...
  370.         g_pLight0.Type = D3DLIGHT_DIRECTIONAL;
  371.         g_pLight0.Direction = D3DXVECTOR3( 1.0f, 0.0f, 1.0f );
  372.  
  373.     g_pLight0.Diffuse.r = 1.0f;
  374.     g_pLight0.Diffuse.g = 1.0f;
  375.     g_pLight0.Diffuse.b = 1.0f;
  376.         g_pLight0.Diffuse.a = 1.0f;
  377.  
  378.         g_pLight0.Specular.r = 1.0f;
  379.         g_pLight0.Specular.g = 1.0f;
  380.         g_pLight0.Specular.b = 1.0f;
  381.         g_pLight0.Specular.a = 1.0f;
  382.  
  383.     g_pd3dDevice->SetLight( 0, &g_pLight0 );
  384.     g_pd3dDevice->LightEnable( 0, TRUE );
  385.  
  386.     g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_COLORVALUE( 0.2f, 0.2f, 0.2f, 1.0f ) );
  387.  
  388.     // Load up the teapot mesh...
  389.     D3DXLoadMeshFromX( "teapot.x", D3DXMESH_SYSTEMMEM, g_pd3dDevice,
  390.                        NULL, NULL, NULL, NULL, &g_pTeapotMesh );
  391. }
  392.  
  393. //-----------------------------------------------------------------------------
  394. // Name: shutDown()
  395. // Desc:
  396. //-----------------------------------------------------------------------------
  397. void shutDown( void )
  398. {
  399.     if( g_pTeapotMesh != NULL )
  400.         g_pTeapotMesh->Release();
  401.  
  402.         if( g_swapChain_0 != NULL )
  403.                 g_swapChain_0->Release();
  404.  
  405.         for (int i = 0; i < NUM_WINDOWS; i++)
  406.         {
  407.                 if (g_swapChains[i] != NULL)
  408.                 {
  409.                         g_swapChains[i]->Release();
  410.                 }
  411.         }
  412.  
  413.         //if( g_swapChain_1 != NULL )
  414.         //      g_swapChain_1->Release();
  415.  
  416.         //if( g_swapChain_2 != NULL )
  417.         //      g_swapChain_2->Release();
  418.  
  419.     if( g_pd3dDevice != NULL )
  420.         g_pd3dDevice->Release();
  421.  
  422.     if( g_pD3D != NULL )
  423.         g_pD3D->Release();
  424. }
  425.  
  426. //-----------------------------------------------------------------------------
  427. // Name: renderToWindow_0()
  428. // Desc:
  429. //-----------------------------------------------------------------------------
  430. void renderToWindow_0( void )
  431. {
  432.         D3DXMATRIX matView;
  433.         D3DXMATRIX matWorld;
  434.         D3DXMATRIX matRotation;
  435.         D3DXMATRIX matTranslation;
  436.  
  437.         // Tell the Direct3D device to render to the first swap chain’s back buffer
  438.         LPDIRECT3DSURFACE9 pBackBuffer = NULL;
  439.         g_swapChain_0->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
  440.         g_pd3dDevice->SetRenderTarget( 0, pBackBuffer );
  441.  
  442.         // Clear the target buffer to red...
  443.         g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
  444.                                      D3DCOLOR_COLORVALUE( 1.0f, 0.0f, 0.0f, 1.0f ), 1.0f, 0 );
  445.  
  446.         g_pd3dDevice->BeginScene();
  447.         {
  448.                 // For window #0, leave the view at the origin...
  449.                 D3DXMatrixIdentity( &matView );
  450.                 g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  451.  
  452.                 // ... and use the world matrix to spin and translate the teapot  
  453.                 // out where we can see it...
  454.                 D3DXMatrixRotationYawPitchRoll( &matRotation, D3DXToRadian(g_fSpinX), D3DXToRadian(g_fSpinY), 0.0f );
  455.                 D3DXMatrixTranslation( &matTranslation, 0.0f, 0.0f, 4.0f );
  456.                 matWorld = matRotation * matTranslation;
  457.                 g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  458.  
  459.                 g_pd3dDevice->SetMaterial( &g_teapotMtrl );
  460.                 g_pTeapotMesh->DrawSubset(0);
  461.         }
  462.         g_pd3dDevice->EndScene();
  463.  
  464.    
  465.      //Report frames per second and the number of objects culled...
  466.    
  467.  
  468.     static int nFrameCount = 0;
  469.     ++nFrameCount;
  470.  
  471.     static double nTimeOfLastFPSUpdate = 0.0;
  472.     static char fpsString[50] = "Frames Per Second = ";
  473.  
  474.     if( g_dElpasedAppTime - nTimeOfLastFPSUpdate > 1000 ) // Update once a second
  475.     {
  476.         sprintf( fpsString, "Frames Per Second = %4.2f",
  477.             nFrameCount*1000.0/(g_dElpasedAppTime - nTimeOfLastFPSUpdate) );
  478.  
  479.         nTimeOfLastFPSUpdate = g_dElpasedAppTime;
  480.         nFrameCount = 0;
  481.     }
  482.  
  483.     RECT destRect;
  484.     SetRect( &destRect, 5, 5, 0, 0 );
  485.  
  486.     g_pd3dxFont->DrawText( NULL, fpsString, -1, &destRect, DT_NOCLIP,
  487.                            D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
  488.  
  489.          //Present swap chain #0 to window #0
  490.         g_swapChain_0->Present( NULL, NULL, g_hWnd_0, NULL, 0 );
  491.  
  492.         pBackBuffer->Release();
  493. }
  494.  
  495.  
  496. void renderWindow(HWND hwnd, LPDIRECT3DSWAPCHAIN9 swapchain)
  497. {
  498.         D3DXMATRIX matView;
  499.         D3DXMATRIX matWorld;
  500.         D3DXMATRIX matRotation;
  501.         D3DXMATRIX matTranslation;
  502.  
  503.         // Tell the Direct3D device to render to the second swap chain’s back buffer
  504.         LPDIRECT3DSURFACE9 pBackBuffer = NULL;
  505.         swapchain->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
  506.         g_pd3dDevice->SetRenderTarget( 0, pBackBuffer );
  507.  
  508.         // Clear the target buffer to green...
  509.         g_pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
  510.                                      D3DCOLOR_COLORVALUE( 0.0f, 1.0f, 0.0f, 1.0f ), 1.0f, 0 );
  511.  
  512.         g_pd3dDevice->BeginScene();
  513.         {
  514.                 D3DXMatrixRotationYawPitchRoll( &matRotation, D3DXToRadian(g_fSpinX), D3DXToRadian(g_fSpinY), 0.0f );
  515.                 D3DXMatrixTranslation( &matTranslation, 0.0f, 0.0f, 4.0f );
  516.                 matView = matRotation * matTranslation;
  517.                 g_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );
  518.  
  519.                 // ... and don't bother with the world matrix at all.
  520.                 D3DXMatrixIdentity( &matWorld );
  521.                 g_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  522.  
  523.                 g_pd3dDevice->SetMaterial( &g_teapotMtrl );
  524.                 g_pTeapotMesh->DrawSubset(0);
  525.         }
  526.         g_pd3dDevice->EndScene();
  527.  
  528.         swapchain->Present( NULL, NULL, hwnd, NULL, 0 );
  529.  
  530.         pBackBuffer->Release();
  531. }