2. Tekstury w Direct3D7
Transkrypt
2. Tekstury w Direct3D7
Direct3D7, cz. 2 - tekstury W poprzedniej części artykułu stworzyliśmy obracającą się piramidę. Jednak omówienie posługiwania się teksturami będzie prostsze z wykorzystaniem sześcianu. W tym celu należy zmodyfikować procedurę geometrii: Public Sub GEOMETRY() DX.CreateD3DLVertex -5, -5, -5, DX.CreateColorRGB(1, 1, 1), 1, 0, 0, Wierzcholek(0) DX.CreateD3DLVertex -5, 5, -5, DX.CreateColorRGB(1, 1, 1), 1, 0, 0, Wierzcholek(1) DX.CreateD3DLVertex 5, -5, -5, DX.CreateColorRGB(1, 1, 1), 1, 0, 0, Wierzcholek(2) DX.CreateD3DLVertex 5, 5, -5, DX.CreateColorRGB(1, 1, 1), 1, 0, 0, Wierzcholek(3) DX.CreateD3DLVertex 5, -5, 5, DX.CreateColorRGB(1, 1, 1), 1, 0, 0, Wierzcholek(4) DX.CreateD3DLVertex 5, 5, 5, DX.CreateColorRGB(1, 1, 1), 1, 0, 0, Wierzcholek(5) DX.CreateD3DLVertex -5, -5, 5, DX.CreateColorRGB(1, 1, 1), 1, 0, 0, Wierzcholek(6) DX.CreateD3DLVertex -5, 5, 5, DX.CreateColorRGB(1, 1, 1), 1, 0, 0, Wierzcholek(7) DX.CreateD3DLVertex -5, -5, -5, DX.CreateColorRGB(1, 1, 1), 1, 0, 0, Wierzcholek(8) DX.CreateD3DLVertex -5, 5, -5, DX.CreateColorRGB(1, 1, 1), 1, 0, 0, Wierzcholek(9) End Sub Nie zapomnijmy o zwiększeniu tablicy wierzchołków. Teraz potrzebujemy ich dziesięć: Public Wierzcholek(10) As D3DLVERTEX 'tablica wierzchołków Nalezy też zwiększyć liczbę wyświetlanych wierzchołków w metodzie DrawPrimitive w procedurze RENDERLOOP: Call Device.DrawPrimitive(D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, Wierzcholek(0), 10, D3DDP_DEFAULT) Zmieniamy też flagę na D3DPT_TRIANGLESTRIP, bowiem teraz naszą bryłę tworzymy z trójkątów. Tworzenie i nakładanie tekstury Teksturanie jest niczym innym jak "naciągniętą" bitmapą na powierzchnię bryły. Będziemy wykorzystywać jedynie bitmapy (pliki bmp), choć istnieje możliwość korzystania z innych formatów graficznych, jednak na razie nie wiem, jak je załadować na powierzchnię DirectDraw. Jeszcze jedna drobna uwaga: wymiary bitmapy powinny być (choć nie muszą) potęgami liczby 2, czyli np. 256x256 pikseli. Do naszego projektu dołożymy dodatkową procedurę, tworzącą teksturę: Public Sub CREATETEXTURE() '........... '........... End Sub Oczywiście dodajemy też jej wywołanie w funkcji main. Teksturę możemy tworzyć przed lub po stworzeniu wierzchołków bryły, ale oczywiście przed renderowaniem. Tak więc nasz main wygląda teraz tak: Public Sub MAIN() frmMain.Show step = 1 Call INIT Call GEOMETRY Call CREATETEXTURE Call RENDERLOOP Call ENDIT End Sub 'procedura inicjacji 'tworzenie wierzchołków 'tworzenie tekstury 'procedura renderowania 'procedura kończąca Deklarujemy też dodatkową zmienną - powierzchnię, która będzie przechowywała teksturę: Public tekstura As DirectDrawSurface7 'powierzchnia tekstury Teraz zajmiemy się właściwym stworzeniem tekstury. W procedurze CreateTexture deklarujemy zmienną opisu powierzchni DirectDrawSurface7: Dim TekstDesc As DDSURFACEDESC2 Ustawiamy flagi tego opisu, tak, aby można było potem opisać pole DDSD_CAPS: TekstDesc.lFlags = DDSD_CAPS Należy zaznaczyć, że tworzona powierzchnia będzie teksturą - ustawiamy odpowiednią flagę: TekstDesc.ddsCaps.lCaps = DDSCAPS_TEXTURE Mamy już gotowy opis. Wywołujac metodę CreateSurfaceFromFile z obiektu DirectDraw tworzymy teksturę z pliku bitmapy: Set tekstura = DD.CreateSurfaceFromFile(App.path & "/" & "1TeksturaD3D.bmp", TekstDesc) Na koniec musimy jeszcze ustawić teksturę na urządzeniu renderującym. Służy do tego odpowiednia metodą obiektu Direct3DDevice7: Device.SetTexture 0, tekstura Jako drugi parametr należy przekazać nazwę powierzchni przechowującej teksturę, zaś jako pierwszy 0. Spójrzmy na efekt naszej pracy. Na razie nie wygląda zbyt ciekawie. Po prostu musimy odpowiednio naciągnąć teksturę na naszą bryłę. Zasady przedstawia poniższy rysunek: Do ustawiania współrzędnej tekstury na wierzchołku służą parametry tu (odpowiada współrzędnej poziomej) oraz tv (współrzędnej pionowej). Tak więc procedurę geometrii należy zmodyfikować np. w ten sposób: Public Sub GEOMETRY() DX.CreateD3DLVertex 0, 10, 0, DX.CreateColorRGBA(0, 1, 0, 1), 1, 0.5, 0, Wierzcholek(0) DX.CreateD3DLVertex 0, -5, 10, DX.CreateColorRGBA(1, 1, 1, 1), 1, 1, 1, Wierzcholek(1) DX.CreateD3DLVertex 10, -5, 0, DX.CreateColorRGBA(1, 1, 1, 1), 1, 0, 1, Wierzcholek(2) DX.CreateD3DLVertex 0, -5, -10, DX.CreateColorRGBA(1, 0, 0, 1), 1, 1, 1, Wierzcholek(3) DX.CreateD3DLVertex -10, -5, 0, DX.CreateColorRGBA(1, 1, 0, 1), 1, 0, 1, Wierzcholek(4) DX.CreateD3DLVertex 0, -5, 10, DX.CreateColorRGBA(1, 1, 1, 1), 1, 1, 1, Wierzcholek(5) End Sub Jedynka we współrzędnych oznacza wykorzystanie całej długości bądź szerokości tekstury. Jesli chcemy skorzystać tylko z jej części, to współrzędna musi być mniejsza od jednego. A oto efekt naszej dotychczasowej pracy: Rozciągnięcie tekstury możemy zmieniać poprzez modyfikację współrzędnych tu i tv dla poszczególnych wierzchołków. Dzięki temu, można używać tylko fragmentu tekstury lub nałożyć ją kilka razy. Poniżej mamy przykład: Przemnożyliśmy każdą współrzędną przez 0.5 - uzyskaliśmy nałożenie tylko fragmentu tekstury, a przez to jej rozciągnięcie. Tutaj przemnożyliśmy każdą współrzędną przez 2. Uzyskaliśmy dwukrotne wklejenie tekstury wzdłuż każdej z osi współrzędnych. Oczywiście wartości tu i tv mogą być przemnażane niezależnie dla każdego wierzchołka - radzę poeksperymetować. Tryby adresowe tekstury (Texture adressing modes) Przemnóżmy każdą współrzędną tu i tv dla każdego wierzchołka przez 3. - ęłęóD3DTADDRESS_WRAP - to tryb domyślny (owijanie). Jego efekt widzieliśmy powyżej. - D3DTADDRESS_MIRROR - to efekt lustra. Jego działanie widzimy poniżej:ęłęó Jak widać każde kolejne nałożenie tekstury na ścianę jest lustrzanym odbiciem poprzedniego. W pojedyńczym pasie używane jest odbicie względem pionowej osi. Poszczególne pasy są odbijane wzdłuż poziomej osi. - D3DTADRESS_CLAMP - tryb "zaciskania" (jeśli dobrze przetłumaczyłem). Pomimo przemnażania wspólrzednych przez liczbę większą od 1, Direct3D ustawia pojedyńczą teksturę, zaś na pozostałej części bryły rozmazuje ją. Efekt widoczny poniżej na przykładzie kraty: tekstura (256x256) i jej nałożenie z użyciem trybu Clamp (w przykładzie współrzędne są przemnożone przez 2). Jest jeszcze czwarty tryb - D3DTADDRESS_BORDER, ale w chwili obecnej nie potrafię go użyć. Tryby ustawiamy za pomocą metody obiektu Direct3DDevice7: Device.SetTextureStageState 0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP gdzie ostatnim parametrem jest właśnie tryb adresowania tekstury. Tryby możemy także ustawiać niezależnie dla osi poziomej i pionowej. Wtedy jako drugi parametr w powyzszej metodzie należy przekazać stałą D3DTSS_ADDRESSU (dla osi X) lub D3DTSS_ADDRESSV (dla osi Y). Określanie zachowania się tekstury i wierzchołków Załóżmy, że nasza bryła ma jakieś kolorowe wierzchołki, np. czerwone. Po nałożeniu tekstury zobaczymy pewien kolor wynikowy, będący odpowiednim złożeniem koloru wierzchołków i koloru tekstury. Przykład widzimy poniżej: Dla porównania wierzchołki po prawej stronie mają kolor biały, aby można było zobaczyć faktyczny kolor tekstury. Domyślną operacją przy nakładaniu tekstury na bryłę jest przemnożenie kolorów tekstury przez koloy wierzchołków. Dzięki temu otrzymujemy pewien kolor wypadkowy. Dla operacji takiej potrzebne są dwa argumenty - domyślnie jest to kolor wierzchołków oraz kolor tekstury Pierwszy argument można określić w ten sposób: SetRenderState 0, D3DTS_COLORARG1, wartość Jako wartość najczęściej podstawiamy: D3DTA_DIFFUSE - argumentem jest kolor wierzchołków D3DTA_TEXTURE - argumentem jest kolor tekstury D3DTA_SPECULAR - argumentem jest kolor składowej odblasków zawarty w wierzchołkach Drugi argument można określić w podobny sposób, z tą różnicą, że w funkcji SetRenderStageState jako drugi argument ustawiamy D3DTS_COLORARG2. Pozostał jeszcze sposób operacji wykonywanej na tych argumentach. Pod pojęciem operacji kryją się działania logiczne na poszczególnych składowych kolorów (np. mnożenie: REDARG1*REDARG2, GREENARG1*GREENARG2, BLUEARG1*BLUEARG2). device.SetTextureStageState 0, D3DTSS_COLOROP, wartość Jako wartość stosujemy zwykle: D3DTOP_DISABLE - tekstura nie jest w ogóle brana pod uwagę. Przy ustawieniach domyślnych dla argumentów bryła będzie miała taki kolor jak wierzchołki D3DTOP_SELECTARG1 - pierwszy z argumentów zostanie przepisany bez zmian na wyjście. Oznacza to, że jeśli np. ustawiliśmy - pierwszy argument - kolor wierzchołków, żaś drugi - kolor tekstury, to bryła będzie miała wyłącznie kolor wierzchołków. Gdybysmy zrobili odwrotnie (argument1 = kolor tekstury, argument2 = kolor wierzchołków) to bryła będzie miała tylko kolor tekstury. Analogicznie jak dla D3DTOP_SELECTARG2 Przykład widzimy poniżej: Ustawienia wspólne dla obu obrazków device.SetTextureStageState 0, D3DTSS_COLORARG1, D3DTA_TEXTURE - pierwszym argumentem jest kolor tekstury device.SetTextureStageState 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE - drugim argumentem jest kolor wierzchołków device.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 (dla obrazka po lewo) device.SetTextureStageState 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 (dla obrazka po prawo) D3DTOP_MODULATE - jest to przemnożenie przez siebie argumentu pierwszego przez argument drugi. Wartość domyślna. Efekt dla czerwonych wierzchołkówi używanej wcześniej tekstury: D3DTOP_MODULATE2X - przemnożenie przez siebie pierwszego i drugiego argumentu i dodatkowo przemnożenie jeszcze wyniku przez 2. Dzięki temu zwiększa się jasność. D3DTOP_MODULATE4X - podobnie jak poprzednio, z tym, że teraz wykonujemy dodatkowo przemnożenie przez 4: D3DTOP_ADD - dodawanie logiczne poszczególnych składowych do siebie (czyli: składowa zielona arg1 OR składowa zielona arg2…): Jeśli coś wyszło poza zakres (tzn np. otrzymaliśmy kolor 1.2, 1.5, 1.1)to jest on przycinany to maksymalnej wartości, czyli do koloru białego (1.0, 1.0, 1.0). Efekt taki powstał na prawej stronie bryły. Istnieje jeszcze wiele innych flag - zapraszam do lektury DirectX7 SDK.