2011-05-12 3 views
6

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

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). Все работает и сообщений об ошибках нет.

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

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

EDIT: Пытался это также с GetDC(FALSE,&hDc) (согласно документации): одни и те же результаты -> ничего.

+0

Вы пробовали формат 'DXGI_FORMAT_R8G8B8A8_UINT'? – Necrolis

+0

в соответствии с документом по ссылке выше совместимой с gdi текстурой нужны специальные форматы. «Вы должны настроить формат текстуры одним из следующих типов: DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_TYPELESS, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB« – sandicz

ответ

3

Возможно, вы все делаете хорошо, это только текст не делает то, что вы ожидаете?

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

привет, эти строки - это просто тесты. установите пиксель с 1,1 на белый и, во-вторых, напишите демонстрационный текст. Я попробую вашу версию. спасибо :) – sandicz

+0

Я только заметил, что im получает сообщение об ошибке в функции GetDC(): «Microsoft C++ - Исключение: _com_error в ячейке памяти 0x0018f760» (на английском языке). Я действительно не могу представить, почему это происходит. Возможно, это главная проблема, а не GDI. Похоже, мне нужно подождать, пока DirectWrite не поддержит D3D11 ... – sandicz

+0

Да, проверка возвращаемого значения/исключений - хорошая идея, особенно если что-то не так :) – valdo

4

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

Учитывайте следующее в виду, когда с помощью этого метода:

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

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

• Этот метод завершается с ошибкой, если этот метод уже создан.

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

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

• Перед изменением размера буферов вы должны освободить все неиспользуемые контроллеры постоянного тока.

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

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

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

+0

эй, спасибо за ваш ответ. это звучит очень полезно, и, может быть, я знаю, где проблема в моем коде (освобождение DC и восстановление Rendertarget). К сожалению, у меня нет времени, чтобы попробовать ваше решение, но я буду в будущем ... – sandicz

Смежные вопросы