在D3D上正确调整D2D的大小

时间:2013-10-02 09:19:00

标签: c++ directx directwrite

我在D3D11上调整D2D渲染目标的大小时遇到​​问题。我使函数调整交换链缓冲区的大小。 它工作得很好,但是当我激活D2D时,调整大小就会被破坏。

当我缩小窗口时,所有网格都会从窗口中消失 - 仅显示文本。 当我制作更大的 - 渲染的网格,但比例不正确,尽管我重新创建投影矩阵。

我的问题是 - 如何在窗口大小改变后正确调整D2D渲染目标和文本的大小?

这是我创建D3D11Device,swapchain1和D2D的代码。

bool D3D11::InitializeD3D11(HWND hwnd, SettingsContainer* settingsContainer)
{
this->hwnd = hwnd;
HRESULT result;
IDXGIFactory2* factory;
IDXGIAdapter* adapter;
IDXGIOutput* adapterOutput;
D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_UNKNOWN;
unsigned int numModes, numerator, denominator;
DXGI_MODE_DESC* displayModeList;
DXGI_ADAPTER_DESC adapterDesc;
DXGI_OUTPUT_DESC displayDesc;
DXGI_SWAP_CHAIN_DESC1 swapChainDescription;
D3D_FEATURE_LEVEL featureLevel;
ID3D11Texture2D* backBufferPtr;
D3D11_TEXTURE2D_DESC depthBufferDescription;
D3D11_DEPTH_STENCIL_DESC depthStencilDescription;
D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDescription;
D3D11_RASTERIZER_DESC rasterizerDescription;
D3D11_VIEWPORT viewPort;
D3D11_DEPTH_STENCIL_DESC depthStencilDescriptionDisabled;
D3D11_BLEND_DESC blendStateDescrition;
AdapterInfo* adapterInfo;
DisplayInfo* displayInfo;

adapterInfo = NULL;

//Создаём фабрику графических интерфейсов DX
result = CreateDXGIFactory1(__uuidof(IDXGIFactory2), (void**)&factory);
if (FAILED(result))
{
    return false;
}

/*IDXGIDevice2 * pDXGIDevice;
result = d3d11_Device->QueryInterface(__uuidof(IDXGIDevice2), (void **)&pDXGIDevice);*/

/*IDXGIAdapter * pDXGIAdapter;
result = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void **)&pDXGIAdapter);*/

/*IDXGIFactory2 * pIDXGIFactory;
pDXGIAdapter->GetParent(__uuidof(IDXGIFactory2), (void **)&pIDXGIFactory);*/

//pIDXGIFactory->EnumAdapters1(0,&adapter);

//adapter->EnumOutputs(0, &adapterOutput);

//Достаём все графические адаптеры
for (UINT i = 0; factory->EnumAdapters(i,&adapter)!= DXGI_ERROR_NOT_FOUND;++i)
{
    adapterInfo = new AdapterInfo(adapter);
    adapter->GetDesc(&adapterDesc);
    adapterInfo->Name = adapterDesc.Description;
    adapterInfo->InternalMemory = (float)adapterDesc.DedicatedVideoMemory/1024/1024;

    for (UINT j = 0; adapter->EnumOutputs(j, &adapterOutput) != DXGI_ERROR_NOT_FOUND;++j)
    {
        displayInfo = new DisplayInfo;
        adapterOutput->GetDesc(&displayDesc);
        displayInfo->MonitorHWND = displayDesc.Monitor;
        DWORD cPhysicalMonitors;
        LPPHYSICAL_MONITOR pPhysicalMonitors = NULL;
        BOOL bSuccess = GetNumberOfPhysicalMonitorsFromHMONITOR(displayInfo->MonitorHWND, &cPhysicalMonitors);
        ZeroMemory(&pPhysicalMonitors, sizeof(pPhysicalMonitors));
        pPhysicalMonitors = (LPPHYSICAL_MONITOR)malloc(
            cPhysicalMonitors* sizeof(PHYSICAL_MONITOR));
        GetPhysicalMonitorsFromHMONITOR(displayInfo->MonitorHWND, cPhysicalMonitors, pPhysicalMonitors);

        displayInfo->Name = pPhysicalMonitors->szPhysicalMonitorDescription;

        //Получаем количество режимов которые удовлетворяют формату монитора DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM
        adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, NULL ); 


        displayModeList = new DXGI_MODE_DESC[numModes];
        if (!displayModeList)
        {
            return false;
        }

        //Заполняем структуру display mode list
        result = adapterOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, displayModeList);

        //Проходимся по всем режимам дисплея и находим тот, который совпадает с высотой и шириной экрана
        //Когда совпадение найдено сохраняем нумератор и деноминатор частоты обновления для монитора
        std::ofstream input_file("file.txt");


        for(int k=0; k<numModes; k++)
        {
            if (input_file.is_open())
            {
                input_file << displayModeList[k].Width<<" "<<displayModeList[k].Height<<" "<<displayModeList[k].RefreshRate.Numerator<<" "<<displayModeList[k].RefreshRate.Denominator
                    <<" "<<displayModeList[k].ScanlineOrdering<<" "<<displayModeList[k].Format<<" "<<displayModeList[k].Scaling<<std::endl;
            }


            if (displayModeList[k].Width >= 1024)
            {
                if ((displayModeList[k].RefreshRate.Numerator/displayModeList[k].RefreshRate.Denominator)>59)
                {
                    if (displayModeList[k].Scaling == DXGI_MODE_SCALING_CENTERED)
                    {
                        DisplayMode displayMode;
                        displayMode.Width = displayModeList[k].Width;
                        displayMode.Height = displayModeList[k].Height;
                        displayMode.Numerator = displayModeList[k].RefreshRate.Numerator;
                        displayMode.Denominator = displayModeList[k].RefreshRate.Denominator;

                        displayInfo->DisplayModes.push_back(displayMode);


                        /*numerator = displayModeList[k].RefreshRate.Numerator;
                        denominator = displayModeList[k].RefreshRate.Denominator;*/
                    }
                }
            }
        }

        //Удаляем display mode list
        delete[] displayModeList;
        displayModeList = NULL;

        adapterInfo->displayList.push_back(displayInfo);
        input_file.close ();

    }
    //добавляем в вектор всю собранную информацию по видеокарте
    adapterList.push_back(adapterInfo);
}



//Удаляем адаптер и адаптер output
//adapter->Release();
adapter = 0;
//adapterOutput->Release();
adapterOutput = 0;

//Удаляем фабрику
/*factory->Release();
factory = 0;*/

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

UINT numFeatureLevels = ARRAYSIZE(featureLevels);
factory->EnumAdapters(0,&adapter);
//Создаём устройство Direct3D и контекст устройства Direct3D
/*result = D3D11CreateDevice(NULL, driverType,NULL,D3D11_CREATE_DEVICE_DEBUG|D3D11_CREATE_DEVICE_BGRA_SUPPORT, featureLevels,numFeatureLevels,
        D3D11_SDK_VERSION, &d3d11_Device, &featureLevel, &d3d11_DeviceContext );*/

result = D3D11CreateDevice(adapterList[0]->adapter, driverType, NULL, D3D11_CREATE_DEVICE_DEBUG|D3D11_CREATE_DEVICE_BGRA_SUPPORT, featureLevels,numFeatureLevels,
    D3D11_SDK_VERSION, &d3d11_Device, &featureLevel, &d3d11_DeviceContext );

if (FAILED(result))
{
    return false;
}
UINT qualityLevels;
d3d11_Device->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 4, &qualityLevels);

//Инициализируем структуру swap chain description
ZeroMemory(&swapChainDescription, sizeof(swapChainDescription));


//Устанавливаем количество буферов
swapChainDescription.BufferCount = 1;

