Odroczone cieniowanie - jak łączyć wiele lampek?

9

Zaczynam od GLSL i zaimplementowałem proste odroczone cieniowanie, które generuje bufor G z pozycjami, wartościami normalnymi i albedo.

Napisałem również prosty punktowy moduł cieniujący.

Teraz rysuję kulę dla światła punktowego i wyjście trafia do bufora oświetlenia.

Problem polega na tym, jak połączyć wyniki bufora oświetlenia podczas rysowania wielu świateł?

Np. Kiedy rysuję drugie światło do bufora światła za pomocą punktowego modułu cieniującego, jak dodać pierwsze światło do drugiego światła w buforze oświetlenia. Mam na myśli, że nie możesz czytać i zapisywać w tym samym buforze wyjściowym?

JBeurer
źródło

Odpowiedzi:

12

Mieszanie addytywne, tj. GlBlendFunc (GL_ONE, GL_ONE) i glEnable (GL_BLEND).

Nathan Reed
źródło
czy w tym celu należy wyłączyć testowanie głębokości?
woojoo666
1
@ woojoo666 Nie. W rzeczywistości należy ją włączyć, gdy test głębokości ustawiony jest na mniej równy, tak aby przechodziły powierzchnie dokładnie pasujące do poprzedniego przejścia. Jeśli test głębokości jest wyłączony, powierzchnie niepoprawnie gromadzą światło z tego, co znajduje się za nimi. :)
Nathan Reed
hmm, wygląda na to, że właśnie tak się dzieje. włączenie mieszania powoduje, że przednie twarze łączą się z tylnymi, mimo że włączyłem testy głębokości. czy muszę coś zrobić również z maską głębokości?
woojoo666
wykonałem nieco więcej testów, wydaje się, że kolejność rysowania ma znaczenie (rysowanie od przodu do tyłu sprawia, że ​​testowanie głębokości działa poprawnie i mieszanie zachodzi tylko wtedy, gdy twarze są równe, a od tyłu do przodu wszystko się łączy). Czy można to zrobić bez sortowania wszystkiego?
woojoo666
2
@ woojoo666 Aha, wygląda na to, że rozwiązałeś go samodzielnie. Tak, musisz położyć głębokość w nieprzejrzystym przejściu, zanim będziesz mógł użyć jakiegokolwiek mieszania. Może to być Z-prepass z wyłączonym zapisywaniem kolorów, lub innym powszechnym sposobem jest oświetlenie otoczenia / kierunkowe w pierwszym przejściu bez mieszania, a następnie dodawanie lamp punktowych / punktowych w późniejszych przejściach z mieszaniem.
Nathan Reed
2

W przypadku mojego odroczonego mechanizmu renderującego agreguję wszystkie światła w jeden cel renderowania światła, korzystając z informacji z bufora g, a następnie próbkuję ten cel renderowania pod kątem intensywności światła podczas tworzenia końcowego obrazu backbuffera.

Zasadniczo przeglądam całą geometrię gry, przechodząc przez przepustkę geometrii, aby zbudować bufory G. Stamtąd podaję bufory g do mojego modułu cieniowania światła. Każde światło przebiega przez przełęcz za pomocą quada pełnoekranowego. W ten sposób mój moduł cieniujący pikseli może obliczyć natężenie światła dla wszystkich widocznych powierzchni z bufora g, a następnie dodać je do celu renderowania światła. Po prostu dodajesz intensywność światła dla każdego światła do bufora światła, ale upewnij się, że natężenie zostało ograniczone od 0 do 1.

Wszystko, co musisz zrobić, aby obsługiwać różne rodzaje świateł (punktowe, punktowe, równoległe), to uczynić światło bardziej odpornym, ewentualnie wykorzystując stały bufor do określenia, które procedury oświetleniowe należy wykonać.

KlashnikovKid
źródło
Tak, a pytanie brzmi - jak dodać do celu renderowania światła? Używasz mieszania alfa, jak sugerował Nathan Reed? Ponieważ, o ile wiem, nie można czytać i zapisywać w tym samym buforze wyjściowym (w tym przypadku jest to bufor lekki).
JBeurer
Ups, tak. Pozwoliłem, aby fuzja wyjściowa obsługiwała to przez mieszanie addytywne. Gdy próbkowanie do końcowego obrazu ma miejsce, gdy chcesz ustalić wartość, która działa dla mnie jako maksymalne możliwe natężenie światła, jakie może otrzymać powierzchnia. Stamtąd możesz po prostu skalować światła w razie potrzeby.
KlashnikovKid
Jak radzić sobie z przypadkami, w których światło jest za ścianą i nie powinno zapalać rzeczy po drugiej stronie ściany?
jjxtra
@PsychoDad To domena cieni, która jest ... bardziej skomplikowanym tematem. :)
Nathan Reed
0

Prawdopodobnie jest lepsza odpowiedź niż ta, ale wiem, że jeśli w swoim module cieniującym powtórzysz kod potrzebny do zrobienia drugiego światła, możesz następnie przetworzyć dwa światła na jednym obiekcie zamiast jednego. Wymaga to zrzucenia dużej ilości kodu dla drugiego światła i szwów trochę zbędnych, ale wiem, że to działa. Wierzę jednak, że jak ktoś ma nadzieję, że będzie dla ciebie wskazany, może być bardziej eleganckie rozwiązanie.

CodeNeko
źródło
Nie, to nie działa w ten sposób. Rysuję kulę dla każdego światła punktowego. O ile drugie światło punktowe nie leży w sferze wpływów pierwszego światła, drugie światło po prostu nie zostanie narysowane. Twoja metoda zadziałałaby, jeśli narysuję kwadrat na pełnym ekranie dla wszystkich świateł punktowych, jednak nie jest to poprawne podejście, ponieważ do globalnego oświetlenia stosowane są kwadraty na pełnym ekranie. Powiedzmy, że mam 16 małych świateł punktowych, które zmusiłyby mnie do przejścia przez nie dla każdego piksela, nawet jeśli piksel nie jest przez niego oświetlony. I zwykle powiedziałbym, że każdy piksel jest oświetlony jednym lub dwoma światłami. A co jeśli mam 100 świateł? NIE
JBeurer
Głównym powodem, dla którego to stwierdziłem, jest to, że jeśli używasz tylko dwóch lub kilku lampek, może to pomóc. Zwłaszcza jeśli rozbijasz wiele obiektów, użycie mieszania oznacza, że ​​musisz przerysować scenę dla każdego światła, więc jeśli masz dużo kształtów, powiedzmy milion, dziesięć milionów lub miliard, każde losowanie kosztuje znacznie więcej . Wykonanie tego w module cieniującym powoduje problemy, jeśli chcesz mieć dużo świateł, ale mieszanie powoduje problemy, jeśli chcesz mieć wiele kształtów. Jeśli masz dużo obu, musisz znaleźć środek, ale zwykle masz kilka świateł i wiele przedmiotów w grach.
CodeNeko
Nie, odroczone cieniowanie nie działa w ten sposób. Muszę narysować scenę tylko raz i zapisać odpowiednie informacje w buforze G. Następnie sfera wpływów dla każdego światła i zmieszaj go z buforem światła. I w końcu, łącząc bufor światła z buforem kolorów, otrzymuję ostatni zacieniowany bufor kolorów. Ilość obliczeń oświetlenia nie zależy od złożoności sceny. Jest to przede wszystkim główna zaleta odroczonego cieniowania.
JBeurer
Ach, to ma o wiele większy sens i byłoby znacznie lepsze.
CodeNeko