Kamil Nowakowski 2011
Zaprezentowane materiały pochodzą z silnika: Oraz z projektu :
Czym jest grafika 3D nowoczesny sposób przedstawienia świata rzeczywistego. Odwzorowanie struktury obiektów, kolorów, światła i zjawisk optycznych przy użyciu komputera. Grafika 3D speed up czyli realtime rendering. Dzięki coraz to potężniejszym kartom dedykowanym grafice 3D ( od zewnętrznego procesora dysku na C64 po najnowsze potwory GeForce ). Przeniesienie pełni mocy obliczeń na sprzęt.
Realtime = tricki i oszustwa. Nie da się ( przynajmniej na znanej obecnie technologii ) zasymulować pełni fizyki optyki dla generowania obrazu czasu rzeczywistego ( co najmniej 30 fps ). Stosuje się szereg kruczków, aby oszukać obserwatora ( o tym przy optymalizacji ). Ruchomy obraz 3D lets put some fun in it. Całą obecną uwagę rynku gier kieruje się na technologie grafiki 3D ( wraz z stereoskopią true 3D ). Rynek gier napędza rynek kart. Wzajemne wymogi technologiczne.
Programowa jak i designerska grafika 3D jest w 100% oparta na matematyce i abstrakcyjnych formach prezentowania rzeczywistości. Trzeba patrzeć jak Architekt w Matrixie. Programista 3D żyje w świecie macierzy i vertexów.
Silnik jest mechanizmem do budowania środowiska 3D tak, jak tego zechce twórca. Silnik ma zarządzać wszystkimi aspektami gry. Zbiór narzędzi i komponentów.
Ładowanie modeli i tekstur Dźwięków, filmów, mapy Interakcje z obiektami Fizyka środowiska Sztuczna inteligencja Wymiana sieciowa
Kilka najczęściej wykorzystywanych technik oszukania obserwatora:
To co widzimy na ekranie jest jednym wielkim oszustwem ;) Jednak ma to na celu coś więcej jak tylko uproszczenie sobie sprawy. Taka reprezentacja przestrzeni 3D jest efektywna w obliczeniach i pozwala na szybki rendering. Dodatkowo stosuje się techniki jeszcze bardziej przyspieszające generowanie sceny.
Szczególnie w grach duże znaczenie ma płynność grafiki. Nikt nie będzie chciał grać w pokaz slajdów. Od płynności zależy komfort dostarczanej rozrywki. Prócz wcześniejszych uproszczeń stosuje się takie metody ( od najprostszych po te bardziej zaawansowane ).
Czyli odrzucanie elementów poza widokiem
Skoro nie widać różnicy, to po co przepłacać?? Trapez widoczności: FOV, znear, zfar
Zamiast badać każdy obiekt na scenie, można je pogrupować w paczki. Np. : Segment Paczka Obiekt Oszczędza to bardzo wielu zbędnych obliczeń. Drzewo binarne ( gęstości obiektów ), AABB, OBB, heurystyka algorytmu.
Rozpoznawanie, czy obiekt jest zasłonięty przez coś. Jak tak, to czy jest sens go renderować? NIE!
Idea bardzo chwalebna. Wyrzuca ze sceny wszystkie obiekty, których obserwator nie widzi.
Wady i kłopoty : Problemy w implementacji. Dość trudno jest oprogramować OC. Oraz metoda wyciągania informacji o zasłonięciu obiektu jest kosztowna. Hardware OC wymaga dodatkowego render passu z uwzględnieniem wstępnego posortowania modeli wg odległości.
Umiejętne zaprogramowanie i optymalizacja OC ( mieszając go z frustrum i AABB/OBB ) daje znaczący wzrost wydajności sceny im mniej trójkątów, tym karta mniej się poci. Przygotowanie elementów Test frustrum culling Occlusion culling Wyciąganie wyników Budowanie sceny Rendering
Zmniejszanie szczegółowości geometrii modelu wraz z dystansem. Obserwator nie dostrzega z daleka drobnych elementów, po co jest więc zajmować nimi kartę graficzną?
Analogicznie do geometrii, zmniejszamy rozdzielczość tekstur.
Im mniejszą powierzchnię na ekranie zajmuje trójkąt geometrii, tym wybieramy coraz dalszą mipmapę ( gorsczej rozdzielczości ). Wadą mogą być zbyt rozmazane horyzontalne tekstury. Stosuje się filtry anizotropowe.
Oprócz zwykłych kwadratowych mipmap oryginalnej tekstury stosuje się dodatkowe zeskalowane w daną stronę mapy :
Innymi słowy na jedną klatkę sceny 3D składa się wiele wstępnych renderingów:
Technika polegająca na wyrenderowaniu sceny w osobnym cyklu i zapisania geometrii jako tekstura zawierająca położenie i zwrot płaszczyzn. Lub też z wykożystaniem technologi MRT ( Multi Render Targets ) Głównie stosowana w procesie oświetlania sceny. Pozwala na dynamiczne zarządzanie tysiącami świateł. To nie obiekt jest oświetlany, tylko światło oświetla.
Technika dodawania szczegółów do modelu poprzez dodanie dodatkowej tekstury nierówności normal mapy.
Aby móc dodać cienie do sceny najczęściej wykorzystuje się dodatkowy render pass jako shadow mapping. Zapis sceny z punktu widoku źródła światła jako mapa głębi. Rozpoznawanie czy miejsce jest zacienione, poprzez sprawdzenie głębi obiektu w punkcie a głębi na shadow mapie. Niesamowite podniesienie realizmu grafiki.
Różne techniki : 1. Variance SM 2. PSM ( rozmycie gaussa ) 3. CSM ( Cascaded Shadow Maps ).
Post coś na końcu. Ogólne poprawianie parametrów obrazu. Bloom, HDR, Motion Blur, SSAO, Global Illumination, God Rays, DOF
Dynamiczne chmury Scattering atmosferyczny Realistyczna woda
Generowanie programowo tekstur. 3 tekstury 256x256, każdy 3 kanały RGB osobno. 9 niezależnych layerów chmur. Miksowanie kanałów i barwienie.
Refrakcje Aberracja chromatyczna Odbicia Fale
Kierunkowe rozmycie obrazu spowodowane szybko poruszającymi się obiektami. Motion blur jest fajny przy grach z narzuconym niskim fps w okolicach 30. Efekt kinowości.
Przypinanie tych obiektów do dynamicznych przedmiotów np. pochodnia w ręce postaci.
Przechodzimy do kwestii stricte programowania grafiki 3D. Mamy pomysł, ale jak to zrealizować?
Każde ma swoje wady i zalety. Wszystko ma inną implementację niemożliwa przenośność kodu albo jedno albo drugie * W obu osiągniesz ten sam efekt, ale inną drogą.
Siada sobie programista do kodu i skleja trójkąty :
glbindtexture( GL_TEXTURE_2D, jakiś ID ); glcolor3ub( 255, 128, 75 ); glenable( GL_BLENDING ); glclear( GL_COLOR_BIT_BUFFER );
glloadidentity(); glpushmatrix() ; glpopmatrix(); gltranslatef( x, y, z ); glrotatef( R, x, y, z ); glscalef( x, y, z );
Shadery są to programy pisane z myślą o przetwarzaniu geometrii oraz pikseli renderowanych przez karty graficzne.
Vertexy ( x, y, z ) Pamięć systemowa Vertex Shader Vertex Processing Pamięć karty graficznej Pixel Shader Pixel Processing Pamięć tekstur Piksele ( R, G, B, A ) Framebuffer
varying vec3 col; varying vec2 coord; void main(){ gl_position = ftransform(); col = vec3( 1.0, 0.0, 1.0 ); coord = gl_multitexcoord0; } varying vec3 col; varying vec2 coord; uniform sampler2d T; void main(){ Vec3 c = texture2d(t,coord); gl_fragcolor.rgb = col * c; }
Dziękuje za uwagę. Pytania?