Wykres sceny dla odroczonego mechanizmu renderowania

10

Jako ćwiczenie edukacyjne napisałem odroczony silnik renderowania. Teraz chciałbym dodać wykres sceny do tego silnika, ale jestem trochę zaskoczony, jak to zrobić.

W normalnym (silniku renderującym do przodu) po prostu dodawałbym wszystkie elementy (wszystkie implementujące IDrawable i IUpdateAble) do mojego wykresu scen, niż najpierw podróżowałem po wykresie scen i wywoływałem Draw () wszędzie.

Jednak w odroczonym silniku renderowania muszę rozdzielić wywołania. Najpierw muszę narysować geometrię, następnie kółka cienia, a następnie światła (wszystkie do różnych celów renderowania), zanim połączę je wszystkie. Więc w tym przypadku nie mogę po prostu przejechać przez wykres sceny i po prostu wywołać remis. Z tego, co widzę, albo muszę trzykrotnie przemierzyć cały wykres sceny, sprawdzając, jaki to obiekt należy narysować, albo muszę utworzyć 3 osobne wykresy sceny, które są w jakiś sposób ze sobą połączone. Oba wydają się kiepskie rozwiązania, chciałbym obsłużyć obiekty sceny bardziej przejrzyste.

Innym rozwiązaniem, o którym myślałem, było przechodzenie przez wykres sceny jako normalne i dodawanie elementów do 3 oddzielnych list, oddzielanie geometrii, kółek i świateł, a następnie iterowanie tych list w celu narysowania poprawnych elementów, jest to lepsze i czy jest mądre jest ponowne wypełnienie 3 list w każdej ramce?

Roy T.
źródło

Odpowiedzi:

6

Podejście, którego użyłem w projekcie C ++, polega na tym, że wykres sceny (który ma indeks przestrzenny) wypełnia „widoczny” std :: wektor trafień na podstawie bieżącego widoku frustum. Ta widoczna lista jest zarządzana przez wykres sceny, więc jest ponownie obliczana tylko wtedy, gdy kamera się porusza - poruszające się obiekty na wykresie są przemieszczane na tej liście i przy użyciu nagrobków i nieposortowanych list zmian, które są sortowane i scalane w razie potrzeby.

Lista widocznych elementów jest najpierw sortowana według identyfikatora shadera, a dla każdego typu według odległości od kamery. Identyfikatory shaderów są przypisywane w taki sposób, że teren najpierw sortuje, a następnie budynki, a następnie jednostki, a następnie pociski, a następnie cząstki i tak dalej - jest to RTS. Niektóre modele mają więcej niż jeden moduł cieniujący, ale reklamują tylko swój główny moduł cieniujący. Gdy zostaną poproszeni o narysowanie, te, które również wymagają bitów narysowanych innym shaderem, dodają się do pojedynczej połączonej listy następnego przejścia.

Tak więc rysowanie przechodzi przez widoczną tablicę w jednym przejściu, w tym jednym przejściu tworzona jest połączona lista tych elementów do ponownego odwiedzenia, a oni rysują drugie przejście i tak dalej.

Rysowanie od przodu do tyłu i nieprzezroczyste, a następnie przezroczyste pomaga utrzymać wszystko przy zdrowych zmysłach.

Być może nie oznacza to minimalizacji liczby zmian modułu cieniującego itp., Ale jest dość wykonalne i łatwe do wdrożenia.

Nie mam pojęcia o XNA, obawiam się, jak to jest odpowiednie i ile z tych niskopoziomowych rzeczy, które tworzysz. Jednak najbardziej interesujące byłoby wiedzieć, co weterani sądzą o tym podejściu do C ++ RTSes.

Będzie
źródło
Hej Will, naprawdę podoba mi się ta odpowiedź, szczególnie dlatego, że jest zupełnie inna niż dotychczas. Twoja metoda wydaje się bardzo rozsądna, szczególnie gdy myślisz także o obiektach półprzezroczystych (których do tej pory głównie omijałem). Tworzenie (połączonej) listy z wykresu sceny dla obiektów do odwiedzenia wydaje się bardzo dobrym pomysłem. I tak, w XNA musimy też robić te wszystkie rzeczy na niskim poziomie :).
Roy T.,
3

Moja sugestia byłaby dwustopniowym podejściem dostosowanym do twoich konkretnych wymagań, podobnym do tego, co sam opisałeś. Potrzebujesz wykresu scen i „kolekcji renderowania” dla każdego z etapów renderowania, w twoim przypadku cienia, geometrii, świateł (może czwartym z nich są obiekty przezroczyste?)

Wykres sceny może być oparty na dowolnym typie relacji, ale moje osobiste preferencje byłyby oparte na relacjach przestrzennych, w których każdy węzeł może zawierać inne węzły, aby ułatwić szybkie wyrównywanie.

Renderowane kolekcje mogą być dowolnymi strukturami danych dostosowanymi do konkretnego kroku. Na przykład kolekcja cieni może być listą lub drzewkiem posortowanym według głębokości, aby zmaksymalizować wczesne odrzucanie. Kolekcja geometrii może być sortowana według użycia modułu cieniującego, aby zminimalizować zmiany (stan) modułu cieniującego. Kolekcja świateł może być listą lub drzewkiem posortowanym według odległości światła, rozmiaru lub ich kombinacji, dzięki czemu można ograniczyć renderowanie światła do tylko najbardziej efektywnych świateł, jeśli wydajność stanowi problem.

Niezależnie od wybranych struktur danych, upewnij się, że operacja wstawiania jest szybka i upewnij się, że używa ona puli i innych technik w celu wyeliminowania alokacji / zniszczenia danych, ponieważ będziesz czyścić i wypełniać te listy w każdej ramce.

Teraz wiązanie wszystkiego razem jest łatwe. Wystarczy przejść przez wykres sceny i dodać każdy element do odpowiednich kolekcji renderowania. Pomaga to, jeśli struktura danych automatycznie sortuje / konstruuje nowe wpisy na podstawie wymagań. Po zakończeniu przejrzyj kolekcje renderowania w wymaganej kolejności i wyrenderuj je.

Ponieważ struktury danych mają szybkie wstawianie i nie generują śmieci, nie ma kary za ponowne wypełnianie list, jak wspomniano.

Targowisko
źródło