Direct3D 2D + sprite

background image

1

DirectX ▪ 2D + Sprite

Powitanko.
Co jak co, ale tego się po Was nie spodziewałem. Ja się tutaj produkuję, żebyśmy mogli tworzyć wspaniałe światy 3D, przy
których Tomb Raider czy Quake wymiękają a Wy mi robicie taką rzecz? Wy chcecie 2D??? W zasadzie to mógłbym Was
odesłać do tutorialu o wierzchołkach, bo tam ładnie to macie opisane. Nic w zasadzie nie trzeba kombinować, wszystko jest
zupełnie płaskie! Jak łatwo zauważyć, nie ma tam żadnego rzutowania, macierzy i tym podobnych rzeczy. Trójkąt, który
wyświetlamy a w zasadzie jego współrzędne, pokrywają się co do joty z rzeczywistymi, jeśli można tak powiedzieć,
współrzędnymi okna. Wystarczyłoby utworzyć teksturę, załadować na trójkąt i gotowe... możemy śmigać w 2D. No ale
pewnie wielu z Was zacznie kręcić nosem i mówić, że to nie całkiem to, o co im chodziło. W zasadzie nie bardzo potrafię
sobie wyobrazić, co może być fajniejszego w wykorzystaniu obiektów 3D (bez trzeciego wymiaru) w technice 2D. Mamy w
ręce przecież coś takiego jak wierzchołki, więc dużo rzeczy na pewno da się zrobić o wiele, wiele prościej - czy to kolizje z
innymi obiektami, czy wykorzystanie kanału alfa czy co tam Wam do głowy jeszcze przyjdzie. Żeby Was przekonać, że to
ma sens ten oto tutorialik, dzięki któremu i Wam 2D nie odejdzie jeszcze całkiem w przeszłość.

Stare, najlepsze platformówki najczęściej posiadały bardzo ładne, kolorowe tło, po którym przesuwały się postacie
znajdujące się na pierwszym planie. Zastanówmy się przez chwilę, jak my moglibyśmy zrealizować je u nas. Pierwszym,
oczywistym sposobem jest załadowanie tekstury przedstawiającej nasze tło do pamięci no i potem nałożenie jej na prostokąt,
złożony na przykład z dwóch trójkątów, który będziemy wyświetlać na ekranie. Animacja naszego tła polegałaby na
płynnym zmienianiu współrzędnych mapowania naszego prostokąta - przy założeniu, że prostokąt umieścimy w taki sposób,
aby mieścił się nam całym na ekranie a tekstura była o wiele większa. Patrząc na to chłodnym okiem moglibyśmy stwierdzić,
że jest to całkiem niezły pomysł, więc spróbujmy go zrealizować. Omówimy sobie dzisiaj trochę kodu , ale oparty jest on
ciągle na tych samych szablonach, których używamy cały czas. O inicjalizacji urządzeń i wszelkich innych niezbędnych
zabiegach, aby naszą aplikację uruchomić nie będę już trąbił setny raz i skupię się na tym co najważniejsze:


struct CUSTOMVERTEX
{
FLOAT x, y, z, rhw; // The transformed position for the vertex
DWORD color; // The vertex color
FLOAT tx, ty;
};

