Inicjalizacja Direct3D. Szablon projektu.

Hej! Nie mam talentu do pisania kwiecistych wstępów. Zacznijmy więc od razu lekcję! :)

Co to jest Direct3D? Jest to API (Application Programming Interface), które, jak napisałem rozdział wcześniej, służy do rysowania (renderowania) na ekranie używając karty grafiki. Najnowszą obecnie wersją Direct3D jest wersja 10.1, która wprowadziła całkowicie nowe API odcinając się od poprzedników. My jednak zajmiemy się D3D9.0c. Ale co to dokładnie znaczy? Początki DirectX-a sięgają 1995 roku, kiedy to Microsoft stworzył pierwszą wersję tego pakietu. Nie była ona zbyt użyteczna – niewygodny interface i małe możliwości przemawiały zdecydowanie przeciw ówczesnemu D3D, który zdecydowanie przegrywał wtedy z OpenGL-em. Sytuacja ta utrzymała się aż do wersji 8. tej biblioteki, kiedy to przeprojektowano cały podsystem, zrywając kompatybilność wsteczną (mniej-więcej to samo nastąpiło z D3D10).

W tutorialu zakładam znajomość języka C++ w stopniu pozwalającym na swobodne posługiwanie się nim. Dodatkowo byłoby fajnie, gdyby ewentualny adept programowania grafiki 3D znał dosyć dobrze swoje środowisko programowania, troszkę WinAPI (a więc COM w pewnym stopniu).

Aby zacząć pracować z D3D nie potrzeba wiele. Przede wszystkim musimy ściągnąć SDK DirectX-a ze strony Microsoftu (darmowe). Jest ono niestety dosyć niemałe, ale da się to przeżyć – tym bardziej, że jest tam dużo fajnych rzeczy. Ustawiamy ścieżki w naszym środowisku (można też ustawić ścieżkę do Executables; przyda się to później). Każdy projekt D3D dołącza plik d3d9.h, a w większości przypadków również d3dx9.h. Pamiętamy o odpowiednich bibliotekach (d3d9.lib, d3dx9.lib).

   1: #include <d3dx9.h>

   2: #pragma comment (lib, "d3d9.lib")

   3: #pragma comment (lib, "d3dx9.lib")

   4:  

   5: IDirect3D9* pD3D;

   6: IDirect3DDevice9* pDev;

   7:  

   8: HWND hWnd;

   9:  

  10: void InitWindow()

  11: {

  12: //  ...

  13: }

  14: int __stdcall WinMain(HINSTANCE, HINSTANCE, LPSTR, int)

  15: {

  16:     InitWindow();

  17:     

  18:     pD3D = Direct3DCreate9(D3D_SDK_VERSION);

  19:  

  20:     D3DPRESENT_PARAMETERS d3dpp;

  21:     ZeroMemory(&d3dpp, sizeof(d3dpp));

  22:     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;

  23:     d3dpp.Windowed = true;

  24:     d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;

  25:     

  26:     pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, 

  27:         D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &pDev);

  28:  

  29:     MSG msg;

  30:     while(1)

  31:     {

  32:         if (PeekMessage(&msg, 0, 0U, 0U, PM_REMOVE))

  33:         {

  34:             TranslateMessage(&msg);

  35:             DispatchMessage(&msg);

  36:         }

  37:         else

  38:         {

  39:             pDev->Clear(0, 0, D3DCLEAR_TARGET, 0xff00ff00, 1, 0);

  40:             pDev->BeginScene();

  41:             pDev->EndScene();

  42:             pDev->Present(0, 0, 0, 0);

  43:         }

  44:     }

  45:     pDev->Release();

  46:     pD3D->Release();

  47: }

Zacznijmy od góry. Tak jak mówiłem, mamy dołączenie niezbędnych bibliotek oraz linkowanie z D3D. Plik windows.h jest dołączany przed d3d9.h, więc nie musimy sami tego robić.

Widzimy deklaracje zmiennych. IDirect3D9 jest najbardziej podstawowym interfejsem biblioteki. Tym niemniej, nie jest on często używany i posłuży nam jedynie do stworzenia znacznie ważniejszego obiektu – międzymordzia IDirect3DDevice9, nazywanego również urządzeniem D3D. Jest to dużo ważniejsze narzędzie i będzie nam ono towarzyszyć przez całą naszą podróż z tą biblioteką.

Funkcje inicjalizującą okno pomijam; zakładam, że czytelnik napisze ją sobie sam :)

Przechodzimy do sedna tej lekcji. Tworzenie obiektów głównych podsystemu. Jak widzimy, najpierw tworzymy IDirect3D9. Wskaźnik do niego uzyskujemy wywołując prostą funkcję tworzącą. Jako parametr przyjmuje ona aktualną wersję SDK, zdefiniowaną w nagłówku jako prosta do użycia stała.

