C++ 如何在C中使用DirectX 9渲染多个窗口?

C++ 如何在C中使用DirectX 9渲染多个窗口?,c++,window,directx-9,C++,Window,Directx 9,我已经问了这个问题,但还没有得到答复 我尝试使用DirectX 9和交换链渲染多个窗口,但即使我创建了两个窗口,我也只能看到我创建的第一个窗口。我的RenderDX9标题如下: #include <d3d9.h> #include <Windows.h> #include <vector> #include "RAT_Renderer.h" namespace RAT_ENGINE { class RAT_RendererDX9 : public

我已经问了这个问题,但还没有得到答复

我尝试使用DirectX 9和交换链渲染多个窗口,但即使我创建了两个窗口,我也只能看到我创建的第一个窗口。我的RenderDX9标题如下:

#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);
    };
}
如何让多个窗口工作?

与为多个屏幕创建多个设备相比,您用于呈现多个窗口的“交换链”方法听起来不错

您是否查看了使用交换链渲染多个窗口的codesampler教程。如果没有,请找到下面的链接,其中有一个使用交换链渲染多个窗口的工作示例项目。这段代码纯粹是特定于windows Directx 9的,但您可以添加包装器以实现平台无关性

  • 创建多个设备

  • 使用交换链


  • 谷歌的第一个结果:,它是DX8,但DX9非常有趣。该链接显示的代码与我基于代码编写的代码非常相似,但那里的窗口(它们也是分开的)有一个HWND句柄。由于我希望使引擎尽可能与平台无关,因此我决定将HWND窗口放在渲染器中,并根据RAT_窗口输入重新创建它们。我认为我对渲染器进行了充分的调整,使其能够工作,但事实显然并非如此。我想知道的是为什么它不工作,以及我如何修复它,而不必在我的RAT_Window类中放入DX9/Windows特定代码。请定义“平台中立”。我很困惑。一旦我优化了DirectX 9的引擎,我想添加一个OpenGL渲染器,这样引擎也可以在Linux和MacOS上使用。我记不起正确的术语了,但我想在我的引擎中尽可能多的类独立于平台。这就是所谓的:)但是如果你想写DX代码和OpenGL代码,你可能需要为每个类分别写两段代码,在最后一个阶段,您只需制作一个主程序,处理opengl和directx之间的差异。此外,您还需要调整代码(通过创建单独的代码库或#如果定义了等),使其在其他系统上真正工作/编译。
    #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();
    }