Przyzwyczailiśmy się już do tego, że na własną rękę transformujemy wierzchołki (liczymy dla nich macierze, rzutujemy i
wyświetlamy). Pamiętacie na pewno lekcję o wierzchołkach. Tam użyliśmy ich nie przetransformowanych i dzisiaj właśnie
powrócimy do tego, jak wspomniałem na początku. Ponieważ nie chcemy trzeciego wymiaru, nie będzie nam więc zależało
na przeliczeniu wierzchołków przez perspektywę i odpowiednim ich zrzutowaniu na płaszczyznę ekranu. Dzisiaj użyjemy
sobie wierzchołków przetransformowanych przez Direct3D. Co nam to da? Podstawowa rzecz to to, że współrzędne
wierzchołków pokryją nam się ze współrzędnymi na ekranie. Co to znaczy? Jak wiemy, ekran (okno) ma określone
współrzędne. Lewy, górny róg jest przeważnie określony jako punkt o współrzędnych (0, 0), natomiast prawy dolny
zależy od aktualnie ustawionego rozmiaru okna. Jeśli więc narysujemy sobie wierzchołek w punkcie (0, 0), to znajdzie
się on w lewym górnym rogu naszego ekranu a nie na środku, gdzie znalazłby się gdybyśmy odpowiednio
przekształcili go przez nasze macierze.
Jeśli chodzi o 2D, to niesamowicie ułatwia nam to sprawę. Będziemy mogli
malować nasze rysuneczki dokładnie w miejscach, gdzie sobie tego zażyczymy, bez kombinowania w przestrzeni 3D! A
jednocześnie będziemy mieć do dyspozycji trójkąty i wierzchołki i wszelkie inne dobrodziejstwa 3D, czyż to nie wspaniałe?

// Our custom FVF, which describes our custom vertex structure
#define D3DFVF_CUSTOMVERTEX(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1 )

To oczywiście bardzo dobrze nam znana definicja typu wierzchołków złożonego z typów podstawowych. Ale sądzę, że tego
już nie muszę Wam tłumaczyć. Uruchamianie Direct3D dzisiaj sobie darujemy, ale wiemy przecież doskonale, jak to robić,
prawda?


HRESULT InitVB()
{
RECT rect;
GetClientRect( hWnd, &rect );

// Initialize six vertices for rendering a triangle
CUSTOMVERTEX g_Vertices[] =
{
{ (float)rect.left, (float)rect.top, 100.0f, 1.0f, 0xFFFFFFFF, 0.0f, 2.0f },
{ (float)rect.right, (float)rect.bottom, 100.05f, 1.0f, 0xFFFFFFFF, 2.0f, 0.0f
},
{ (float)rect.left, (float)rect.bottom, 100.0f, 1.0f, 0xFFFFFFFF, 0.0f, 0.0f },
{ (float)rect.left, (float)rect.top, 0.0f, 1.0f, 0xFFFFFFFF, 0.0f, 2.0f },
{ (float)rect.right, (float)rect.top, 0.0f, 1.0f, 0xFFFFFFFF, 2.0f, 2.0f },
{ (float)rect.right, (float)rect.bottom, 0.0f, 1.0f, 0xFFFFFFFF, 2.0f, 0.0f },

background image

2

DirectX ▪ 2D + Sprite

};
...
}

Nasza funkcja do tworzenia bufora wierzchołków i jego wypełniania odpowiednimi wartościami. Ogólna istota jest już
oczywiście Wam doskonale znana, więc my zajmiemy się szczegółami. Na początku zadajmy sobie jakże słuszne pytanie -
Co my tak właściwie chcemy osiągnąć? Wyobraźmy sobie, że robimy typową platformówkę - postać chodzi sobie po
planszy, plansza przewija się w odpowiedni sposób w zależności od ruchu postaci. Ogólnie mówiąc chcemy, aby nasz ekran,
na którym będzie toczyć się rozgrywka, był czymś w rodzaju okna, które pokazuje tylko określony, potrzebny w danym
momencie wycinek planszy. Oknem tym możemy przesuwać w dowolną stronę i możemy wybierać z planszy ten fragment,
który chcemy. Sytuację przedstawia mniej więcej rysunek poniżej:


Jak to zrealizować w naszym programie? Nic prostszego:


RECT rect;
GetClientRect( hWnd, &rect );

