Advertisement
Guest User

DirectX9 Multi-window test

a guest
Nov 3rd, 2012
1,027
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.37 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement