Czy można zbudować sześcian o mniej niż 24 wierzchołkach


14

Mam świat oparty na kostkach, taki jak Minecraft i zastanawiam się, czy istnieje sposób na zbudowanie kostki z mniej niż 24 wierzchołkami, aby zmniejszyć zużycie pamięci.

Wydaje mi się to niemożliwe z dwóch powodów: normalne nie wyszłyby dobrze, a tekstury na twarz nie działałyby.

Czy tak jest, czy się mylę? Może jest jakaś nowa, wymyślna technologia DX11, która może pomóc?

Edycja: Żeby wyjaśnić, mam 2 wymagania: potrzebuję normałów powierzchni dla każdej powierzchni kostki, aby wykonać odpowiednie oświetlenie i potrzebuję sposobu na zajęcie się innym indeksem w tablicy tekstur dla każdej powierzchni kostki


1
Czy chcesz zmniejszyć zużycie pamięci karty graficznej lub pamięci RAM ?
— doppelgreener

1
Dane wierzchołków są teraz przechowywane w pamięci RAM i na GPU, więc zmniejszenie ich zmniejszy oba.
— Telanor

Odpowiedzi:


9

Jeśli potrzebujesz tylko normalnych na twarz, a jeśli twoje texcoords dla twarzy są ściśle 0/0, 0/1, 1/0, 1/1 (lub podobne do twojego układu), możesz zbudować sześcian z 8 wierzchołkami oraz indeksy 30 (pasek z restartem) lub 36 (lista). Pobierz normalne i tekstowe przy użyciu stałego wyszukiwania tablicowego na podstawie SV_VertexID w swoim module cieniującym wierzchołki.

Oznacza to, że nie musisz nawet umieszczać tekstów ani normałów w buforze wierzchołków, co zapewni jeszcze więcej oszczędności pamięci.

Idąc dalej, nadal możesz przejść do 24 wierzchołków na kostkę, ale także użyć instancji. Każda kostka miałaby stały rozmiar w buforze wierzchołków (1x1x1) i miałbyś współczynnik skalowania i pozycję (zakładając, że twoje kostki się nie obracają, a jeśli macie, to macierz) jako dane dla instancji. W przypadku nieobrotowego jednorazowy koszt wynosi 24 wierzchołki, ale wtedy każda kostka potrzebuje tylko 6 pływaków, aby w pełni określić. W obrotowej obudowie patrzysz na 16 liczb zmiennoprzecinkowych, ale nawet to jest znaczną oszczędnością (w tym przypadku bardziej prawdopodobne jest wąskie gardło po stronie procesora w przypadku transformacji macierzowych - w przypadku nieobrotowej obudowy budującej matrycę w locie w twój moduł cieniujący wierzchołki - nawet jeśli jest zrobiony dla jednego wierzchołka, jest tak głupio szybki, że nawet nie musisz się tym martwić).

W przypadku tekstur na twarz wystarczy użyć tablicy tekstur. Musisz oczywiście upewnić się, że każda taka tekstura w tablicy ma ten sam rozmiar, i nadal będziesz musiał przerwać bieżącą partię, jeśli sama tablica musi się zmienić, ale w przeciwnym razie dobrze sobie poradzi. Dodaj trzeci tekstowy tekst do definicji wierzchołka, który określa plasterek tablicy do użycia dla każdej twarzy.

Nie potrzebujesz GS z tym i powinien on działać szybciej niż przy użyciu jednego, ponieważ włączenie etapu modułu cieniującego geometrię spowoduje dodatkowe własne obciążenie.

W swoim silniku mam kod porównawczy, który po prostu rysuje kilka kostek za pomocą tej metody, i mogę łatwo przeżuć ponad 300 000 kostek, wciąż czyszcząc 60 klatek na sekundę na stosunkowo niskiej jakości GPU i nie robiąc nic innego, aby zoptymalizować proces . Wprawdzie nie jestem ich oświetleniem ani teksturowaniem, ale mam włączone mieszanie alfa, wyłączone wygładzanie tła i ogólnie równoważy to z moją częścią „nie robienia niczego innego w celu optymalizacji”, więc powinno dać ci rozsądne wyobrażenie o rodzaju boisko można uderzyć tą metodą.