Ponieważ nasza aplikacja pracuje w oknie, więc konieczne staje się pobranie jego współrzędnych, dzięki którym będziemy
wiedzieć gdzie w oknie narysować trzeba trójkąt. Nie wspomniałem o tym wcześniej, więc już się poprawiam. Kiedy
rysujemy w oknie przetransformowane wierzchołki, to ich współrzędne podajemy względem współrzędnych okna. Co to
znaczy? Wiadomo, że okno może być położone na ekranie w zasadzie w dowolnym miejscu. Jak wiadomo, okno posiada
obszar w którym można rysować i robić praktycznie co się chce - jest to tak zwany obszar klienta. Jest to praktycznie całe
okno prócz belki tytułowej, ramek i innych rzeczy, po których (teoretycznie) nie można rysować. Pomimo zmian położenia
okna na ekranie, współrzędne obszaru klienta w oknie pozostają oczywiście zawsze te same. Lewy górny róg obszaru klienta
ma względem okna, w którym leży zawsze współrzędne (0, 0) co chyba wydaje się oczywiste. Prawy dolny zależy już tylko
od rozmiaru i typu okna (czy posiada ramki, jakiej są one grubości, itd.). W naszym przypadku chcemy, aby nasz prostokąt,
złożony z trójkątów, pokrył nam cały obszar klienta, musimy więc określić jego współrzędne. Robimy to funkcją

GetClientRect()

. Pobiera ona dwa argumenty - pierwszym z nich jest uchwyt okna, w którym określamy położenie naszego

obszaru. Położenie to będzie określone poprzez drugi argument, o którym już wspominałem czyli przez strukturę

RECT

,

zawierającą dane prostokąta - czyli najprościej mówiąc jego lewy górny i prawy dolny wierzchołek.

...
(float)rect.left, (float)rect.top, 0.0f, 1.0f, 0xffff0000, 0.0f, 2.0f }
...

Następnie tworzymy tablicę zawierającą dwa trójkąty, które w całości stworzą prostokąt. Trójkąty te pokryją nam cały obszar
klienta, a po nałożeniu na nie tekstury, będziemy mieć gotowe do wykorzystania tło. Pierwsze dwie współrzędne każdego
trójkąta to elementy struktury

RECT

zawierające dane o obszarze klienta naszego okna. Widać z tego, że trójkąt będzie

umieszczony w całej rozciągłości tego obszaru, bo jako argumentów używamy skrajnych wartości. Jak będą umieszczone te
trójkąty nietrudno sobie wyobrazić. Współrzędna z może mieć w zasadzie dowolną wartość, my dla porządku ustawiamy ją
na 0.0 ale jak ktoś nie wierzy, niech ustawi na przykład w jednym trójkącie na 100 a w drugim na 0 - nie zmieni się
absolutnie nic. Czwarta współrzędna jest potrzebna Direct3D do transformowania przez niego wierzchołków i nie ma dla nas
znaczenia, podobnie jak współrzędna z, powinna ona mieć jednak wartość 1. Następnie ustawiamy kolor naszych
wierzchołków. Tutaj ujawni się jeszcze jedna zaleta używania przez nas wierzchołków. Mimo że nie mamy trzeciego
wymiaru, mamy do dyspozycji wszelkie inne "bajery". Wiadomo, że nakładamy na trójkąty teksturę, więc możemy zrobić co
na przykład? Ano możemy sobie zmodulować kolor tekstury za pomocą koloru wierzchołków, prawda? Możemy ustalić
sobie więcej współrzędnych teksturowania niż tylko jedne, możemy władować sobie multitekstury, możemy... dużo, dużo
więcej :-). No ale wróćmy na ziemię. Dwa ostatnie pola naszego wierzchołka to współrzędne teksturowania. I tutaj tkwi cały
bajer. My podamy z naszej załadowanej planszy tylko pewien wycinek, który chcemy aby był widoczny na ekranie. Przecież
nikt nie każe nam podawać współrzędnych 0.0 - 1.0, prawda? My wybierzemy sobie ze środka tektury, która będzie większa
od naszego okna pewien fragment. Rozwiązanie to ma pewną małą niedogodność. Otóż przy dużych planszach będzie trochę
trudno określić, jakie współrzędne mapowania należy dobrać z bitmapy, aby w teksturze nakładanej na trójkąty jeden teksel
tekstury odpowiadał jednemu pikselowi na ekranie. Rozwiązania najprostsze:

• Można sobie napisać odpowiednie przeliczanie współrzędnych mapowania na podstawie obrazka i rozmiarów okna.

• Można ustalać rozmiary plansz, które są wielokrotnością współrzędnych okna (będzie łatwiej dobierać współrzędne

mapowania dla trójkątów).

background image

3

DirectX ▪ 2D + Sprite

• Mamy do dyspozycji filtrowanie tekstur! Więc nawet jak się "walniemy" o jeden czy dwa piksele, to nic się nie

stanie, prawda? Możemy stosować wszystkie sztuczki znane nam z techniki 3D, co bardzo ułatwia sprawę.

void ChangeVertex( int nDir )
{
CUSTOMVERTEX g_Vertices[6];

g_pVB->Lock( 0, sizeof(g_Vertices), (BYTE**)&pVertices, 0 );
memcpy( g_Vertices, pVertices, sizeof( g_Vertices ) );

// ... change tex coord ...
for( int i = 0; i < 6; i++ )
{
g_Vertices[i].tx = ...;
g_Vertices[i].ty = ...;
}
memcpy( pVertices, g_Vertices, sizeof( g_Vertices ) );
g_pVB->Unlock();
}

No i w zasadzie wszystko jest już jasne. Teraz pozostaje nam tylko napisanie funkcji, która na jakiejś tam podstawie będzie
nam zmieniać współrzędne mapowania naszej tekstury. Ktoś zawoła: zaraz, zaraz! Współrzędne wierzchołków mamy w
buforze i teraz nie ma jak się do nich dobrać! I tu się myli! To, że mamy je w buforze paradoksalnie znacznie ułatwia nam
sprawę! Co musimy zrobić aby dobrać się do tych wierzchołków?

CUSTOMVERTEX g_Vertices[6];

Ponieważ nasza bryła a właściwie płaska powierzchnia składa się tylko z sześciu wierzchołków, więc nie zaszkodzi nam
absolutnie, jeśli zrobimy sobie dodatkową, tymczasową tablicę, która będzie nam przechowywać te sześć wierzchołków - w
końcu to tylko kilkadziesiąt bajtów w pamięci. Tworzymy więc naszą tymczasową tablicę:

g_pVB->Lock( 0, sizeof(g_Vertices), (BYTE**)&pVertices, 0 );
memcpy( g_Vertices, pVertices, sizeof( g_Vertices ) );

Nie zapominajmy, że cały czas mamy w ręce uchwyt do naszego bufora wierzchołków w zmiennej g_pVB. Mając ten
uchwyt, możemy sobie w każdej chwili "otworzyć" czyli odblokować nasz bufor, co też robimy, wykorzystując metodę

Lock()

interfejsu bufora wierzchołków. Następne co robimy, to kopiujemy zawartość naszego bufora (sześć wierzchołków)

do naszej pomocniczej tablicy, którą przed chwilą stworzyliśmy. A po co nam to? Ano po to, aby móc sobie zmienić
współrzędne wierzchołków w tablicy i ponownie zapisać ja do bufora! Ktoś powie, że równie dobrze możemy to zrobić
grzebiąc bezpośrednio w buforze. I będzie miał rację. Możemy sobie używając wskaźnika do pamięci (pVertices) buszować
po pamięci bufora i zmieniać co nam się tylko podoba. Dlaczego ja zrobiłem to tak a nie inaczej? Uznałem po prostu, że tak
będzie jaśniej i będzie wszystko widać. Wy, w swoich produkcjach, oczywiście możecie zrobić to na milion innych
sposobów, ważna jest sama istota naszego działania.