Struktura D3DPRESENT_PARAMETERS opisuje nam tak zwane parametry prezentacji. Jest to dosyć szumna nazwa opisująca całkiem proste zadanie; D3DPP opisuje nam sposób, w jaki zachowywać będzie się urządzenie Direct3D. W strukturze jest oczywiście więcej pól niż te przedstawione w przykładowym kodzie, jednak je omówimy później, na razie zajmiemy się tymi. Pole SwapEffect oznacza jak zachowa się device przy zamianie buforów.

Tutaj mała dygresja dot. podwójnego buforowania; służy ono przeciwdziałaniu migotaniu obrazu wskutek rysowania aktualnie na nim. Działa to w prosty i logiczny sposób – karta graficzna rysuje na buforze tylnim (backbuffer). Po zakończeniu rysowania, za pomocą odpowiedniej funkcji, przerzucamy (pole SwapEffect!) bufor tylni na bufor klatki (zwany też rzadziej buforem przednim). Flaga D3DSWAPEFFECT_DISCARD oznacza, że urządzenie ma dowolność w wybraniu najoptymalniejszego sposobu przerzucania.

Pole Windowed jest zrozumiałe – oznacza ono, czy aplikacja utworzona zostanie w okienku czy w fullscreen. Następnie mamy pole BackBufferFormat. Odpowiada ono za sposób przechowywania koloru w buforze tylnym. Flaga D3DFMT_X8R8G8B8 oznacza, że w naszym nowoutworzonym backbufferze przchowywać będziemy 24bitowy kolor, po 8 bitów (256 wartości) na kanał (czerwony, zielony, niebieski i pusty – X).

Następnie mamy już faktyczną inicjalizację urządzenia renderującego. Funkcja może wyglądać na skomplikowaną, ale w rzeczywistości wywołanie jest bardzo intuicyjne.

   1: pD3D->CreateDevice(D3DADAPTER_DEFAULT,

   2:     D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &pDev);

Pierwszy parametr oznacza adapter, którego używać będzie urządzenie. Oznazcza ono w teorii „kartę graficzną”, jednak poza pewnymi rzadkimi i specyficznymi przypadkami flaga D3DADAPTER_DEFAULT, czyli domyśly adapter, będzie wystarczająca.

Następnym parametrem jest typ urządzenia. Tutaj używamu device`a typu HAL, czyli Hardware Abstraction Layer – warstwa abstrakcji nad sprzętem (niefortunne tłumaczenie ;) ). Innymi słowy, używamy karty grafiki zamiast przetwarzania programowego. Parametr hWnd jest jasny.

Flaga D3DCREATE_HARDWARE_VERTEXPROCESSING oznacza, że nasze wierzchołki (o tym później) będziemy przekształcać na karcie graficznej miast na procesorze. W końcu po cóż ona innego? ;) Dwa ostatnie argumenty to utworzona wcześniej struktura D3DPRESENT_PARAMETERS oraz nowoutworzone urządzenie.

   1: pDev->Clear(0, 0, D3DCLEAR_TARGET, 0xff00ff00, 1, 0);

   2: pDev->BeginScene();

   3: //Rendring

   4: pDev->EndScene();

   5: pDev->Present(0, 0, 0, 0);

 

W pętli czasu rzeczywistego używamy po raz pierwszy naszego urządzenia. Mamy podpięte je pod nasze okno, działające i gotowe do akcji.

Pierwsza funkcja (Clear) czyści backbuffer pod rendering następnej sceny. Jej dwa pierwsze parametry to ilość buforów oraz tablica struktur RECT które chcemy wyczyścić (zazwyczaj 2xNULL ;) ). Następnie flaga określająca co właściwie chcemy czyścić (D3DCLEAR_TARGET – kolor w tym przypadku), kolor na jaki czyścimy – u nas ładny zielony (kolor zapisany w postaci liczby int zapisujemy kanałami jaki 0xAARRGGBB). Dwa ostatnie parametry to wartości jakimi wypelniamy bufor Z oraz bufor matrycy.

Po zakończeniu programu musimy oczywiście zwolnić zajmowaną pamięć. Ważnym jest, aby zwalniać interface`y w kolejności odwrotnej niż były tworzone!

W następnym odcinku ( ;) ) zaczniemy już rysować po ekranie!

Kod źródłowy


komentarze 4 to “Inicjalizacja Direct3D. Szablon projektu.”

  1. Z dokumentacji funcji LoadCursor:
    ‚To use one of the predefined cursors, the application must set the hInstance parameter to NULL’

    Jest : LoadCursor(hProg, IDC_ARROW);
    Powinno być : LoadCursor(NULL, IDC_ARROW);

  2. Niezły kursik, fajnie jest się na nim przerzucać z OGL na DX. Cóż Charibo, kawał dobrej roboty.

  3. Mam do was wielkie pytanie… Wie ktoś w jaki sposób zainstalować directX sdk dla IDE Code::Blocks ?

  4. , przeciwnie zaś stary jak Katie diabli. W najbliższym czasie
    tenże aby zdechł. Von Egger milczał. Czuł się winno,
    poniekąd
    prawidłowo. Kardynalnym, który zameldował, był przebiegły szewc,
    starszy cechu. Smoka wprzódy nie stało, zaś.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s

 
%d blogerów lubi to: