4

我已经在https://gamedev.stackexchange.com/questions/50374/how-can-i-render-multiple-windows-with-directx-9-in-c提出了这个问题,但我还没有收到回答。

我正在尝试使用 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();
}

如何让多个窗口工作?

4

1 回答 1

5

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

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

  1. 创建多个设备

  2. 使用交换链

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

于 2013-04-12T14:29:58.757 回答