// ... change tex coord ...
for( int i = 0; i < 6; i++ )
{
g_Vertices[i].tx = ...;
g_Vertices[i].ty = ...;
}

Mając współrzędne naszych wierzchołków w tablicy, możemy przystąpić do działania, czyli do ich zmiany. Nie ma chyba
nic prostszego - po prostu odwołujemy się do odpowiednich pól tablicy i zmieniamy co trzeba. Prawda, że proste? Zmiana ta
może obejmować też współrzędne wierzchołków czy ich kolor oczywiście, co daje nam do ręki znów spore możliwości... no
ale wszystko zależy od Waszej wyobraźni - tylko i wyłącznie.

memcpy( pVertices, g_Vertices, sizeof( g_Vertices ) );
g_pVB->Unlock();

Po tej zmianie tego możemy z powrotem umieścić zmienione dane w naszym buforze. Kopiujemy więc naszą tablicę w drugą
stronę, czyli do naszego bufora i odblokowujemy go, aby aplikacja mogła działać dalej. I to w zasadzie cała filozofia robienia
"płaskiego" w 3D. Mając wypełniony bufor, załadowaną na scenę teksturę, ustalony sposób działania (chodzi o zmianę
współrzędnych) możemy przystąpić do renderingu. W tym miejscu muszę nadmienić, że nie możemy zapominać, że mamy
do dyspozycji nowe wynalazki panów z nVidii czyli vertex i pixel shader! Ale czy potraficie wymyślić coś w 2D, żeby fajnie
wyglądało wykorzystując moc naszych akceleratorów? Na końcu artykułu macie przykładowy program, który wykorzystuje
opisaną przeze mnie właśnie technikę tworzenia tła w 2D wraz z zastosowaniem interfejsu do sprite'ów z biblioteki

D3DX

, o

background image

4

DirectX ▪ 2D + Sprite

którym już za chwilę. Właśnie, właśnie. Mamy nasze tło, czas więc wprowadzić na scenę, coś co się rusza. A ruszać się
będą... duchy. Duchy czyli inaczej mówiąc sprite'y. Są one obecne od czasów, od kiedy obecne są platformówki. Sprite'y
reprezentują wszystko, co może się poruszać po ekranie, czyli pływające, latające, biegające i chodzące, postacie bohaterów,
wrogów i wszystko co może nas uderzyć, czyli zrobić mniejszą lub większą krzywdę. Sprite ma to do siebie, że podczas
poruszania się, nie zostawia żadnych śladów na ekranie. To znaczy, że w miejscu, gdzie go już nie ma, nie pozostaje jego
obraz, tylko tło, na którym przebywał. Przy poruszaniu sprite'ów stosujemy następującą technikę:

1. Określamy nowe położenie sprite'a.
2. Zapamiętujemy tło, jakie znajduje się w tym miejscu.
3. Rysujemy w miejscu poprzedniego pobytu sprite'a to co było pod nim (zapamiętane w kroku nr 1).
4. Rysujemy sprite'a w nowym miejscu.

Tak powtarzając te operacje będziemy mogli poruszać spritem po całym ekranie. Jak widać, jest to operacja dosyć
pracochłonna, ale od czego jest nasz pakiet? W zasadzie dzisiaj nie robi się już platformówek (a szkoda), ale być może po
tym artykule pojawi się kilka nowych ;-). Ponieważ pakiet DirectX zawiera wszystko co jest potrzebne do zrobienia gry (i to
gry dowolnego rodzaju), nie może w nim więc zabraknąć czegoś takiego jak sprite'ów. Nie pamiętam kiedy dokładnie
pojawił się sprite'owy interfejs, ale podejrzewam, że wraz z biblioteką

D3DX

. Co on nam takiego daje do ręki i po co nam on

