Wydaje mi się, że rozumiem podstawy Marching Ray Field Signed Distance. Modelujesz scenę za pomocą szeregu pól odległości (takich jak: http://iquilezles.org/www/articles/distfunctions/distfunctions.htm ), a następnie dla każdego piksela rzucanego promieniem zacznij od początku promienia , znajdź odległość do najbliższego obiektu w tym punkcie i zwiększaj punkt o najbliższą odległość, aż coś trafisz. Udało mi się zrobić prosty renderer i właśnie tam kończy się większość opisów techniki.
Pozostawia mi to kilka pytań, w jaki sposób można wykorzystać SDF Ray Marching w scenariuszu z prawdziwego świata:
Pytanie 1: W prawdziwej grze scena jest zwykle złożona i ładowana na procesor, z wieloma dynamicznymi obiektami. Rozumiem podstawowe culling okluzji (takie jak oktany), a przy renderowaniu wielokątnym tworzyłbym listę (na CPU) elementów w widoku frustrowanym do renderowania.
Wyobraź sobie, że mam bardzo złożoną scenę z wieloma postaciami i dynamicznymi obiektami poruszającymi się po ekranie, kontrolowanymi przez CPU. Jak przesyłać strumieniowo obiekty, które chcę renderować do GPU w każdej ramce? Każdy przykład ma scenę zakodowaną na stałe w GLSL. Czy ktoś może udostępnić przykład poziomu dynamicznie przesyłanego strumieniowo do modułu cieniującego?
Pytanie 2: W jaki sposób obiekty mogą mieć wiele kolorów? Funkcje odległości zwracają tylko odległość, ale w jaki sposób implementacje często zwracają kolor? (np. uderzyłeś w czerwoną kulę, a nie w niebieski sześcian.) Gdyby to była implementacja procesora, mogłabym wywołać funkcję globalną wewnątrz funkcji odległości, gdy jest to trafienie kończące marsz promienny, i które mogłoby również przekazać obiekt trafionego tekstura / kolor. Ale jak zwrócisz kolor lub teksturę przedmiotu w GLSL?
Dziękuję Ci.
Obecnie rozwijam silnik gry, który wykorzystuje podpisane pola odległości jako technikę renderowania, aby wyświetlać płynną geometrię proceduralną (generowaną za pomocą prostych prymitywów, takich jak na razie w twoim łączu, z zamiarem zaimplementowania fraktali Julii i IFS w przyszłości). Ponieważ mój silnik koncentruje się na generowaniu procedur i musi definiować liczby w sposób, który czyni je przyjaznymi dla ray-marchera, wydaje mi się, że jestem w dobrym miejscu, aby odpowiedzieć na to pytanie: P.
Jeśli chodzi o przesyłanie strumieniowe, najprostszym rozwiązaniem jest użycie jakiegoś buforowanego typu i wrzucenie go na GPU, gdy chcesz przeprowadzić marsz promienny. Każdy element bufora jest typem złożonym (np. Struct w C / C ++), a każdy typ zawiera elementy określające, jaką funkcję należy użyć do jego reprezentowania, jego pozycję, obrót, skalę itp. Oraz średni kolor. Następnie proces upraszcza się do:
Jeśli chodzi o kolory figur, pamiętaj, że shadery pozwalają definiować zarówno złożone typy, jak i prymitywy;). To pozwala ci wrzucić wszystko do struktury w stylu C, a następnie przekazać te struktury z powrotem z funkcji odległości.
W moim silniku każda struktura zawiera odległość, kolor i identyfikator, który wiąże ją z odpowiednią definicją figury w buforze wejściowym. Każdy identyfikator jest wywnioskowany z otaczającego kontekstu odpowiedniej funkcji odległości (ponieważ moja funkcja mapowania zapętla się przez bufor wejściowy, aby znaleźć najbliższą liczbę dla każdego promienia dla każdego kroku, mogę bezpiecznie traktować wartość licznika pętli, gdy wywoływany jest każdy SDF jako identyfikator figury dla tej funkcji), podczas gdy wartości odległości są definiowane przy użyciu arbitralnego rdzenia SDF (np
point - figure.pos
dla kuli), a kolory są albo definiowane na podstawie średniego koloru odpowiedniego elementu w buforze postaci (dlatego dlaczego warto zachować identyfikatory postaci) lub poprzez kolor proceduralny ważony w kierunku przechowywanej średniej (jednym przykładem może być wzięcie liczba iteracji dla pewnego punktu na żarówce Mandelbulb, mapowanie „przeciętnego koloru” z przestrzeni kolorów FP na przestrzeń kolorów całkowitych, a następnie użycie odwzorowanego koloru jako palety przez XOR'owanie go względem liczby iteracji).Tekstury proceduralne to inne podejście, ale sam nigdy ich nie użyłem. iq przeprowadził sporo badań w tej dziedzinie i opublikował kilka ciekawych demonstracji na temat Shadertoy, dzięki czemu może to być jeden ze sposobów na zdobycie dodatkowych informacji.
Niezależnie od tego, czy kolor jest statyczny dla każdej figury, generowany proceduralnie, czy magicznie próbkowany z tekstury proceduralnej, podstawowa logika jest taka sama: abstrakcyjne figury do pewnego rodzaju pośredniego typu złożonego (np. Struktury), przechowują zarówno lokalną odległość, jak i lokalną kolor w instancji tego typu, a następnie przekaż typ złożony jako wartość zwracaną z funkcji odległości. W zależności od implementacji kolor wyjściowy może następnie przejść bezpośrednio do ekranu lub podążać za punktem kolizji do kodu oświetlenia.
Nie wiem, czy powyższe było wystarczająco jasne, czy nie, więc nie martw się pytaniem, czy coś nie ma sensu. Naprawdę nie mogę podać żadnych próbek kodu GLSL / cieniowania pikseli, ponieważ pracuję z HLSL i cieniowaniem obliczeniowym, ale z przyjemnością próbuję przejrzeć wszystko, czego nie napisałem poprawnie :).
źródło