RENDERING W CZASIE RZECZYWISTYM Michał Radziszewski
Plan wykładu Programy geometrii wprowadzenie Miejsce w potoku graficznym Wejścia i wyjścia programów geometrii Wierzchołki, prymitywy, ich nowe rodzaje Warstwy i widoki Funkcje specyficzne dla programów geometrii Wydajność programów geometrii Programy geometrii a programy wierzchołków Dodawanie i usuwanie wierzchołków
Plan wykładu c.d. Obliczanie normalnych i stycznych Zamiana typu prymitywów Rendering siatki na tle modelu Współpraca z programem fragmentów Rendering sylwetek obiektów Cienie wolumetryczne po raz drugi Odczyt wyniku transformacji Ang. transform feedback
Literatura Programy geometrii są zagadnieniem bardziej technicznym, niż naukowym praktycznie nie ma prac naukowych na ich temat Pozostaje specyfikacja OpenGL, podręczniki, tutoriale F. Diard, Using the Geometry Shader for Compact and Variable-Length GPU Feedback, GPU Gems 3, Addison-Wesley Professional, 2007
Programy geometrii wprowadzenie Programy operujące na prymitywach (trójkąty, paski/wachlarze trójkątów, linie, punkty, ) W przeciwieństwie do programu wierzchołków, mają do dyspozycji pełną informacje o wszystkich wierzchołkach danego prymitywu jednocześnie Programy geometrii mogą też dodawać i usuwać wierzchołki, a także zmieniać typ prymitywów Umożliwiają rendering do kilku warstw tekstury jednocześnie nieznaczna poprawa wydajności
Programy geometrii wprowadzenie Pozwala to na wiele różnorodnych efektów, nieosiągalnych bez programów geometrii Względnie nowa technologia (przełom 2006/2007) Obecnie wydane gry na ogół z niej nie korzystają, ale prawdopodobnie niedługo się to zmieni Dostępne jako rozszerzenie od wersji OpenGL 3.0 Dostępne w wersji podstawowej od OpenGL 3.2 Dostępne w DirectX od wersji 10.0
Programy geometrii wprowadzenie
Miejsce w potoku graficznym Programy geometrii wykonywane są bezpośrednio po programach wierzchołków a przed programami fragmentów Wyjścia programu wierzchołków są bezpośrednio przekazywane do programu geometrii Pomiędzy programem geometrii a programem fragmentów jest jeszcze przetwarzanie danych przez kartę graficzną, identyczne jak bez programu geometrii
Miejsce w potoku graficznym Program fragmentów dostaje dane wejściowe od programu geometrii, dokładnie w ten sam sposób w jaki dostawałby je od programu wierzchołków Zatem program fragmentów jest niezależny od tego, czy współpracuje z programem geometrii, czy nie Zawsze dostaje wartości interpolowane pomiędzy wierzchołkami, w zależności od jedynie od trybu interpolacji
Miejsce w potoku graficznym
Wejścia i wyjścia programów geometrii Podstawowym wejściem i wyjściem programów geometrii są informacje o prymitywach Programy geometrii operują na konkretnym typie prymitywów wejściowych i wyjściowych Typy te są ustawiane niezależnie Muszą zostać określone na etapie pisania programu Komendy layout(prim) in; oraz layout(prim) out; Specyfikacja ta musi być umieszczona na początku programu, na zewnątrz jego funkcji
Wejścia i wyjścia programów geometrii Dopuszczalne wejściowe typy prymitywów Punkty (prim.: points) Linie (prim.: lines) Linie z sąsiedztwem (prim.: lines_adjacency) Trójkąty (prim.: triangles) Trójkąty z sąsiedztwem (prim.: triangles_adjacency) Dla linii i trójkątów (z sąsiedztwem i bez) aplikacja może renderować linie, trójkąty i ich paski (odpowiednio z sąsiedztwem i bez)
Wejścia i wyjścia programów geometrii Dopuszczalne wyjściowe typy prymitywów Paski linii (prim.: line_strip) Paski trójkątów (prim.: triangle_strip) Tylko takie prymitywy wyjściowe są dostępne Programy geometrii nie obsługują wachlarzy trójkątów (GL_TRIANGLE_FAN)
Wejścia i wyjścia programów geometrii
Wejścia i wyjścia programów geometrii
Wejścia i wyjścia programów geometrii Wszystkie wbudowane informacje o prymitywach (ich wierzchołkach) dostępne są w tablicy gl_in[] Ilość wpisów w tej tablicy odpowiada ilości wierzchołków prymitywu gl_clipdistance[], gl_pointsize, gl_position Wszystkie pozostałe informacje są przekazywane podobnie jak pomiędzy programem wierzchołków i fragmentów, z tym że w programie geometrii dostępne są one jako tablice
Wejścia i wyjścia programów geometrii Program geometrii może być wykonywany wielokrotnie dla tych samych prymitywów wejściowych Komenda: layout(invocations=n); Jeżeli ilość wywołań nie jest wyspecyfikowana, to program zostanie wywołany raz dla każdego prymitywu Numer wywołania dostępny jest za pomocą zmiennej gl_invocationid (typu int)
Wejścia i wyjścia programów geometrii Dostępna jest wbudowana zmienna określająca numer prymitywu gl_primitiveidin Prymitywy numerowane są od zera, w ramach każdego wywołania gldraw* Jeżeli rendering obiektu składa się z więcej niż jednego wywołania gldraw*, to numery nie będą unikatowe Zmienna analogiczna do gl_vertexid z programu wierzchołków
Wejścia i wyjścia programów geometrii W przypadku renderingu do tekstury program geometrii może skierować rendering do wybranej warstwy lub widoku Warstwy tekstury to ściany tekstury sześciennej albo kolejne elementy tekstury tablicowej albo kolejne warstwy głębi tekstury wolumetrycznej Wybór warstwy odbywa się poprzez zapisanie odpowiedniej wartości do zmiennej wbudowanej gl_layer, (albo gl_viewport dla widoku)
Wejścia i wyjścia programów geometrii Taki zapis musi być wykonany przed wywołaniami EmitVertex() dotyczącymi prymitywu, który jest aktualnie generowany Program geometrii może w jednym przebiegu wygenerować różne prymitywy (niekoniecznie o różnych wierzchołkach) na różne warstwy (widoki) Przy pomocy jednego wywołania gldraw* można wypełnić np. sześcienną mapę cienia Mniej pracy CPU, niestety tyle samo pracy GPU
Funkcje specyficzne dla programów geometrii EmitVertex() Wywoływana na zakończenie tworzenia wierzchołka Wszystkie niezbędne dane muszą być zapisane do rejestrów wyjściowych Wygenerowany wierzchołek ma parametry równe bieżącym wartościom rejestrów wyjściowych Po wywołaniu zawartość rejestrów wyjściowych jest niezdefiniowana trzeba je odtworzyć nawet jeżeli nowy wierzchołek ma pewne atrybuty takie same
Funkcje specyficzne dla programów geometrii EndPrimitive() Kończy tworzenie prymitywu i zaczyna tworzenie nowego Wszystkie kolejne wywołania EmitVertex() dotyczą następnego prymitywu Niekonieczne jeżeli program geometrii tworzy tylko jedną figurę Funkcje EmitStreamVertex() i EndStreamPrimitive() analogiczne, ale dla wielu strumieni wyjściowych
Wydajność programów geometrii Dla optymalnej wydajności programów GPU z zastosowaniem programów geometrii istotne są: Optymalne rozdzielenie pracy pomiędzy program wierzchołków a program geometrii Maksymalnie ograniczona ilość prymitywów generowana przez program geometrii
Wydajność programów geometrii Optymalne rozdzielenie pracy pomiędzy program wierzchołków a program geometrii Ze względu na możliwości przetwarzania program geometrii mógłby zastąpić program wierzchołków Nie byłoby jednak to optymalne karta graficzna posiada pamięć cache dla przetworzonych wierzchołków, która minimalizuje ilość ponownych obliczeń dla tych samych wierzchołków Optymalizacja siatki wierzchołki współdzielone między trójkątami powinny być indeksowane przez indeksy będące możliwie blisko siebie
Wydajność programów geometrii Optymalne rozdzielenie pracy pomiędzy program wierzchołków a program geometrii c.d. Najlepiej wszystkie obliczenia, które nie wymagają więcej niż jednego wierzchołka jednocześnie wykonać w programie wierzchołków Program geometrii wykona te same obliczenia wielokrotnie nawet jeżeli wierzchołek jest współdzielony Optymalizacja siatki w takim przypadku nic nie da
Wydajność programów geometrii Maksymalnie ograniczona ilość wierzchołków generowana przez program geometrii Musi zostać wyspecyfikowana przez komendę layout(max_vertices=n) out; Program geometrii może wygenerować mniej wierzchołków, niż wynika to z deklaracji, ale nie może wygenerować więcej Na wydajność ma wpływ wartość zadeklarowana, a nie ilość rzeczywiście wygenerowanych wierzchołków
Wydajność programów geometrii Maksymalnie ograniczona ilość wierzchołków generowana przez program geometrii c.d. Karta graficzna musi zachować kolejność renderowanych prymitywów Konieczność przydziału pamięci na wszystkie wierzchołki możliwe do wygenerowania Ograniczenie maksymalnej ilości równoległych wywołań programu geometrii to najbardziej obniża wydajność
Wydajność programów geometrii Programy geometrii często stosowane są do zwielokrotniania ilości trójkątów w modelach Podejście takie działa dobrze dla prostych modeli testowych Niestety, ze względu na wydajność, jest bezużyteczne dla bardziej złożonych scen Do takich zastosowań służy program teselacji, użycie programu geometrii jest błędem!
Obliczanie normalnych i stycznych Dysponując pełną informacją o wierzchołkach prymitywu, program geometrii może obliczyć normalne i styczne Niestety, rezultatem takich obliczeń będzie cieniowanie płaskie (flat shading) Brak uśredniania wektorów T, B i N dla sąsiednich trójkątów Niestety prymitywy z sąsiedztwem nie rozwiązują problemu potrzebne są informacje o wszystkich prymitywach współdzielących dany wierzchołek
Zamiana typu prymitywów Program geometrii może przyjmować prymitywy jednego typu (np. punkty), a generować prymitywy innego typu (np. paski trójkątów) Za pomocą tej możliwości można napisać bardziej wydajny system cząsteczkowy Aplikacja przekazuje do karty graficznej jedynie pojedyncze punkty, i w razie potrzeby kierunki w górę, (a nie cztery wierzchołki czworokątów) Program geometrii generuje czworokąty (przy pomocy pasków trójkątów) zwrócone do obserwatora
Rendering siatki na tle modelu Aby wykonać rendering siatki na tle modelu bez programu geometrii, obiekt trzeba renderować dwukrotnie raz normalnie wszystkie jego prymitywy, i drugi raz siatkę Dwukrotne wykonanie programu wierzchołków Problem z wartością przesunięcia głębi Program geometrii we współpracy z programem fragmentów potrafi wyrenderować taką siatkę w jednym przebiegu
Rendering siatki na tle modelu Program geometrii generuje paski złożone z pojedynczych trójkątów Dodatkowy atrybut typu vec3 dla każdego wierzchołka Program geometrii zapisuje do niego wartości (0, 0, 1), (0, 1, 0) i (1, 0, 0) dla trzech wierzchołków, w dowolnej kolejności
Rendering siatki na tle modelu W programie fragmentów atrybut ten interpolowany jest pomiędzy wierzchołkami Dla każdego komponentu x, y i z w jednym wierzchołku jest wartość 1, w pozostałych 0 Dla każdego komponentu wartość 1 jest w innym wierzchołku Dwa zera wyznaczają krawędź jej szerokość można określić na stałą wartość w przestrzeni ekranu za pomocą pochodnych
Rendering siatki na tle modelu
Rendering sylwetek obiektów Podobnie jak rendering siatki Dodatkowo wykrywanie krawędzi tworzących sylwetkę Konieczność renderingu trójkątów z sąsiedztwem Jeżeli dwa trójkąty współdzielące krawędź są zwrócone jeden tyłem, a drugi przodem do obserwatora, to taka krawędź należy do sylwetki Tylko takie krawędzie należą do sylwetki
Rendering sylwetek obiektów Rendering tylko krawędzi należących do sylwetki Jeżeli dana krawędź nie należy do sylwetki, to do odpowiednich komponentów dla odpowiednich wierzchołków dodatkowego atrybutu należy wpisać jedynki W takim przypadku program fragmentów odczyta same jedynki i pominie rendering danej krawędzi
Rendering sylwetek obiektów
Cienie wolumetryczne Przypomnienie: podstawowy algorytm cieni wolumetrycznych Dokładne omówienie algorytmu wykład o renderingu cieni Wszystkie trójkąty sceny tworzą obcięte ostrosłupy z wierzchołkiem w pozycji światła trzy czworokąty na każdy trójkąt Rendering tak utworzonej geometrii zajmuje bardzo dużo czasu GPU, co jest podstawową, i jedyną, wadą cieni wolumetrycznych
Cienie wolumetryczne
Cienie wolumetryczne Stosując programy geometrii można bardzo łatwo wykryć krawędzie stanowiące sylwetkę obiektu Jeżeli tylko takie krawędzie będą generować czworokąty, to zasada działania algorytmu nie ulegnie zmianie, a rendering będzie wykonany znacznie szybciej Poza tym czworokąty (jako paski dwóch trójkątów) można generować przy pomocy programu geometrii, a nie CPU, przekazując na wejście oryginalną siatkę obiektu
Odczyt wyniku transformacji Wierzchołki są przetwarzane przez programy wierzchołków, i opcjonalnie geometrii Zamiast przesłać wierzchołki po przetworzeniu do dalszego renderingu, można zapisać ich parametry w buforze Tzw. funkcjonalność Transform Feedback Wierzchołki można przetwarzać w ten sposób wielokrotnie algorytmy iteracyjne
Odczyt wyniku transformacji Zastosowanie programów geometrii można dodawać i usuwać wierzchołki, zmieniając ilość danych w buforze Technika ta może być stosowana do obliczeń ogólnego przeznaczenia Nie można otrzymać wynikowej tablicy o nieokreślonej z góry ilości elementów za pomocą renderingu pełnoekranowego czworokąta
Odczyt wyniku transformacji
Dziękuję za uwagę