2013-03-05 163 views
3

我已經在https://gamedev.stackexchange.com/questions/50374/how-can-i-render-multiple-windows-with-directx-9-in-c提問了這個問題,但我還沒有收到答案。如何在C中使用DirectX 9渲染多個窗口?

我試圖渲染多個窗口,使用DirectX 9和交換鏈,但即使我創建了2個窗口,我只能看到我創建的第一個窗口。我RendererDX9標題是這樣的:

#include <d3d9.h> 
#include <Windows.h> 
#include <vector> 

#include "RAT_Renderer.h" 

namespace RAT_ENGINE 
{ 
    class RAT_RendererDX9 : public RAT_Renderer 
    { 
    public: 
     RAT_RendererDX9(); 
     ~RAT_RendererDX9(); 

     void Init(RAT_WindowManager* argWMan); 
     void CleanUp(); 

     void ShowWin(); 


    private: 
     LPDIRECT3D9   renderInterface; // Used to create the D3DDevice 
     LPDIRECT3DDEVICE9  renderDevice; // Our rendering device 
     LPDIRECT3DSWAPCHAIN9* swapChain;  // Swapchain to make multi-window rendering possible 
     WNDCLASSEX wc; 

     std::vector<HWND> hwindows; 

     void Render(int argI); 
    }; 
} 

我的.cpp文件是這樣的:

#include "RAT_RendererDX9.h" 


static LRESULT CALLBACK MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 


namespace RAT_ENGINE 
{ 
    RAT_RendererDX9::RAT_RendererDX9() : renderInterface(NULL), renderDevice(NULL) 
    { 
    } 

    RAT_RendererDX9::~RAT_RendererDX9() 
    { 
    } 

    void RAT_RendererDX9::Init(RAT_WindowManager* argWMan) 
    { 
     wMan = argWMan; 
     // Register the window class 
     WNDCLASSEX windowClass = 
     { 
      sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0, 0, 
      GetModuleHandle(NULL), NULL, NULL, NULL, NULL, 
      "foo", NULL 
     }; 

     wc = windowClass; 

     RegisterClassEx(&wc); 

     for (int i = 0; i< wMan->getWindows().size(); ++i) 
     { 
      HWND hWnd = CreateWindow("foo", argWMan->getWindow(i)->getName().c_str(), 
            WS_OVERLAPPEDWINDOW, argWMan->getWindow(i)->getX(), argWMan->getWindow(i)->getY(), 
            argWMan->getWindow(i)->getWidth(), argWMan->getWindow(i)->getHeight(), 
            NULL, NULL, wc.hInstance, NULL); 
      hwindows.push_back(hWnd); 
     } 

     // Create the D3D object, which is needed to create the D3DDevice. 
     renderInterface = (LPDIRECT3D9)Direct3DCreate9(D3D_SDK_VERSION); 

     // Set up the structure used to create the D3DDevice. Most parameters are 
     // zeroed out. We set Windowed to TRUE, since we want to do D3D in a 
     // window, and then set the SwapEffect to "discard", which is the most 
     // efficient method of presenting the back buffer to the display. And 
     // we request a back buffer format that matches the current desktop display 
     // format. 
     D3DPRESENT_PARAMETERS deviceConfig; 
     ZeroMemory(&deviceConfig, sizeof(deviceConfig)); 
     deviceConfig.Windowed = TRUE; 
     deviceConfig.SwapEffect = D3DSWAPEFFECT_DISCARD; 
     deviceConfig.BackBufferFormat = D3DFMT_UNKNOWN; 
     deviceConfig.BackBufferHeight = 1024; 
     deviceConfig.BackBufferWidth = 768; 
     deviceConfig.EnableAutoDepthStencil = TRUE; 
     deviceConfig.AutoDepthStencilFormat = D3DFMT_D16; 

     // Create the Direct3D device. Here we are using the default adapter (most 
     // systems only have one, unless they have multiple graphics hardware cards 
     // installed) and requesting the HAL (which is saying we want the hardware 
     // device rather than a software one). Software vertex processing is 
     // specified since we know it will work on all cards. On cards that support 
     // hardware vertex processing, though, we would see a big performance gain 
     // by specifying hardware vertex processing. 
     renderInterface->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwindows[0], 
           D3DCREATE_SOFTWARE_VERTEXPROCESSING, 
           &deviceConfig, &renderDevice); 

     this->swapChain = new LPDIRECT3DSWAPCHAIN9[wMan->getWindows().size()]; 
     this->renderDevice->GetSwapChain(0, &swapChain[0]); 

