Tło:
Projektuję prosty system renderowania 3D dla architektury typu elementu systemu elementów za pomocą C ++ i OpenGL. System składa się z renderera i wykresu sceny. Kiedy skończę pierwszą iterację mechanizmu renderującego, mogę rozpowszechnić wykres sceny w architekturze ECS. Na razie jest to symbol zastępczy w taki czy inny sposób. Jeśli to możliwe, następujące cele są dla renderera:
- Prostota . To jest projekt badawczy i chcę mieć możliwość łatwej zmiany i rozszerzenia moich systemów (stąd podejście ECS).
- Wydajność . Moja scena może mieć wiele małych modeli, a także duże objętości o dużej geometrii. Niedopuszczalne jest pozyskiwanie obiektów z kontekstu OGL i geometrii bufora dla każdej ramki renderowania. Dążę do lokalizacji danych, aby uniknąć błędów w pamięci podręcznej.
- Elastyczność . Musi być w stanie renderować duszki, modele i objętości (woksele).
- Oddzielone . Graf scen może zostać ponownie przekształcony w podstawową architekturę ECS po napisaniu mojego renderera.
- Modułowy . Byłoby miło móc wymieniać różne renderery bez zmiany mojego wykresu sceny.
- Referencyjna przezroczystość , co oznacza, że w dowolnym momencie mogę nadać jej dowolną prawidłową scenę i zawsze będzie renderować ten sam obraz dla tej sceny. W szczególności ten cel nie jest koniecznie wymagany. Pomyślałem, że pomoże to uprościć serializację scen (będę musiał być w stanie zapisywać i ładować sceny) i dać mi elastyczność w zamianie różnych scen podczas działania w celach testowych / eksperymentalnych.
Problem i pomysły:
Wymyśliłem kilka różnych podejść do wypróbowania, ale mam problemy z buforowaniem zasobów OGL (VAO, VBO, shadery itp.) Dla każdego węzła renderowania. Oto różne koncepcje buforowania, które do tej pory wymyśliłem:
- Scentralizowana pamięć podręczna. Każdy węzeł sceny ma identyfikator, a moduł renderujący ma pamięć podręczną, która odwzorowuje identyfikatory w celu renderowania węzłów. Każdy węzeł renderowania zawiera VAO i VBO związane z geometrią. Brak pamięci podręcznej nabywa zasoby i mapuje geometrię do węzła renderowania w pamięci podręcznej. Po zmianie geometrii ustawiana jest brudna flaga. Jeśli moduł renderujący widzi brudną flagę geometrii podczas iteracji przez węzły sceny, ponownie buforuje dane za pomocą węzła renderowania. Po usunięciu węzła sceny zdarzenie jest rozgłaszane, a moduł renderujący usuwa powiązany węzeł renderowania z pamięci podręcznej, zwalniając zasoby. Alternatywnie węzeł jest oznaczony do usunięcia, a moduł renderujący jest odpowiedzialny za jego usunięcie. Myślę, że to podejście najbardziej zbliża się do osiągnięcia celu 6, jednocześnie biorąc pod uwagę 4 i 5. 2 cierpi z powodu dodatkowej złożoności i utraty lokalizacji danych przy wyszukiwaniu mapy zamiast dostępu do tablicy.
- Rozproszona pamięć podręczna . Podobnie powyżej, ale każdy węzeł sceny ma węzeł renderowania. Pomija to wyszukiwanie mapy. Aby zająć się lokalizacją danych, węzły renderujące mogą być przechowywane w module renderującym. Następnie węzły sceny mogłyby zamiast tego mieć wskaźniki do renderowania węzłów, a moduł renderujący ustawia wskaźnik na brak pamięci podręcznej. Myślę, że ten rodzaj naśladuje podejście komponentu bytu, więc byłoby spójne z resztą architektury. Problem polega na tym, że teraz węzły scen przechowują dane specyficzne dla implementacji mechanizmu renderującego. Jeśli zmienię sposób renderowania rzeczy w rendererze (np. Renderowanie duszków względem woluminów), muszę teraz zmienić węzeł renderowania lub dodać więcej „komponentów” do węzła sceny (co oznacza również zmianę wykresu sceny). Na plus wydaje się, że jest to najprostszy sposób na uruchomienie mojego renderera pierwszej iteracji.
- Rozproszone metadane . Komponent metadanych pamięci podręcznej mechanizmu renderującego jest przechowywany w każdym węźle sceny. Te dane nie są specyficzne dla implementacji, ale raczej zawierają identyfikator, typ i wszelkie inne istotne dane potrzebne pamięci podręcznej. Następnie wyszukiwanie pamięci podręcznej można wykonać bezpośrednio w tablicy przy użyciu identyfikatora, a typ może wskazywać, jakiego rodzaju metody renderowania należy użyć (jak duszki kontra woluminy).
- Gość + mapowanie rozproszone . Mechanizm renderujący jest gościem, a węzły sceny są elementami we wzorze gościa. Każdy węzeł sceny zawiera klucz pamięci podręcznej (taki jak metadane, ale tylko identyfikator), którym manipuluje tylko moduł renderujący. Identyfikatora można użyć dla tablicy zamiast uogólnionego wyszukiwania mapy. Mechanizm renderujący może zezwolić węzłowi sceny na wywołanie innej funkcji renderowania w zależności od typu węzła sceny, a identyfikator może być używany przez dowolną pamięć podręczną. Domyślny lub spoza zakresu identyfikator wskazuje na brak pamięci podręcznej.
Jak rozwiązałbyś ten problem? Czy masz jakieś sugestie? Dzięki za przeczytanie mojej ściany tekstu!