воскресенье, 20 декабря 2009 г.

Direct3D 11 and Text Drawing

В 9 и 10 D3DX были классы для вывода текста (конкретно в 10 это ID3DXFont10). Замечательно так работали: задаём параметры шрифта (аналогично структуре LOGFONT), шрифт рендерится в текстуру, потом делаем Font->DrawText() и всё. В Direct3D 11 D3DX совершил очередной round-trip: если при переходе с 9 на 10 Effect FX перекочевал в ядро, то в 11 - обратно в D3DX :) Кроме того, фреймворк доступен в виде исходного кода, а не библиотеки (посмотрев, сколько там говна, я вообще решил не юзать FX). А вместе с изменениями в FX Microsoft убрал такие классы как ID3DXFont10, ID3DXMesh10, ID3DXSprite10 и т. д. Почти ничего этого я не использовал, но вот быстрый вывод шрифта в маленьких аппах через ID3DXFont10 был полезен.

Озадачившись выводом шрифта с новым SDK, я решил выводить его через GDI. Но напрямую GDI и D3D не дружат - текст ужасно мерцает. Полазив по SDK, я нашёл, как делать правильно.

1) При создании swap chain указываем флаг DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE.
2) Формат back-буфера должен быть DXGI_FORMAT_B8G8R8A8_UNORM_SRGB или DXGI_FORMAT_B8G8R8A8_UNORM (порядок RGBA не поддерживается).
3) Количество отсчётов в back-буфере должно быть равным 1.
4) Далее необходимо получить интерфейс поверхности (новый интерфейс в DXGI 1.1):

IDXGISurface1* pSurface1 = NULL;
pSwapChain->GetBuffer(0, __uuidof(IDXGISurface1), (void**)&pSurface1);

У этого интерфейса есть методы GetDC() и ReleaseDC(). Вывод текста средствами GDI можно делать между этими двумя вызовами:

HDC hDC;
pSurface1->GetDC(FALSE, &hDC);
...
//Draw on the DC using GDI
...
//When finish drawing relase the DC
pSurface1->ReleaseDC(NULL);

5) После необходимо заново прицепить render target окна, т. к. он отвязывается. У меня, если этого не делать, рантайм падает в D3D11SDKLayers.dll.

Комментариев нет:

Отправить комментарий