2013-03-05 164 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