1
Używałem już instancji i działa świetnie dla mniej niż 40 tysięcy kostek. Ale mam co najmniej 256 tys. Kostek, a instancja też tego nie obsługiwała. Jednak użycie SV_VertexID przy wyszukiwaniu wydaje się bardzo obiecujące.
— Telanor

Jak duży był Twój bufor na instancję? Próba umieszczenia ich wszystkich w ogromnym buforze może skończyć się zadławieniem GPU; Generalnie przechowuję bufory dla poszczególnych instancji w wystarczającej ilości miejsca dla 64k obiektów (w razie potrzeby dzielę wywołania losowania), używam wzorca discard / no-overwrite i piszę bezpośrednio do odwzorowanego wskaźnika zamiast kopiowania z tablicy pośredniej, która działa bardzo dobrze .
— Maximus Minimus

Niezbędne jest także utrzymanie niskiej liczby map. Mapuj / pisz jedną kostkę / odkrywaj 40k razy będzie znacznie wolniej niż mapuj / zapisuj 40k kostek / odkrywaj tylko raz. Jeśli robiłeś to pierwsze, spróbuj przełączyć się na drugie.
— Maximus Minimus

15

Myślę, że główna optymalizacja, jaką możesz wykonać, polega na tym, że nie każda kostka faktycznie potrzebuje wszystkich 24 wierzchołków . W rzeczywistości jedynymi sześcianami, które potrzebują 24 wierzchołków, są te, które unoszą się w powietrzu, co jest prawdopodobnie rzadkim zjawiskiem.

Zasadniczo generuj quady tylko dla twarzy mających kontakt z powietrzem . Oznacza to, że jeśli dwa sześciany się stykają, nie trzeba generować żadnych wierzchołków dla twarzy, do której się dotykają.

Poniższy obraz pokazuje tę koncepcję, ale w 2D dla łatwiejszego zrozumienia. Na obrazie znajduje się 11 zajętych bloków (reprezentowanych przez wypełnione szare kółka), które normalnie wymagałyby reprezentacji 4 x 11 = 44 krawędzi (4, ponieważ jest to kwadrat, a nie sześcian). Ale jak widać, naprawdę musisz narysować krawędzie tylko wtedy, gdy stykają się z pustym kwadratem, który w tym przypadku ma tylko 8 krawędzi.

wprowadź opis zdjęcia tutaj

Jeśli tak prostemu przykładowi w 2D udało się zmniejszyć 44 krawędzie do 8 krawędzi, wyobraź sobie korzyści w dużym świecie 3D ...

Takie podejście opisano w tym artykule , które polecam przeczytać, mimo że jest skierowane do OpenGL. Koncepcje powinny być jednak dość uniwersalne.

Prawdopodobnie możesz również użyć modułu cieniującego geometrię do generowania wierzchołków w locie na GPU, co eliminuje potrzebę przechowywania ich w pamięci, ale nie mam z tym doświadczenia, ani nie wiem, jak dobrze by to działało w przypadku dużych świat.


1
Bardzo ciekawy artykuł. Robię już optymalizację krawędzi, co z pewnością bardzo pomaga. Spróbuję shaderów geometrii i zobaczę, czy to się uda.
— Telanor

Czy masz na myśli, użyj modułu cieniującego geometrię i iloczynu krzyżowego, aby obliczyć normalne? Zastanawiałem się nad tym, jak stworzyć osobny program dla płaskich powierzchni (nie interesują mnie tekstury).
— dreta

@dreta Nie tylko to, ale przechodząc do punktu, w którym wysyłasz tylko centroidy kostki jako listę punktów, a wszystkie wierzchołki są emitowane przez GS. Być może zakoduj sąsiednie informacje w punktach, aby moduł cieniujący generował tylko te twarze, które są naprawdę potrzebne, choć nie zastanawiałem się, jak to zrobić.
— David Gouveia

Jeśli chcesz wydajności, nie używaj modułu cieniującego geometrię ... Prawie zawsze. Całkowicie zepsuły rurociąg. Jeśli chcesz wygenerować geometrię na GPU, użyj shadera obliczeniowego lub openCL
— Robert Fraser
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.