     for (int i = 0; i < wMan->getWindows().size(); ++i) 
     { 
      renderDevice->CreateAdditionalSwapChain(&deviceConfig, &swapChain[i]); 
     } 

     renderDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); // Set cullmode to counterclockwise culling to save resources 
     renderDevice->SetRenderState(D3DRS_AMBIENT, 0xffffffff); // Turn on ambient lighting 
     renderDevice->SetRenderState(D3DRS_ZENABLE, TRUE);   // Turn on the zbuffer 
    } 

    void RAT_RendererDX9::CleanUp() 
    { 
     renderDevice->Release(); 
     renderInterface->Release(); 
    } 

    void RAT_RendererDX9::Render(int argI) 
    { 
     // Clear the backbuffer to a blue color 
     renderDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0); 
     LPDIRECT3DSURFACE9 backBuffer = NULL; 

     // Set draw target 
     this->swapChain[argI]->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &backBuffer); 
     this->renderDevice->SetRenderTarget(0, backBuffer); 

     // Begin the scene 
     renderDevice->BeginScene(); 

     // End the scene 
     renderDevice->EndScene(); 
     swapChain[argI]->Present(NULL, NULL, hwindows[argI], NULL, 0); 
    } 

    void RAT_RendererDX9::ShowWin() 
    { 
     for (int i = 0; i < wMan->getWindows().size(); ++i) 
     { 
      ShowWindow(hwindows[i], SW_SHOWDEFAULT); 
      UpdateWindow(hwindows[i]); 

      // Enter the message loop 
      MSG msg; 
      while(GetMessage(&msg, NULL, 0, 0)) 

      { 
       if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE)) 
       { 
       TranslateMessage(&msg); 
       DispatchMessage(&msg); 
       } 
       else 
       { 
        Render(i); 
       } 
      } 
     } 
    } 
} 

LRESULT CALLBACK MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    switch(msg) 
    { 
     case WM_DESTROY: 
      //CleanUp(); 
      PostQuitMessage(0); 
      return 0; 

     case WM_PAINT: 
      //Render(); 
      ValidateRect(hWnd, NULL); 
      return 0; 
    } 

    return DefWindowProc(hWnd, msg, wParam, lParam); 
} 

我做了一個樣本功能,使多個窗口:

void RunSample1() 
{ 
    //Create the window manager. 
    RAT_ENGINE::RAT_WindowManager* wMan = new RAT_ENGINE::RAT_WindowManager(); 

    //Create the render manager. 
    RAT_ENGINE::RAT_RenderManager* rMan = new RAT_ENGINE::RAT_RenderManager(); 

    //Create a window. 
    //This is currently needed to initialize the render manager and create a renderer. 
    wMan->CreateRATWindow("Sample 1 - 1", 10, 20, 640, 480); 
    wMan->CreateRATWindow("Sample 1 - 2", 150, 100, 480, 640); 

    //Initialize the render manager. 
    rMan->Init(wMan); 

    //Show the window. 
    rMan->getRenderer()->ShowWin(); 
} 

我如何讓多個窗口工作?

+0

第一個結果在谷歌:http://www.mvps.org/directx/articles/rendering_to_multiple_windows。 htm,這是DX8,但DX9非常好。 – 2013-03-05 08:34:22

+0

該鏈接顯示的代碼看起來與我的代碼基本相似,但是窗口(它們也是單獨的)有一個HWND句柄。由於我想讓引擎儘可能平臺中立,因此我決定將HWND窗口放在渲染器中,並根據我的RAT_Window輸入重新創建它們。我認爲我已經適應了渲染器,足以讓它工作,但顯然並非如此。 我想知道的是爲什麼它不起作用,以及如何解決這個問題,而不必將DX9/Windows特定代碼放入我的RAT_Window類中。 – Friso 2013-03-06 00:52:03

+0

請定義「平臺中性」。我很困惑。 – 2013-03-06 06:33:48

回答

4

與爲多個屏幕創建多個設備相比,用於渲染多個窗口的「交換鏈」方法聽起來不錯。

你檢查過codesampler教程使用交換鏈渲染多個窗口。如果沒有,請找到下面的鏈接,其中有一個工作示例項目,用於使用交換鏈呈現多個窗口。此代碼純粹是針對Windows DirectX 9的,但您可以添加包裝以實現平臺無關。

  1. 創建多個設備

  2. 使用交換鏈

http://www.codesampler.com/dx9src/dx9src_1.htm