Wprowadzenie

Poniższy artykuł ma na celu przekonanie młodych programistów gier do DirectX oraz ułatwienie życia tym, którzy zastanawiają się nad przesiadką z OpenGL’a. Przedstawię tutaj parę podstawowych kwestii w programowaniu w DirectX 9 przy okazji pisania swojej własnej kasy do symulacji trybu bezpośredniego znanego z OpenGL.
Implementacja klasy do obsługi buforów wierzchołków

Wydaje mi się, że każdy początkujący programista ma przerażenie w oczach, gdy zobaczy operacje konieczne, aby w ogóle utworzyć bufor wierzchołków, a co dopiero coś narysować na ekranie. Te operacje mogą się początkowo wydawać trudne i trochę niepotrzebne.

Operacje konieczne do zainicjalizowania bufora wierzchołków:
1. Inicjalizacja DirectX 9
2. Utworzenie bufora wierzchołków (g_d3d9->CreateVertexBuffer(…))
3. Ustalenie formatu wierzchołków, które będą przechowywane w buforze
4. Zablokowanie bufora
5. Skopiowanie przygotowanych wierzchołków w odpowiednim formacie do bufora
6. Odblokowanie bufora

Teraz, aby jeszcze cos narysować za pomocą tego bufora konieczne są następujące operacje:
1. Ustawienie źródła skąd będą pobierane dane o wierzchołkach
2. Ustawienie formatu wierzchołków
3. Narysowanie wierzchołków (np. za pomocą g_d3d9->DrawPrimitive(…))
I na koniec po zakończeniu pracy z buforem zwolnienie bufora wierzchołków.

Ufff… aż tyle operacji do zapamiętania dla początkującego w DirectX może być zniechęcające. To nie to samo, co stare dobre glBegin i glEnd. Dlatego, aby uniknąć ewentualnych błędów przy wykonywaniu tych samych czynności zamkniemy je w klasę.

Przykładowa implementacja (musimy wykorzystać szablony, aby nasza klasa była jak najbardziej elastyczna):

Kod wydaje mi się, że jest dość przejrzysty. Jeśli czegoś nie rozumiesz polecam zerknąć do odpowiedniej książki o DirectX lub do SDK. Wadą powyższego kodu jest to, że prawie w każdej funkcji konieczne jest przekazywanie wskaźnika do urządzenia DirectX. Można to rozwiązać poprzez utworzenie globalnego obiektu DirectX.

Teraz czas na przedstawienie wykorzystanie tej klasy w praktyce(na podstawie kodu z SDK):

Jak widać użycie naszej klasy znacznie uprościło nam sprawę 😉

Implementacja klasy symulującej glBegin i glEnd

Naszym celem będzie stworzenie odpowiedników tych funkcji w DirectX 9. Na początek przypomnienie dla tych, którzy nie pamiętają jak te funkcje działają:
glBegin(typ_wielokatow);

typ_wielokatow może być np.: GL_TRIANGLES, GL_LINES, GL_QUADS, GL_TRIANGLESTRIP… itp. Typ wielokątów tak naprawdę określa, w jaki sposób maja być interpretowane wierzchołki znajdujące się w bloku glBegin – glEnd.
glEnd() – koniec podawania wierzchołków
Pomiędzy tymi funkcjami umieszcza się instrukcje, np. glVertex2f, glColor3f… itp. Określające poszczególne parametry wierzchołków.

Dla tych, którzy nie rozumieją, co oznaczają poszczególne operacje odsyłam do artykułów wyjaśniających podstawy operacji graficznych w OpenGL’u lub jeśli Cię to API nie interesuje możesz je po prostu zignorować (nie powinno ci to przeszkodzić w zrozumienie pozostałej części artykułu).

Zacznijmy od przedstawienie naszej implementacji w DirectX:

Powyższa klasa jest dość prosta i z pewnością ma wiele niedoskonałości. Chociaż osobiście nie widzę zbyt wielu możliwości na jej rozbudowę. Jej implementacja stawia jednak pewne wymaganie odnośnie struktury przechowującej wierzchołki:
1. Klasa reprezentująca wierzchołek musi mieć publiczny konstruktor domyślny
2. Dla wygody przydałby się również konstruktor do inicjalizacji wszystkich składowych klasy jakimiś wartościami

Dlaczego, jest tak a nie inaczej postaram się przedstawić na poniższym przykładzie:

Powyższy przykład spowoduje narysowanie na ekranie takiego samego trójkącika jak ten narysowany powyżej z „zwykłego” bufora wierzchołków.

Od Autora
Mam nadzieję, że powyższy artykuł okaże się dla kogoś przydatny. Wszelkie pytania i uwagi proszę kierować na adres: gosuwachu@o2.pl

Autor: Wachu