D3D11: Как нарисовать текст GDI на поверхность GXDI? (Без D2D) - PullRequest
8 голосов
/ 12 мая 2011

Мне нужна помощь с рисованием текста на текстуре с помощью GDI и D3D11.Я пытался использовать D2D / DirectWrite, но он поддерживает только D3D10, а не D3D11, как мне нужно.Все, что я пробовал, провалилось до сих пор ... Теперь я хочу использовать методы GDI для записи в текстуру.Итак, я создал текстуру с такими параметрами:

Usage = D3D11_USAGE_DEFAULT;
Format = DXGI_FORMAT_B8G8R8A8_UNORM;
BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
CPUAccessFlags = 0;
MiscFlags = D3D11_RESOURCE_MISC_GDI_COMPATIBLE

Затем я создал обычный RenderTargetView из этой текстуры, как Microsoft говорит здесь: http://msdn.microsoft.com/en-us/library/ff476203%28v=vs.85%29.aspx

Следующий шаг: Получить интерфейс DXGI:

m_pTexFSText->QueryInterface(__uuidof(IDXGISurface1), (void **)(&m_pDXGISurface));

В функции Render я делаю только это:

m_pDeviceContext->OMSetRenderTargets(1,&m_pTextRenderTarget,NULL);

HDC hDc = NULL;
if(FAILED(m_pDXGISurface->GetDC(TRUE,&hDc)))
    return E_FAIL;

COLORREF bla = SetPixel(hDc,1,1,RGB(255,255,255));
bool hmm = TextOutA(hDc, 10, 10, "LALALA!", 7);

if(FAILED(m_pDXGISurface->ReleaseDC(NULL)))
    return E_FAIL;

Проблема в том, что текстура остается пустой после этого чертежа GDI (также протестировано с PIX).Все работает и сообщений об ошибках нет.

Я надеюсь, что кто-нибудь может объяснить, как это работает.

Спасибо, Стефан

РЕДАКТИРОВАТЬ: Пробовал также с GetDC(FALSE,&hDc) (согласно документации): те же результаты -> ничего.

Ответы [ 3 ]

5 голосов
/ 10 января 2012

Я на самом деле много боролся с этой проблемой на прошлой неделе - но у меня все работает! Вот список вещей, которые вы должны знать / делать, чтобы все это работало:

При использовании этого метода учитывайте следующее:

• Необходимо создать поверхность с помощью флага D3D11_RESOURCE_MISC_GDI_COMPATIBLE для поверхности или с помощью флага DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE для цепочек подкачки, в противном случае этот метод завершится неудачей.

• Вы должны освободить устройство и вызвать метод IDXGISurface1 :: ReleaseDC, прежде чем вводить какие-либо новые команды Direct3D.

• Этот метод завершается ошибкой, если с помощью этого метода уже был создан выдающийся DC.

• Формат поверхности или цепочки обмена должен быть DXGI_FORMAT_B8G8R8A8_UNORM_SRGB или DXGI_FORMAT_B8G8R8A8_UNORM.

• В GetDC цель рендеринга в выходном слиянии конвейера Direct3D не связана с поверхностью. Вы должны вызвать метод ID3D11DeviceContext :: OMSetRenderTargets на устройстве до визуализации Direct3D после визуализации GDI.

• Перед изменением размера буферов вы должны освободить все выдающиеся DC.

  • Если вы собираетесь использовать его в обратном буфере, не забудьте повторно связать цель рендеринга после того, как вы вызвали ReleaseDC. Нет необходимости вручную отсоединять RT перед вызовом GetDC, поскольку этот метод делает это за вас.

  • Вы не можете использовать любой Рисование Direct3D между вызовами GetDC () и ReleaseDC (), так как DXGI для GDI блокирует поверхность. Однако вы можете смешивать рендеринг GDI и D3D при условии, что вы вызываете GetDC () / ReleaseDC () каждый раз, когда вам нужно использовать GDI, прежде чем переходить к D3D.

  • Этот последний бит может показаться легким, но вы будете удивлены, как много разработчиков попадут в эту проблему - когда вы рисуете с GDI на заднем буфере, помните, что это буфер back, а не кадровый буфер, поэтому для того, чтобы на самом деле увидеть то, что вы нарисовали, вы должны повторно привязать RT к OM и вызвать метод swapChain-> Present (), чтобы обратный буфер стал кадровым буфером, а его содержимое отобразилось на экран.

3 голосов
/ 16 мая 2011

Может быть, вы все делаете хорошо, просто рисунок текста не делает то, что вы ожидаете?

COLORREF bla = SetPixel(hDc,1,1,RGB(255,255,255));
bool hmm = TextOutA(hDc, 10, 10, "LALALA!", 7);

Я не понимаю из этого, как вы ожидаете, что TextOutA догадается, что bla должен использоваться в качестве цвета текста. AFAIK цвет текста по умолчанию, используемый во вновь созданном / полученном DC - черный. Не уверен насчет режима заливки фона, но если он по умолчанию TRANSPARENT - это полностью объясняет, почему ничего не рисует.

Я бы изменил ваш код на следующий:

COLORREF bla = SetPixel(hDc,1,1,RGB(255,255,255));
VERIFY(SetTextColor(hDc, bla) != CLR_INVALID);

CREct rc(0, 0, 30, 20); // put relevant coordinates
VERIFY(ExtTextOut(hDc, rc.left, rc.top, ETO_CLIPPED, &rc, "LALALA!", 7));
0 голосов
/ 28 января 2019

Я собираюсь использовать его в заднем буфере. Я не уверен, правильно ли это сделано. Я не вижу рисунок. Он показывает черный.

HDC GetSurfaceDC()
{
    m_pSurface1 = nullptr;
    HDC hdc{};

    //Setup the swapchain surface
    IF_FAILED_THROW_HR(m_swapChain->GetBuffer(0, IID_PPV_ARGS(&m_pSurface1)));

    // Obtain the back buffer for this window which will be the final 3D render target.
    ID3D11Texture2DPtr backBuffer;
    IF_FAILED_THROW_HR(m_swapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer)));

    // Create a descriptor for the RenderTargetView.
    CD3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc(D3D11_RTV_DIMENSION_TEXTURE2DARRAY, DXGI_FORMAT_B8G8R8A8_UNORM, 0, 0, 1);

    ID3D11RenderTargetViewPtr renderTargetView;

    // Create a view interface on the render target to use on bind for mono or left eye view.
    IF_FAILED_THROW_HR(m_device->CreateRenderTargetView(backBuffer, &renderTargetViewDesc, &renderTargetView));

    m_context->OMSetRenderTargets(1, &renderTargetView.GetInterfacePtr(), nullptr);

    IF_FAILED_THROW_HR(m_pSurface1->GetDC(FALSE, &hdc));
    return hdc;
}

void ReleaseSurfaceDC()
{
     if (m_pSurface1 == nullptr)
        return;
     //When finish drawing release the DC
     m_pSurface1->ReleaseDC(nullptr);

     m_context->OMSetRenderTargets(1, &m_renderTargetView.GetInterfacePtr(), m_depthStencilView);
}

Я использовал цепочку обмена desc:

    DXGI_SWAP_CHAIN_DESC swapChainDesc = { 0 };
    swapChainDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE;
...