Bufor szablonu
Bufor wzornika który to dodatkowy bufor danych , oprócz bufora kolorów i bufora Z , można znaleźć w nowoczesnym sprzęcie graficznym . Bufor przypada na piksel i działa na całkowitych , zwykle z głębokością jednego bajta na piksel. Bufor Z i bufor wzornika często dzielą ten sam obszar w pamięci RAM sprzętu graficznego.
W najprostszym przypadku bufor szablonu służy do ograniczenia obszaru renderowania (szablonu). Bardziej zaawansowane użycie bufora szablonu wykorzystuje silne połączenie między buforem Z a buforem szablonu w potoku renderowania . Na przykład wartości wzornika mogą być automatycznie zwiększane/zmniejszane dla każdego piksela, który nie przejdzie lub pomyślnie przejdzie test głębi.
Prosta kombinacja testu głębi i modyfikatorów szablonów umożliwia ogromną liczbę efektów (takich jak objętości cieni szablonu, szablon dwustronny, komponowanie, kalkomania, rozpuszczanie, zanikanie, przesuwanie, sylwetki, rysowanie konturów lub podkreślanie przecięć między złożonymi prymitywami ), chociaż często wymagają kilku przebiegów renderowania i dlatego mogą mocno obciążać sprzęt graficzny.
Najbardziej typowym zastosowaniem jest nadal dodawanie cieni do aplikacji 3D . Jest również używany do płaskich odbić.
Inne techniki renderowania, takie jak renderowanie portalowe , używają bufora wzornika w inny sposób; na przykład można go użyć do znalezienia obszaru ekranu zasłoniętego przez portal i prawidłowego ponownego renderowania tych pikseli.
Dostęp do bufora wzornika i jego modyfikatorów można uzyskać w grafice komputerowej za pomocą interfejsów API, takich jak OpenGL , Direct3D lub Vulkan .
Architektura
Bufor wzornika zwykle dzieli tę samą przestrzeń pamięci co bufor Z, a zazwyczaj stosunek wynosi 24 bity dla bufora Z + 8 bitów dla bufora szablonu lub, w przeszłości, 15 bitów dla bufora Z + 1 bit dla bufora szablonu . Innym wariantem jest 4 + 24, gdzie 28 z 32 bitów jest używanych, a 4 ignorowane. Wzornik i bufory Z są częścią bufora ramki, połączonego z buforem kolorów. Pierwszym chipem dostępnym na szerszym rynku był Permedia II firmy 3Dlabs, który obsługiwał jednobitowy bufor szablonu.
Bity przydzielone do bufora szablonu mogą być użyte do reprezentowania wartości liczbowych z zakresu [0, 2 n -1], a także jako macierz logiczna (n to liczba przydzielonych bitów), z których każdy może być użyty do sterowania konkretna część sceny. Możliwa jest również dowolna kombinacja tych dwóch sposobów wykorzystania dostępnej pamięci.
Test szablonowy
Test szablonu lub szablonowanie jest jedną z operacji na pikselach/fragmentach (operacje na piksel), znajdujących się po teście alfa i przed testem głębi . Test szablonu gwarantuje, że niepożądane piksele nie dotrą do testu głębi. Oszczędza to czas przetwarzania sceny. Podobnie test alfa może uniemożliwić odpowiednim pikselom dotarcie do testu szablonu.
Sam test jest przeprowadzany na buforze szablonu do pewnej wartości w nim lub zmieniany lub używany i przeprowadzany za pomocą tak zwanej funkcji szablonu i operacji szablonu. Funkcja wzornikowa to funkcja, za pomocą której wartość wzorcowa określonego piksela jest porównywana z daną wartością odniesienia. Jeśli to porównanie jest logicznie prawdziwe , test szablonu kończy się pomyślnie. Inaczej nie.
W ten sposób możliwa reakcja spowodowana wynikiem porównania trzech różnych buforów stanu i bufora szablonu:
- Test szablonu nie został zaliczony
- Test szablonu jest pomyślny, ale nie test głębokości
- Oba testy są pomyślne (lub test szablonu jest pomyślny, a głębokość nie jest włączona)
Dla każdego z tych przypadków można ustawić różne operacje na badanym pikselu. W funkcjach wzornika OpenGL odpowiednio wartość odniesienia i maska definiują funkcję glStencilFunc. W Direct3D każdy z tych komponentów jest dostosowywany indywidualnie przy użyciu metod SetRenderState, którymi obecnie sterują urządzenia. Ta metoda oczekuje dwóch parametrów, z których pierwszy jest ustawionym warunkiem, a drugi jego wartością. W podanej powyżej kolejności warunki te noszą nazwy D3DRS_STENCILFUNC, D3DRS_STENCILREF i D3DRS_STENCILMASK.
Operacje na szablonach w OpenGL dostosowują funkcję glStencilOp, która oczekuje trzech wartości. Ponownie w Direct3D każdy stan ustawia określoną metodę SetRenderState. Trzy stany, które można przypisać do operacji, to D3DRS_STENCILFAIL, D3DRENDERSTATE_STENCILZFAIL i D3DRENDERSTATE_STENCILPASS.
Administracja
Chociaż zakres zastosowań buforów szablonowych jest dość szeroki, możemy wymienić kilka dobrze znanych zastosowań.
Na zdjęciu nad ziemią z obrazem znajduje się tuż nad białą powierzchnią, co nie wystarczy, aby zapobiec efektowi głębokiej walki. Natomiast w stensilinga (dolna figura) efekt ten jest całkowicie usunięty, nawet gdy są to powierzchnie współpłaszczyznowe.
Walka Z
Ze względu na brak precyzji w buforze Z współpłaszczyznowe wielokąty o krótkim zasięgu lub nakładające się mogą być przedstawiane jako pojedyncza płaszczyzna z wieloma nieregularnymi przekrojami poprzecznymi. Sekcje te mogą się różnić w zależności od pozycji kamery i innych parametrów i szybko się zmieniają. Nazywa się to walką-Z. Istnieje wiele rozwiązań tego problemu:
- Zbliż odległą płaszczyznę, aby ograniczyć głębokość sceny, zwiększając w ten sposób dokładność bufora Z lub zmniejszając odległość, z której obiekty są widoczne w scenie.
- Zwiększ liczbę bitów przydzielanych do Z-bufora, co jest możliwe kosztem pamięci dla bufora szablonu.
- Odsuwaj wielokąty dalej od siebie, co ogranicza możliwości artysty w tworzeniu skomplikowanych scen.
Wszystkie te podejścia do problemu mogą jedynie zmniejszyć prawdopodobieństwo, że wielokąty doświadczą walki Z i nie gwarantują ostatecznego rozwiązania w ogólnym przypadku.
Rozwiązanie zawierające bufor szablonu opiera się na wiedzy, który wielokąt powinien znajdować się przed pozostałymi. Sylwetka przedniego wielokąta jest rysowana w buforze szablonu . Następnie resztę sceny można renderować tylko tam, gdzie sylwetka jest negatywna, więc nie będzie kolidować z przednim wielokątem.
Objętość cienia
Objętość cieni to technika stosowana w grafice komputerowej 3D w celu dodawania cieni do renderowanej sceny. Zostały one po raz pierwszy zaproponowane przez Franka Crowa w 1977 r. jako geometria opisująca trójwymiarowy kształt obszaru przesłoniętego przez źródło światła. Objętość cienia dzieli wirtualny świat na dwie części: obszary, które są w cieniu i obszary, które nie są.
Implementacja bufora szablonu woluminów cieni jest ogólnie uważana za jedną z najbardziej praktycznych technik cieniowania w czasie rzeczywistym ogólnego przeznaczenia do użytku na nowoczesnym sprzęcie graficznym 3D. Została spopularyzowana przez grę wideo Doom 3 , a szczególna odmiana techniki użytej w tej grze stała się znana jako Carmack's Reverse .
Refleksje
Odbicie sceny jest rysowane, gdy sama scena jest przekształcana i odbijana względem płaszczyzny „lustrzanej”, co wymaga wielu przebiegów renderowania i użycia bufora szablonu w celu ograniczenia obszarów, w których działa bieżący przebieg renderowania:
- Narysuj scenę z wyłączeniem obszarów lustrzanych – dla każdego lustra zablokuj bufor Z i bufor kolorów
- Renderuj widoczną część lustra
- Test głębi jest ustawiony w taki sposób, że każdy piksel przechodzi do maksymalnej wartości i zawsze przechodzi pomyślnie
- dla każdego lustra:
- Test głębi jest ustawiony tak, że przechodzi pomyślnie tylko wtedy, gdy odległość piksela jest mniejsza niż bieżąca (zachowanie domyślne)
- Transformacja macierzy jest zmieniana w celu odzwierciedlenia sceny względem płaszczyzny lustra
- Odblokuj bufor Z i bufor kolorów
- Narysuj scenę, ale tylko jej część, która leży między płaszczyzną lustra a kamerą. Innymi słowy, płaszczyzna lustra jest również płaszczyzną tnącą
- Ponownie blokuje bufor kolorów, test głębi jest ustawiony tak, że zawsze przechodzi pomyślnie, resetuje szablon dla następnego lustra.
Płaskie cienie
Podczas rysowania płaszczyzny cieni dominują dwa problemy: Pierwszy dotyczy problemu głębokiej walki w przypadku nieprzyznania płaskiej geometrii na części objętej cieniem i na zewnątrz. Zobacz sekcję, która się z tym wiąże. Kolejny problem dotyczy zasięgu cieni poza obszarem, w którym znajduje się samolot.
Innym problemem, który może się pojawić lub nie, w zależności od techniki, jest zaprojektowanie większej liczby wielokątów w jednej części cienia, co skutkuje ciemniejszymi i jaśniejszymi częściami tego samego odcienia. Wszystkie trzy problemy można rozwiązać geometrycznie, ale ze względu na możliwość bezpośredniego użycia akceleracji sprzętowej jest to znacznie bardziej elegancka implementacja przy użyciu bufora szablonu: 1. Włącz światła i światła 2. Narysuj scenę bez żadnego wielokąta, który powinien być rzucane cienie 3. Narysuj wszystkie wielokąty, na które mają być rzucane cienie, ale bez świateł. W ten sposób bufor szablonu, piksel każdego wielokąta ma zostać przypisany do określonej wartości dla podłoża, do którego należą. Odległość między tymi wartościami powinna wynosić co najmniej dwie, ponieważ dla każdej płaszczyzny należy zastosować dwie wartości dla dwóch stanów: w cieniu iw jasnym. 4. Wyłącz dowolne globalne oświetlenie (aby upewnić się, że kolejne kroki będą miały wpływ tylko na pojedyncze wybrane światło) Dla każdej płaszczyzny: Dla każdego światła: 1. Edytuj bufor szablonu i tylko piksele, które mają określoną wartość dla wybranego poziomu. Zwiększ wartość wszystkich pikseli, które są rzutowanymi obiektami między datą danego poziomu a jasnością. 2. Pozwól mu narysować tylko wybrane światło na poziomie, przy którym część jego określonej wartości nie uległa zmianie.
Przestrzenne cienie
Implementacja bufora wzornika przestrzennych cieni do rysowania to dowolny cień bryły geometrycznej, którego objętość obejmuje część sceny, która się w nim znajduje. Jeśli jakakolwiek część sceny należy do tej objętości, światło nie jest oświetlone, w przeciwnym razie jest. Ten problem jest potęgowany przez wzrost liczby świateł, ale nie dotyczy liczby obszarów, na które padają cienie. Istnieje kilka rozwiązań tego problemu, ale zastosowaliśmy następujący algorytm: 1. Narysuj scenę bez światła 2. Zablokuj bufor Z i bufor kolorów, aby oba nie mogły wprowadzać zmian Dla każdego światła 1. Używając dogłębnej informacje o scenie (Z-bufor), aby wypełnić bufor szablonu tylko w tych częściach sceny, w których cień objętości nie istnieje lub nie jest widoczny z istniejących budynków. 2. Odblokuj bufor dla koloru i dostosuj funkcję bufora Z, aby umożliwić poprawki tylko tam, gdzie wartość głębi jest równa istniejącej 3. Narysuj scenę oświetloną tylko tym światłem, ale tylko dla części sceny, która przejdzie test szablonu
Każdy z tych fragmentów sugeruje, że można użyć czystego bufora szablonu.
Jeśli chodzi o cienie, technika ta może być używana do oświetlania części przestrzeni, które są oświetlone silnym światłem. Na przykład jasność reflektora w ciemnym pomieszczeniu z dużą zawartością kurzu w powietrzu może być postrzegana jako oświetlająca odpowiednią objętość przestrzeni.
Inne aplikacje
Kolejnym przykładem jest tak zwany miękki cień, w którym przejście między oświetloną i zacienioną częścią sceny jest nieostre. Konkretnie, jednym ze sposobów na osiągnięcie tego efektu bufora szablonu jest zwielokrotnienie objętości cienia, i to w miarę jak kopie odpowiednio są skalowane zgodnie z szeregiem geometrycznym przy małym powiększeniu, np. 1.04. Środek skalowania może być środkiem ciężkości wielokąta reprezentującego górną objętość. To samo w sobie da serię złożonych cieni, które dadzą pożądany efekt.
Kolejna implementacja obejmuje dziedzinę wizualizacji podczas modelowania brył techniką Constructive Solid Geometry (CSG), w której bufor szablonowy wraz z Z-buforem może z powodzeniem rozwiązywać problemy operacji boolowskich SOLiD.
OpenGL
glEnable ( GL_STENCIL_TEST ); // domyślnie wyłączone glStencilMask ( stencilMask ); // zezwala na zapis do bufora wzornika, domyślnie (0xFF) bez maski. glClearStencil ( clearStencilValue ); // wyczyść wartość szablonu, domyślnie = 0 glStencilFunc ( funk , ref , mask ); // domyślnie GL_ALWAYS, 0, 0xFF, zawsze pomyślnie test wzornika glStencilOp ( fail , zfail , zpass
); // domyślnie GL_KEEP, GL_KEEP, GL_KEEP, nie zmieniaj bufora wzornika glClear ( GL_STENCIL_BUFFER_BIT ); // wyczyść bufor szablonu, wypełnij (clearStencilValue & stencilMask)
Test: ( ref & mask ) func (stencilValue & mask)
W zależności od trzech możliwych warunków funkcji szablonu/funkcji głębi.
1. Funkcja testu szablonu nie działa:
Jeśli powiedzmy, że func to GL_NEVER, test szablonu zawsze zakończy się niepowodzeniem. Żadne bufory kolorów/Z nie są modyfikowane. Bufor wzornika jest modyfikowany zgodnie z niepowodzeniem glStencilOp. Jeśli powiedzmy glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP) wtedy nastąpi GL_REPLACE i stencilValue = (ref & stencilMask) // stanie się ref
2. Funkcja testu szablonu zaliczona pomyślnie/funkcja testu głębokości nie powiodła się:
Jeśli powiedzmy, że func to GL_ALWAYS, test szablonu zawsze zakończy się pomyślnie, ale test głębokości może się nie powieść. Żaden bufor koloru/z nie jest modyfikowany. Bufor wzornika jest modyfikowany zgodnie z glStencilOp zfail. Jeśli powiesz glStencilOp(GL_KEEP, GL_INCR, GL_KEEP) wtedy GL_INCR ma miejsce i stencilValue = (stencilValue+1) // stanie się 1
3. Funkcja szablonu przechodzi/Funkcja głębokości przechodzi:
Jeśli powiedzmy, że func to GL_ALWAYS, test szablonu zawsze zakończy się pomyślnie. Jeśli test głębokości również zakończy się pomyślnie. Zmodyfikowano zarówno kolor, jak i bufor Z. Bufor wzornika jest modyfikowany zgodnie z glStencilOp zpass. Jeśli powiedzmy, glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP) to wartości Stencil nie są zmieniane, modyfikowane są tylko bufory kolorów i Z.
Zazwyczaj bufor Stencil jest inicjowany przez ustawienie masek bufora Z i bufora kolorów na wartość false. a następnie ustawienie odpowiedniej wartości ref do bufora szablonu przez niepowodzenie testu szablonu za każdym razem.
// wyłącza kolor i bufory Z glColorMask ( GL_FALSE , GL_FALSE , GL_FALSE , GL_FALSE ); glDepthMask ( GL_FALSE ); glStencilFunc ( GL_NEVER , 1 , 0xFF ); // nigdy nie przechodź testu wzornika glStencilOp ( GL_REPLACE , GL_KEEP , GL_KEEP ); // zamień wartości bufora wzornika na ref=1 glStencilMask ( 0xFF
); // bufor wzornika wolny do zapisu glClear ( GL_STENCIL_BUFFER_BIT ); // najpierw wyczyść bufor wzornika, zapisując domyślną wartość wzornika (0) do całego bufora wzornika. rysuj_wzornik_kształtu (); // w lokalizacjach pikseli kształtu wzornika w buforze wzornika zamień wartości bufora wzornika na ref = 1
Teraz użyj zainicjowanego bufora wzornika i testu wzornika, aby pisać tylko w miejscach, w których wartość wzornika wynosi 1:
// włącz bufory kolorów i Z. glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ); glDepthMask ( GL_TRUE ); // koniec z modyfikacją bufora szablonu na szablonie i przejściu w głąb. glStencilMask ( 0x00 ); // można również uzyskać przez glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // test szablonu: pomyślny test szablonu tylko przy stencilValue == 1 (Zakładając, że test głębokości zakończy się pomyślnie).
// i zapisz rzeczywistą zawartość do bufora głębi i koloru tylko w lokalizacjach kształtu szablonu. glStencilFunc ( GL_EQUAL , 1 , 0xFF ); rysuj_rzeczywistą_zawartość ();
Zobacz też
- Buforowanie Z (bufor głębi)
- Objętość cienia (technika buforowania szablonów tworząca cienie)