//устанавливаем ширину и высоту заднего буфера
swapChainDescription.Width = settingsContainer->renderSettingsDX11->GetScreenWidth();
swapChainDescription.Height = settingsContainer->renderSettingsDX11->GetScreenHeight();

//устанавливаем формат пикселей
swapChainDescription.Format = DXGI_FORMAT_R8G8B8A8_UNORM;

swapChainDescription.SampleDesc.Count = 1;
swapChainDescription.SampleDesc.Quality = 0;

//Устанавливаем использование заднего буфера
swapChainDescription.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDescription.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapChainDescription.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;

DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen;
fullscreen.RefreshRate.Numerator = 0;
fullscreen.RefreshRate.Denominator = 1;
fullscreen.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
fullscreen.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE;
//Устанавливаем в полноэкранный режим и оконный
if (settingsContainer->renderSettingsDX11->IsFullScreenEnabled())
{
    fullscreen.Windowed = FALSE;
}
else
{
    fullscreen.Windowed = TRUE;
}



//Создаём swap chain
result = factory->CreateSwapChainForHwnd(d3d11_Device, hwnd, &swapChainDescription, &fullscreen, NULL, &swapChain);
if(FAILED(result))
    return false;

//Получаем указатель на задний буфер
result = swapChain->GetBuffer(0,__uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr);
if (FAILED(result))
    return false;


//Создаём render target view с указателем на задний буфер
result = d3d11_Device->CreateRenderTargetView(backBufferPtr, NULL, &d3d11_RenderTargetView);
if(FAILED(result))
    return false;

//Освобождаем указатель на задний буфер, так как он больше не нужен
backBufferPtr->Release();
backBufferPtr = 0;

//Инициализируем описание структуры Depth_Buffer
ZeroMemory(&depthBufferDescription, sizeof(depthBufferDescription));

//Заполняем описание структуры
depthBufferDescription.Width = settingsContainer->renderSettingsDX11->GetScreenWidth();
depthBufferDescription.Height = settingsContainer->renderSettingsDX11->GetScreenHeight();
depthBufferDescription.MipLevels = 1;
depthBufferDescription.ArraySize = 1;
depthBufferDescription.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthBufferDescription.SampleDesc.Count = 1;
depthBufferDescription.SampleDesc.Quality = 0;
depthBufferDescription.Usage = D3D11_USAGE_DEFAULT;
depthBufferDescription.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthBufferDescription.CPUAccessFlags = 0;
depthBufferDescription.MiscFlags = 0;

//Создаём текстуру для буфера глубины используя заполненную структуру
result = d3d11_Device->CreateTexture2D(&depthBufferDescription, NULL, &d3d11_DepthStencilBuffer);
if (FAILED(result))
    return false;

//Инициализируем описание stencil state
ZeroMemory(&depthStencilDescription, sizeof(depthStencilDescription));

//Вводим описание структуры stencil_state
depthStencilDescription.DepthEnable = true;
depthStencilDescription.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
depthStencilDescription.DepthFunc = D3D11_COMPARISON_LESS;

depthStencilDescription.StencilEnable = true;
depthStencilDescription.StencilReadMask = 0xFF;
depthStencilDescription.StencilWriteMask = 0xFF;

//Шаблонные операции если пиксель впереди
depthStencilDescription.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDescription.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_INCR;
depthStencilDescription.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDescription.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

//Швблонные операции, если пиксель на обратной стороне
depthStencilDescription.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
depthStencilDescription.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_DECR;
depthStencilDescription.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP;
depthStencilDescription.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;

//Создаём Depth_Stencil_State
result = d3d11_Device->CreateDepthStencilState(&depthStencilDescription, &d3d11_DepthStencilState);
if (FAILED(result))
{
    return false;
}
//Задаём состояние Depth Stencil State
d3d11_DeviceContext->OMSetDepthStencilState(d3d11_DepthStencilState,1);

//Инициализируем структуру Depth Stencil View
ZeroMemory (&depthStencilViewDescription, sizeof(depthStencilViewDescription));