w ogóle. Gdybyśmy chcieli ręcznie malować sprite'y, to nie ma oczywiście żadnego problemu - tworzymy trójkąty, które
będą obrazowały coś co będzie się poruszać, ładujemy do bufora wierzchołków, ustalamy blendingi i wszystko co trzeba no i
malujemy! Ale można sobie to wszystko znacznie ułatwić. Interfejs

ID3DXSprite

daje nam do ręki kilka metod, które w

znacznym stopniu ułatwiają nam tworzenie i rysowanie sprite'ów na ekranie. Całość oczywiście jest w dokumentacji SDK,
no ale omówmy sobie jak w praktyce to zastosować:

LPD3DXSPRITE pSprite;

void InitSprite()
{
D3DXCreateSprite( g_pd3dDevice, &pSprite );
}

Po pierwsze to musimy mieć zmienną, która będzie obiektem naszego sprite'a. W bibliotece

D3DX

mamy coś takiego jak

LPD3DXSPRITE

- czyli wskaźnik na obiekt (interfejs) reprezentujący naszego duszka. Funkcją (nie jest to metoda żadnego

interfejsu!)

D3DXCreateSprite()

tworzymy naszego sprite'a. Jako pierwszy argument podajemy zainicjalizowane wcześniej

urządzenie renderujące. Drugi z tych argumentów to właśnie nasz sprite. Jest to bardzo proste, prawda? Nie musimy tworzyć
żadnych trójkątów, inicjalizować bufora wierzchołków, wypełniać go i przeprowadzać całej tej długiej procedury. My go po
prostu tworzymy. Nie wiemy nawet jaki ma rozmiar, gdzie jest położony... po prostu sobie jest.

pSprite->Draw( g_pTexture, NULL, NULL, NULL, 0.0f, NULL, 0xFFFFFFFF );

A dlaczego? Cała tajemnica tkwi w metodzie obiektu sprite'a o nazwie

Draw()

. Metoda ta powoduje narysowanie naszego

duszka na ekranie. Pobiera ona szereg argumentów, które pozwolą na dosyć szeroką manipulację naszym obiektem. Jako
pierwszy z tych argumentów nadchodzi tekstura, z której zostanie złożony nasz duszek. Należy zaznaczyć w tym miejscu, że
właśnie tutaj decyduje się wielkość naszego sprite'a. Będzie on dokładnie tak duży, jak duża jest tekstura reprezentująca
obraz na niego nałożony! Tak więc odpada nam myślenie nad współrzędnymi wierzchołków - tutaj decyduje obrazek -
prawie jak za starych dobrych czasów, prawda? Drugi argument to współrzędne prostokąta (struktura

RECT

), jaki

pragniemy wyciąć z podanej jako pierwszy argument tekstury i chcemy umieścić na naszym obiekcie sprite'a. Po co to?
Załóżmy, że mamy chodzącego ludzika. Będziemy na pewno potrzebować kilku obrazków, które będą reprezentować kolejne
fazy jego ruchu podczas animacji. Zwykło się robić, tak że wszystkie możliwe pozycje, w jakich przebywa nasz bohater, są
umieszczane w jednym obrazku. My także możemy tak zrobić - możemy załadować wszystkie fazy ruchu jako jedną teksturę
i potem tylko, podczas ruchu obrazka, zmieniać poszczególne klatki zmieniając prostokąt, z jakiego kopiujemy. Można sobie
w ten sposób bardzo ułatwić animowanie naszego płaskiego obrazeczku. Jeśli podamy jako ten argument wartość

NULL

, to

skopiowana zostanie cała tekstura i sprite będzie miał taki rozmiar. Trzeci argument to wektor skalujący. Po co nam to?
Możemy przeskalować sobie naszego sprite'a w dowolną stronę (x i y), na przykład jak spadnie nam na głowę coś dużego, to
możemy sobie to odpowiednio narysować. Dzięki filtrowaniu obrazek będzie się zachowywał bardzo przyzwoicie. Mówiąc
"skalowanie" miałem na myśli też oczywiście powiększanie, które jest niewątpliwie jego rodzajem. Kolejny parametr to
punkt obrotu. Pamiętacie jeszcze ile trzeba było się nakombinować, żeby zrobić latające gwiazdki, które by się jeszcze
obracały dodatkowo? A tu proszę... dzięki zastosowaniu współrzędnych i trójkątów, możemy sobie bez problemu poobracać
naszym sprite'em. Ten parametr służy do pokazania według jakiego punktu nasze sprite'y maja się obracać. Jeśli podamy

