【问题标题】:DirectX11 swapchain texture rendering issue when windowed?窗口化时出现 DirectX11 交换链纹理渲染问题?
【发布时间】:2014-01-31 08:25:20
【问题描述】:

我正在编写一个基于 DirectX11 的游戏框架,但我遇到了一个问题,我的纹理在屏幕上显示不好,这是一个屏幕截图:

如您所见,图像并不完美,但我注意到只有当我将交换链初始化为窗口时才会发生这种情况,如果我没有将其初始化为全屏,则精灵会正确显示,即使在运行时我从全屏切换到窗口它仍然正确显示,这是屏幕上显示的图像:

这是我的交换链的初始化:

RECT dimensions;
GetClientRect(game->Window, &dimensions);

unsigned int width = dimensions.right - dimensions.left;
unsigned int height = dimensions.bottom - dimensions.top;

D3D_DRIVER_TYPE driverTypes[] =
{
    D3D_DRIVER_TYPE_HARDWARE,
    D3D_DRIVER_TYPE_WARP,
    D3D_DRIVER_TYPE_REFERENCE,
    D3D_DRIVER_TYPE_SOFTWARE
};

unsigned int totalDriverTypes = ARRAYSIZE(driverTypes);

D3D_FEATURE_LEVEL featureLevels[] =
{
    D3D_FEATURE_LEVEL_11_0,
    D3D_FEATURE_LEVEL_10_1,
    D3D_FEATURE_LEVEL_10_0
};

unsigned int totalFeatureLevels = ARRAYSIZE(featureLevels);

DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
swapChainDesc.BufferCount = DXGI_SWAP_EFFECT_SEQUENTIAL;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = game->Window;
swapChainDesc.Windowed = true;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;

unsigned int creationFlags = 0;

#ifdef _DEBUG
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

HRESULT result;
unsigned int driver = 0;

pin_ptr<IDXGISwapChain*> swapChainPointer;
swapChainPointer = &swapChain_;

pin_ptr<ID3D11Device*> d3dDevicePointer;
d3dDevicePointer = &d3dDevice_;

pin_ptr<D3D_FEATURE_LEVEL> featureLevelPointer;
featureLevelPointer = &featureLevel_;

pin_ptr<ID3D11DeviceContext*> d3dContextPointer;
d3dContextPointer = &d3dContext_;

for (driver = 0; driver < totalDriverTypes; ++driver)
{
    result = D3D11CreateDeviceAndSwapChain(0, driverTypes[driver], 0, creationFlags, featureLevels, totalFeatureLevels,
        D3D11_SDK_VERSION, &swapChainDesc, swapChainPointer,
        d3dDevicePointer, featureLevelPointer, d3dContextPointer);

    if (SUCCEEDED(result))
    {
        driverType_ = driverTypes[driver];
        break;
    }
}

这是切换全屏的代码:

swapChain_->SetFullscreenState(isFullScreen, NULL);

其中 IsFullScreen 是传递给 containsig 函数的布尔值。

谁能帮帮我?提前致谢!

编辑:

已解决:

我在创建窗口时更改了 WS_OVERLAPPED 参数:

RECT rc = { 0, 0, WindowWidth, WindowHeight };
AdjustWindowRect(&rc, WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU, FALSE);

LPCTSTR title = Utilities::StringToLPCSTR(Title);

HWND hwnd = CreateWindowA("BSGame", title, WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, windowHandler, NULL);

到 WS_OVERLAPPEDWINDOW

【问题讨论】:

  • 调用 set full screen 时是否调整交换链的大小、释放视图、重置视口?
  • 不,这是函数;内联 void GraphicsDevice::FullScreen(bool isFullScreen) { swapChain_->SetFullscreenState(isFullScreen, NULL); }

标签: c++-cli textures directx-11 windowed


【解决方案1】:

当您在 SwapChain 上调用 SetFullScreen 时,您只请求更改模式。

通常在调用之后,您应该会从主窗体中收到一条 WM_SIZE 消息,然后您需要执行以下操作:

释放绑定到交换链的任何相关资源(例如:Texture 和 RenderTargetView) 确保您还在设备上下文中调用 ClearState,因为如果您 SwapChain 仍绑定到管道,您也会遇到问题(如果资源绑定到管道,运行时不会破坏资源)。

接下来你在交换链上调用 resize,比如:

 HRESULT result = mSwapChain->ResizeBuffers(0,0,0,DXGI_FORMAT_UNKNOWN,0);

终于可以再次查询纹理了:

ID3D11Texture2D* texture;
mSwapChain->GetBuffer(0,__uuidof(ID3D11Texture2D),(void**)(&texture));
//Get Buffer does an AddRef on top so we release
texture->Release();

并创建一个新的 RenderTargetView,并将您的 ViewPort 更新为新大小(从纹理中获取描述)。

【讨论】:

  • 我已经按照你的说法更新了我的代码,但我得到的是相同的,我怎样才能向你展示帖子中的代码??
  • 我想你已经理解相反了,我在调整大小之前就遇到了窗口模式的问题!
【解决方案2】:

在我的情况下,问题出在窗口创建期间,这是我的情况:

RECT rc = { 0, 0, WindowWidth, WindowHeight };
AdjustWindowRect(&rc, WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU, FALSE);

LPCTSTR title = Utilities::StringToLPCSTR(Title);

HWND hwnd = CreateWindowA("BSGame", title, WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU, CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, windowHandler, NULL);

为了解决,我将 WS_OVERLAPPED 更改为 WS_OVERLAPPEDWINDOW

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-16
    相关资源
    最近更新 更多