2011-05-12 15 views
6

Potrzebuję pomocy przy rysowaniu tekstu do tekstury za pomocą GDI i D3D11. Próbowałem używać D2D/DirectWrite, ale obsługuje tylko D3D10, a nie D3D11, tak jak potrzebuję. Wszystko, czego próbowałem, zawiodło do tej pory ... Teraz chcę użyć metod GDI do napisania tekstury. Więc stworzyłem teksturę z tego params:D3D11: Jak narysować tekst GDI na powierzchni GXDI? (Bez 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 

Potem stworzył normalny RenderTargetView z tej tekstury jak Microsoft NOK tutaj: http://msdn.microsoft.com/en-us/library/ff476203%28v=vs.85%29.aspx

Następny krok: Get interfejsu DXGI:

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

W funkcji renderowania robię tylko to:

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; 

Problem polega na tym, że tekstura jest nadal pusta po tym rysunku GDI (również testowany przy użyciu PIX). Wszystko działa i nie ma komunikatów o błędach.

Mam nadzieję, że każdy może wyjaśnić, jak to działa.

Dzięki Stefan

EDIT: Próbowałem go również z GetDC(FALSE,&hDc) (zgodnie z dokumentacją): same wyniki -> nic.

+0

Czy próbowałeś formatu 'DXGI_FORMAT_R8G8B8A8_UINT'? – Necrolis

+0

zgodnie z dokumentem na łączu powyżej tekstury kompatybilnej z gdi wymaga specjalnych formatów "Musisz ustawić format tekstury na jeden z następujących typów: DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_TYPELESS, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB" – sandicz

Odpowiedz

3

Może robisz wszystko dobrze, to tylko tekst nie robi tego, czego się spodziewasz?

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

nie rozumiem z tego, jak można się spodziewać, że TextOutA będzie odgadnąć, że bla powinien być używany jako kolor tekstu. AFAIK domyślny kolor tekstu zastosowany w nowo utworzonym/uzyskanym DC jest czarny. Nie jestem pewien co do trybu wypełnienia tła, ale domyślnie jest to TRANSPARENT - w pełni wyjaśnia to, dlaczego nic nie rysuje.

Chciałbym zmienić swój kod do następujących:

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

Cześć, te linie są po prostu testami. ustaw piksel na 1,1 na biały, a następnie napisz tekst demonstracyjny. Spróbuję twojej wersji. dzięki :) – sandicz

+0

Właśnie zauważyłem, że otrzymuję komunikat o błędzie w funkcji GetDC(): "Microsoft C++ - Wyjątek: _com_error w pozycji pamięci 0x0018f760" (przetłumaczony na angielski). Naprawdę nie mogę sobie wyobrazić, dlaczego tak się dzieje. Może TO jest główny problem, a nie GDI. Wygląda na to, że muszę poczekać, aż DirectWrite obsługuje D3D11 ... – sandicz

+0

Tak, sprawdzanie wartości/wyjątków jest dobrym pomysłem, zwłaszcza jeśli coś jest nie tak :) – valdo

4

I rzeczywiście walczył ten problem dużo podczas ostatniego tygodnia - ale mam to wszystko działa! Oto lista rzeczy, które warto wiedzieć/zrobić, aby to wszystko działa:

Przechowywać następujące pamiętać przy korzystając z tej metody:

• należy utworzyć powierzchnię za pomocą D3D11_RESOURCE_MISC_GDI_COMPATIBLE flagę na powierzchni lub przy użyciu DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE flagę łańcuchami swapowych, w przeciwnym razie ta metoda zawiedzie.

• Musisz zwolnić urządzenie i wywołać metodę IDXGISurface1 :: ReleaseDC przed wydaniem jakichkolwiek nowych poleceń Direct3D.

• Ta metoda kończy się niepowodzeniem, jeśli za pomocą tej metody została już utworzona niespłacona wartość DC.

• Format powierzchni lub łańcucha wymiany musi mieć format DXGI_FORMAT_B8G8R8A8_UNORM_SRGB lub DXGI_FORMAT_B8G8R8A8_UNORM.

• W GetDC cel renderowania w połączeniach wyjściowych potoku Direct3D jest niezwiązany z powierzchni. Musisz wywołać metodę ID3D11DeviceContext :: OMSetRenderTargets na urządzeniu przed renderowaniem Direct3D po renderowaniu GDI.

• Przed zmianą rozmiarów buforów należy zwolnić wszystkie zaległe DC.

  • Jeśli masz zamiar używać go w buforze powrotnej, należy pamiętać, aby ponownie związać renderowanie cel po rozmawiania ReleaseDC. Nie jest konieczne ręczne rozłączanie RT przed wywołaniem GetDC, ponieważ ta metoda robi to za Ciebie.

  • Nie można używać dowolny rysunek Direct3D między GetDC() i ReleaseDC() zwraca jako powierzchnia jest excusively zablokowane przez DXGI do GDI. Można jednak łączyć renderowanie GDI i D3D pod warunkiem, że wywołasz GetDC()/ReleaseDC() za każdym razem, gdy będziesz potrzebować GDI, zanim przejdziesz do D3D.

  • Ten ostatni bit może brzmi to łatwe, ale możesz być zaskoczony, jak wiele programiści należą do tej kwestii - kiedy wyciągnąć z GDI na tylnym buforze, należy pamiętać, że jest to powrotem bufor, a nie bufor ramki, Aby więc zobaczyć, co narysowałeś, musisz ponownie połączyć RT z OM i wywołać metodę swapChain-> Present(), aby bufor wsteczny stał się buforem ramki, a jego zawartość zostanie wyświetlona na ekranie.

+0

hej, dziękuję za odpowiedź. to brzmi naprawdę użytecznie i może wiem, gdzie jest problem w moim kodzie (zwalnianie DC i ponowne wiązanie Rendertarget). Niestety nie mam teraz czasu, aby wypróbować twoje rozwiązanie, ale będę w przyszłości ... – sandicz

Powiązane problemy