NULL

, to będą one obracane względem punktu (0, 0). Tak więc, jeśli chcielibyśmy obracać naszego sprite'a wokół własnej

osi, to musimy gdzieś pamiętać jego położenie i na jego podstawie obliczać potrzebne współrzędne. Następująca
bezpośrednio po tym wartość to, jak pewnie łatwo się domyśleć, wartość kąta, o który ma zostać obrócony nasz sprite wokół
ustalonego wcześniej punktu. Spokojnie, już zbliżamy się do końca ;-) - kolejny argument to wektor, o który przesuwamy
naszego sprite'a po planszy. Z tej wartości będziemy zdecydowanie najczęściej korzystać, bo za jej pomocą będziemy mogli
polatać sobie po ekranie. No i ostatnim argumentem naszej metody jest kolor. Jest kolor wierzchołków z którym to będzie
zmodulowana nasza tekstura (dokładnie jak w 3D). Nie mamy tutaj niestety możliwości dobrania się do poszczególnych

background image

5

DirectX ▪ 2D + Sprite

wierzchołków, aby każdemu ustalić inny kolor, ale czy naprawdę jest nam coś takiego potrzebne?

Zauważcie na koniec co dzieje, kiedy spróbujecie przesuwać sprite'a. Nie maże on po tle! Zasługą tego jest zastosowanie
gotowego obiektu, który takie metody ma już zaimplementowane! No i tu uwidacznia się jeszcze jedna zaleta naszego
sposobu. Nie musimy się już martwić o nasz algorytm - my po prostu skupiamy się na rysowaniu. Oczywiście możemy
zrezygnować z tego interfejsu, jeśli pragniemy tworzyć jakieś bardziej wymyślne kombinacje postaci. Będziemy mogli w
łatwiejszy sposób liczyć kolizje, definiować lepsze zachowanie się sprite'ów itp. Tutaj powinna zadziałać już Wasza
wyobraźnia i liczę, że na pewno Wam jej nie zabraknie. Wszystko to, co opisałem, korzysta z dobrodziejstw nowego
DirectX-a i technik 3D, które zostały niejako "wplecione" do 2D. Jeśli posiadacie jakieś stare engine'y, które opierały się na
ręcznym robieniu wszystkiego, zapisywaniu do pamięci karty bezpośrednio, to możecie być trochę załamani. Ale mam dla
Was dobrą wiadomość: jeszcze nic straconego! Następna lekcja będzie o tym jak wrócić do podstaw, czyli starych, dobrych i
sprawdzonych sposobów - będzie zatem trochę o powierzchniach. No a jeśli w międzyczasie skompilowaliście i
uruchomiliście program, to powinniście zobaczyć mniej więcej coś takiego:


Wyszukiwarka

Podobne podstrony:
Direct3D 11 Tessellation
Premier Press Beginning DirectX 9
2d 3 6 Nieznany (2)
Active Directory
5. Prensa, Hiszpański, Kultura, España en directo
2D ZŁOŻENIOWY A3
cw 2d kanalizacja przewody kanalizacyjne PRZEWODY
Kolokwium 1 zestaw 2D
Active Directory
Direct3D Vertex shader 1
Coupe, 2d , 2006 2010
Intermediate Short Stories with Questions, Driving Directions
Directional Movement Index, giełda(3)
2d-15.09, AWF, konspekty
directx
Komunikacja rynkowa direct response marketing

więcej podobnych podstron