Wykład 4. Rendering (1) Informacje podstawowe
Z punktu widzenia dzisiejszego programowania gier: Direct3D jest najczęściej wykorzystywanym przez profesjonalnych deweloperów gier API graficznym na platformie Microsoft Windows jest de facto jedynym API graficznym na platformach konsolowych Microsoft XBox i XBox 360 OpenGL (i jego odmiany, np. OpenGL ES) jest multi-platformowy sterowniki OpenGLa istnieją dla prawie każdego hardwaru 3D jest nadal popularny wśród (na ogół niezawodowych) programistów gier na platformie Microsoft Windows jest standardem de facto na platformach Mac OSX i iphone, linuksowych (PC i wiele smart fonów), Nintendo, Sony Wniosek: Jeżeli tworzona gra jest przeznaczona na różne platformy, wówczas w silniku gry warto utworzyć warstwę abstrakcji renderera, która oddziela konkretne API graficzne od reszty modułów silnika.
Jednakże nawet w ramach konkretnego API bywają duże różnice w odniesieniu do jego poszczególnych wersji, które powodują, że w implementacji interfejsu renderera różne wersje danego API muszą być traktowane odrębnie. Z punktu widzenia przenoszenia gier na różne platformy, największą zmianą było odejście (w obydwu API) od wspierania postulatu wsteczniej kompatybilności. Zmiana ta odbyła się za sprawą usunięcia funkcjonalności stałego potoku graficznego (fixed-function pipeline) na rzecz potoku programowanego (programmable pipeline) przy użyciu shaderów. Nastąpiło to wraz z wprowadzniem wersji OpenGL 3.1 (odpowiednio OpenGL ES 2.0) oraz DirectX 10.
w stałym potoku poszczególne transformacje przekazywane są do potoku za pośrednictwem odpowiednich funkcji API i potok sam stosuje je do nadchodzących wierzchołków w programowalnym potoku OpenGL 2.0 jest prawie tak samo, za wyjątkiem faktu, że o zastosowanie transformacji do wierzchołków musimy zadbać sami w kodzie vertex shadera (transformacje są widoczne jako zmienne wbudowane) w programowalnych potokach OpenGL 3.0 i 4.0 oraz DirectX transformacje przekazywane są do vertex shadera po prostu jako jedne z jego możliwych parametrów (zmienne uniform OpenGL i DirectX 9 lub bufory stałych cbuffer DirectX 10 i 11)
DirectX OpenGL Aby przejść z jednego układu na drugi trzeba zastosować do wizualizowanego świata odbicie zwierciadlane w płaszczyźnie XY. Czasem należy również zmienić kierunek nawinięcia (winding) poligonów w siatkach na przeciwny (w przypadku, gdy stosowany jest backface culling) w celu określenia widocznej strony poligona. Domyślnie OpenGL uznaje poligony o nawinięciu przeciwnym do ruchu wskazówek zegara za ułożone przodem, zaś DirectX wprost przeciwnie.
Przestrzenią modelu (model space, local space) nazywany jest układ współrzędnych skojarzony bezpośrednio z danym modelem, zwykle w procesie modelowania. W konsekwencji, z każdym z modeli związany jest odrębny układ współrzędnych modelu, względem którego określone są wartości współrzędnych wierzchołków siatki wielokątów.
Współrzędne wierzchołków danego modelu określone w przestrzeni modelu przekształcane są do przestrzeni świata (world space, global space), która jest układem współrzędnych związanych z wizualizowaną sceną. Transformacja danego modelu do przestrzeni świata dokonywana jest przy użyciu związanego z tym modelem - przekształcenia świata (world transformation), które jest wyznaczane w procesie komponowania sceny i ew. aktualizowane na bieżąco w przypadku modelu dynamicznie przemieszczającego się po scenie (w przypadku modeli statycznych odwzorowanie jest stałe). Stały potok DirectX Stały potok OpenGL i programowalny OpenGL 2.0 (stos macierzy obecnie usunięty)
Następnie współrzędne wierzchołków przekształcane są do przestrzeni kamery (view space, camera space), która jest układem współrzędnych związanych z punktem położenia kamery (obserwatora) w świecie i kierunkiem jej patrzenia. Transformacja ta dokonywana jest przy użyciu związanego z kamerą - przekształcenia obserwatora (view transformation), które jest wyznaczane w procesie komponowania sceny i następnie aktualizowane na bieżąco gdy kamera przemieszcza się po scenie. Stały potok DirectX Stały potok OpenGL i programowalny OpenGL 2.0 (stos macierzy obecnie usunięty)
Ostrosłup widzenia (frustum) można rozpatrywać jako uproszczony model kamery. Jest on zdefiniowany przez: kąt widzenia (field of view) mierzony zwykle w pionie (fovy) przednią i tylną płaszczyznę obcinania stosunek szerokości do wysokości (aspect ratio) powierzchni (matrycy), na którą jest rzutowany obraz postrzegany przez kamerę
Na podstawie parametrów ostrosłupa widzenia konstruowane jest przekształcenie rzutowania perspektywicznego. 1. Przekształcenie to najpierw sprowadza przy użyciu macierzy rzutowania perspektywicznego - współrzędne wierzchołków w przestrzeni kamery do tzw. jednorodnej przestrzeni obcinania (homogeneous clip space, projection space), w której ma m.in. miejsce operacja obcinania wielokątów wzgl. ostrosłupa widzenia. 2. Następnie ma miejsce operacja dzielenia perspektywicznego współrzędnych wierzchołków, w wyniku której współrzędne te sprowadzane są do układu znormalizowanych współrzędnych urządzenia (NDC). Stosując standardową macierz rzutowania konkretnego API otrzymamy: a. współrzędne x i y [-1, 1] b. współrzędna z [-1, 1] w OpenGL oraz z [0, 1] w DirectX. Stały potok DirectX Stały potok OpenGL i programowalny OpenGL 2.0 (stos macierzy obecnie usunięty) W celu ujednolicenia NDC w zakresie współrzędnej z, przenośny silnik graficzny powinien sam konstruować odpowiednią macierz rzutowania (tzn. nie korzystając z powyższych funkcji API).
W ostatniej fazie potoku przekształceń współrzędne wierzchołków przekształcane są przy wykorzystaniu transformacji widoku (viewport transformation) w celu wyświetlenia we wskazanym prostokątnym obszarze (viewport) okna. Okno może posiadać kilka widoków, np. ukazujących obraz sceny z różnych kamer. DirectX 9 (DirectX 10 i 11 podobnie funkcje RSSetViewports() interfejsów, odpowiednio, ID3D10Device i ID3D11DeviceContext OpenGL
Podstawowe zasoby, które powinien obsługiwać renderer to: geometria wyrażana jest w języku wierzchołków i ich atrybutów (położenie, kolor, normalne, współrzędne tekstur,...) i reprezentowana przez bufory wierzchołków i indeksów współczynniki globalne materiałów opisują globalne właściwości optyczne danej geometrii istotne z punktu widzenia interakcji ze światłem (współczynnik rozproszenia, współczynnik odbicia, etc.) tekstury opisują lokalne właściwości optyczne danej geometrii shadery definiują sposób działania programowalnych części potoku graficznego stany renderingu (render states) określają parametry i właściwości nieprogramowalnych części potoku graficznego, które można zmieniać (mieszanie i test alfa, włączanie i wyłączanie z-bufora, backface culling,...) współczynniki globalne, tekstury, shadery i stany renderingu często wykorzystywane są łącznie do zdefiniowania materiału. światła kamery (i skojarzone z nimi widoki - viewports) bufory renderingu (render targets) - bufor kolorów, z-bufor, stencil bufor,... fonty...