//Заполняем описание структуры Depth_Stencil_View
depthStencilViewDescription.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilViewDescription.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depthStencilViewDescription.Texture2D.MipSlice = 0;

//Задаём описание структуры Depth_Stencil_View
result = d3d11_Device->CreateDepthStencilView(d3d11_DepthStencilBuffer, &depthStencilViewDescription, &d3d11_DepthStencilView);
if (FAILED(result))
    return false;

//Привязываем render target view и depth stencil buffer к output pipeline
d3d11_DeviceContext->OMSetRenderTargets(1, &d3d11_RenderTargetView, d3d11_DepthStencilView);

//Заполняем структуру Raster_Description, которая будет определять как и какие полигоны будут нарисованы
rasterizerDescription.AntialiasedLineEnable = false;
rasterizerDescription.CullMode = D3D11_CULL_BACK;
rasterizerDescription.DepthBias = 0;
rasterizerDescription.DepthBiasClamp = 0.0f;
rasterizerDescription.DepthClipEnable = true;
rasterizerDescription.FillMode = D3D11_FILL_SOLID;
rasterizerDescription.FrontCounterClockwise = false;
rasterizerDescription.MultisampleEnable = true;
rasterizerDescription.ScissorEnable = false;
rasterizerDescription.SlopeScaledDepthBias = 0.0f;

//Создаём rasterizerState из описания, которое только что заполнили
result = d3d11_Device->CreateRasterizerState(&rasterizerDescription, &d3d11_RasterizerState);
if(FAILED(result))
{
    return false;
}


//Устанавливаем rasterizer state (можно менять состояние с D3D11_FILL_SOLID на D3D11_FILL_WIREFRAME)
d3d11_DeviceContext->RSSetState(d3d11_RasterizerState);

//Устанавливаем вьюпорт для рендеринга
viewPort.Width = (float)settingsContainer->renderSettingsDX11->GetScreenWidth();
viewPort.Height = (float)settingsContainer->renderSettingsDX11->GetScreenHeight();
viewPort.MinDepth = 0.0f;
viewPort.MaxDepth = 1.0f;
viewPort.TopLeftX = 0.0f;
viewPort.TopLeftY = 0.0f;

//Создаём ViewPort
d3d11_DeviceContext->RSSetViewports(1,&viewPort);


return true;
}

void D3D11::ResizeSwapChain()
{
HRESULT result;
if (swapChain)
{
    RECT rc;
    GetClientRect(hwnd, &rc);
    UINT width = rc.right - rc.left;
    UINT height = rc.bottom - rc.top;

d3d11_DeviceContext->OMSetRenderTargets(0,0,0);
d3d11_RenderTargetView->Release();

swapChain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0);
swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr);
d3d11_Device->CreateRenderTargetView(backBufferPtr, NULL, &d3d11_RenderTargetView);


//Инициализируем описание структуры Depth_Buffer
ZeroMemory(&depthBufferDescription, sizeof(depthBufferDescription));

//Заполняем описание структуры
depthBufferDescription.Width = width;
depthBufferDescription.Height = height;
depthBufferDescription.MipLevels = 1;
depthBufferDescription.ArraySize = 1;
depthBufferDescription.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthBufferDescription.SampleDesc.Count = 1;
depthBufferDescription.SampleDesc.Quality = 0;
depthBufferDescription.Usage = D3D11_USAGE_DEFAULT;
depthBufferDescription.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthBufferDescription.CPUAccessFlags = 0;
depthBufferDescription.MiscFlags = 0;

d3d11_DepthStencilBuffer->Release();
d3d11_DepthStencilBuffer = NULL;

//Создаём текстуру для буфера глубины используя заполненную структуру
result = d3d11_Device->CreateTexture2D(&depthBufferDescription, NULL,     &d3d11_DepthStencilBuffer);


