Bez ograniczeń prędkości


Łączmy się w... Trójkąty

Gdy zakończona zostanie faza transformacji i oświetlenia, nadchodzi czas na kolejny ważny etap. Współrzędne poszczególnych wierzchołków zostają przesłane do jednostki zajmującej się triangularyzacją, czyli łączeniem wierzchołków w trójkąty. To właśnie trójkąty będą stanowiły szkielet sceny 3D, na który później nałożone zostaną tekstury.

Każdy wierzchołek trójkąta ma przypisane trzy współrzędne, opisujące jego położenie w przestrzeni.

Scena jest, oczywiście, tym bardziej szczegółowa, im większej liczby wierzchołków - a zatem i trójkątów - można użyć do jej opisania. Trudno zweryfikować deklaracje producentów w tym zakresie, ale mimo wszystko warto je przytoczyć, aby mieć pewne wyobrażenie o potencjalnej złożoności obrazu 3D. ATI deklaruje, że wbudowana w układ Radeon jednostka T&L jest w stanie obsłużyć 30 milionów trójkątów na sekundę. Jeśli założymy, że w tym czasie powinniśmy wyświetlić 60 klatek, wówczas jedna scena może się składać maksymalnie z 500 tysięcy trójkątów. GeForce 2 GTS z wynikiem 25 milionów trójkątów na sekundę jest niewiele gorszy. Dla porównania, układ graficzny zastosowany w konsoli PlayStation, która pojawiła się na rynku w 1995 roku, potrafi obsłużyć pół miliona trójkątów. Jak widać, w ostatnich latach dokonał się znaczący postęp.

Teksturujemy świat

Mamy zatem scenę 3D, składającą się z obiektów zbudowanych z trójkątów. Dla poszczególnych wierzchołków zostało obliczone oświetlenie. Obraz wciąż jednak nijak się nie ma do rzeczywistości - brakuje mu tekstur, które odwzorowywałyby fakturę powierzchni obiektów.

Teksturowanie jest jednym z najważniejszych etapów renderowania sceny i właśnie tutaj widać wyraźnie, jaki postęp dokonał się w dziedzinie akceleratorów 3D w ostatnich latach.

Tekstura to zazwyczaj płaska mapa bitowa, której odpowiedni fragment zostaje wycięty i nałożony na siatkę trójkątów tworzących obiekt 3D. Porównać to można do pakowania prezentu w ozdobny papier - w podobny sposób obiekty są owijane teksturami.

Niestety, tekstury, które mają ściśle określone rozmiary (na przykład 32x32 bądź 128x128 pikseli) prawie nigdy nie odpowiadają pod względem rozmiarów teksturowanym trójkątom. Wiadomo przecież, że w scenie o dużym stopniu złożoności trójkąty mogą mieć rozmiary nawet 1 piksela, podczas gdy w prostych scenach wystarczy kilka bardzo dużych trójkątów. Konieczność tak znacznego skalowania tekstur negatywnie odbiłaby się na wydajności karty graficznej i bardzo wyraźnie pogorszyłaby jakość obrazu. Aby tego uniknąć, opracowano mechanizm mapowania tekstur (ang. mip mapping).

Ideą mechanizmu jest przygotowanie tej samej tekstury w kilku rozmiarach, przy czym każda kolejna ma boki dwa razy dłuższe od poprzedniej. Jeśli więc najmniejsza tekstura ma rozmiary 8x8 pikseli, kolejne będą miały odpowiednio 16x16, 32x32, 64x64 piksele.

Dzięki takiemu rozwiązaniu możliwe jest dobranie rozmiaru tekstury najbardziej zbliżonego do wielkości trójkąta. Unika się w ten sposób absurdalnych sytuacji, gdy system musi przeskalować teksturę o rozmiarach 256x256 pikseli, aby pokryć nią trójkąt składający się z 3 pikseli.

Zastosowanie mapowania MIP wciąż nie rozwiązuje jednak problemu dokładnego dopasowania rozmiarów tekstury do rozmiarów trójkąta. Powodem jest to, że nawet jeśli przygotuje się teksturę w ośmiu rozmiarach (co jest standardem w mapowaniu MIP), nie sposób uwzględnić wszystkich możliwych rozmiarów trójkątów składających się na obiekty 3D.

Wielu czytelników pamięta jeszcze na pewno pierwsze gry FPP, takie jak Doom. Pozwalały one wyraźnie zaobserwować opisywany problem - ściany pokryte teksturami wyglądały dobrze, gdy gracz znajdował się w ściśle określonej odległości od nich. Gdy zaczynał się zbliżać, piksele się powiększały, przybierając postać dużych, mało estetycznych kwadratów.

Działo się tak, ponieważ w razie potrzeby (gdy trójkąt był większy od tekstury) poszczególne piksele tekstury powielano tyle razy, ile było trzeba, żeby pokryć nią całą powierzchnię. Skutkiem takiego zwielokrotnienia był właśnie efekt opisywany często jako "pikseloza".

Sytuację poprawiło zastosowanie filtrowania dwuliniowego. Postęp polegał na tym, że kolor każdego punktu teksturowanego obiektu wyliczano na podstawie interpolacji 4 sąsiadujących ze sobą punktów tekstury. Dzięki temu udało się zlikwidować efekt olbrzymich pikseli, które się pojawiały przy zbliżeniach obiektów 3D. Efekt jednak nie był jeszcze doskonały - interpolacja sprawiała, że obraz przy zbliżeniach stawał się wyraźnie rozmyty. Poza tym przejścia między kolejnymi poziomami MIP były zbyt wyraźne. Wprawdzie postęp był oczywisty w stosunku do próbkowania punktowego (stosowanego w Doomie), ale pojawiło się jeszcze doskonalsze rozwiązanie, czyli filtrowanie trójliniowe.

W tej technice do interpolacji tekstur nakładanych na trójkąty używa się nie 4 jak w wariancie dwuliniowym, a 8 tekseli, - 4 z tekstury mniejszej od trójkąta i 4 z tekstury większej od niego. Po uśrednieniu wynik tych dwóch interpolacji wyznacza kolor poszczególnych punktów teksturowanego obiektu.

Zdecydowanie najbardziej zaawansowaną techniką filtrowania, ale jednocześnie wymagającą największej mocy obliczeniowej, jest filtrowanie anizotropowe. Bierze pod uwagę największą liczbę tekseli (ponad 8), a do tego uwzględnia ich orientację w przestrzeni, dzięki czemu obszary, z których interpolowane są wartości nałożonej tekstury, przybierają nieregularne kształty (w przypadku teksturowania dwu- i trójliniowego są to zawsze romby).

Zupełnie już dzisiaj oczywistą operacją jest również korekcja perspektywy nakładanych tekstur, która pozwala uniknąć niepożądanych efektów, takich jak załamania tekstury albo jej znikanie (na przykład w scenach ze schodami albo długim tunelem).