bool D3D11::InitializeD2D11()
{
options.debugLevel = D2D1_DEBUG_LEVEL_ERROR;
D2D1CreateFactory(D2D1_FACTORY_TYPE_MULTI_THREADED, options, &d2dfactory);

swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackbuffer));
D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
    D2D1_RENDER_TARGET_TYPE_HARDWARE,
    D2D1::PixelFormat(DXGI_FORMAT_UNKNOWN, D2D1_ALPHA_MODE_PREMULTIPLIED));
d2dfactory->CreateDxgiSurfaceRenderTarget(dxgiBackbuffer, props, &d2dRenderTarget);

dxgiBackbuffer->Release();
dxgiBackbuffer = NULL;
d2dfactory->Release();
d2dfactory = NULL;

DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(DWriteFactory), (IUnknown**)(&DWriteFactory));

DWriteFactory->CreateTextFormat(
    L"Cambria",
    NULL,
    DWRITE_FONT_WEIGHT_NORMAL,
    DWRITE_FONT_STYLE_NORMAL,
    DWRITE_FONT_STRETCH_NORMAL,
    12,
    L"",
    &textFormat);

DWriteFactory->CreateTextFormat(
    L"Cambria",
    NULL,
    DWRITE_FONT_WEIGHT_NORMAL,
    DWRITE_FONT_STYLE_NORMAL,
    DWRITE_FONT_STRETCH_NORMAL,
    12,
    L"",
    &textFormat2);


textFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_NEAR);
textFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
textFormat2->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_FAR);
textFormat2->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_LEADING);
d2dRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), &Brush);

return true;
}
//Задаём состояние Depth Stencil State
d3d11_DeviceContext->OMSetDepthStencilState(d3d11_DepthStencilState, 1);

//Инициализируем структуру Depth Stencil View
ZeroMemory (&depthStencilViewDescription, sizeof(depthStencilViewDescription));

//Заполняем описание структуры Depth_Stencil_View
depthStencilViewDescription.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilViewDescription.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
depthStencilViewDescription.Texture2D.MipSlice = 0;

d3d11_DepthStencilView->Release();
d3d11_DepthStencilView = NULL;

//Задаём описание структуры Depth_Stencil_View
result = d3d11_Device->CreateDepthStencilView(d3d11_DepthStencilBuffer, &depthStencilViewDescription, &d3d11_DepthStencilView);

//Освобождаем указатель на задний буфер, так как он больше не нужен
backBufferPtr->Release();
backBufferPtr = 0;

d3d11_DeviceContext->OMSetRenderTargets(1, &d3d11_RenderTargetView, d3d11_DepthStencilView);

//d3d11_DeviceContext->OMSetRenderTargets(1, &d3d11_RenderTargetView, NULL);

//Устанавливаем вьюпорт для рендеринга
D3D11_VIEWPORT viewPort;

viewPort.Width = (float)width;
viewPort.Height = (float)height;
viewPort.MinDepth = 0.0f;
viewPort.MaxDepth = 1.0f;
viewPort.TopLeftX = 0.0f;
viewPort.TopLeftY = 0.0f;

//Создаём ViewPort
d3d11_DeviceContext->RSSetViewports(1,&viewPort);

}
}

我在WM_SIZE事件上调整缓冲区:

    case WM_SIZE:
    {
        int Width = LOWORD(lparam);
        int Height = HIWORD(lparam);
        WCHAR* str = NULL;
        if (wparam == SIZE_RESTORED)
        {
            if (system->application)
            {
                system->application->d3d11->ResizeSwapChain();
                system->application->d3d11->ResizeD2DBuffer();
                system->application->cameraDX_Free->perspective(system->application->cameraDX_Free->m_fovx,
                    static_cast<float>(Width) / static_cast<float>(Height),
                    system->application->cameraDX_Free->m_znear,
                    system->application->cameraDX_Free->m_zfar);
            }

        }
    }   

1 个答案:

答案 0 :(得分:0)

要在我的情况下正确调整D2D大小,首先需要删除所有d2d资源,并在调整交换链大小后重新创建所有资源。