Jak skutecznie renderować dużą siatkę terenu?

10

Ostatnio utknąłem w problemie z myśleniem o najlepszym sposobie generowania terenu w mojej grze. W innych projektach zwykle używałem map wysokości, więc cała podstawowa praca była oparta na używanym silniku, ale teraz nie można tego zrobić, ponieważ teren ma miliony określonych wielokątów, które muszą być narysowane dokładnie. Ponadto wielu z nich nie można przeanalizować z wektora Y (z powodu ukrytych pod nimi wielokątów), co oznacza, że ​​mapa wysokości nie jest tu przydatna. W tym przypadku musiałem użyć obiektu COLLADA.

Ktoś kazał mi ręcznie podzielić model w oprogramowaniu takim jak Blender, ale niestety nie jest to również możliwe, ponieważ tereny te są tworzone w częściach w innym oprogramowaniu i ładowane później do gry (taki jest pomysł). W związku z tym byłoby to duże zadanie, które musiałoby być ręcznie krojone za każdym razem.

Dlatego od tygodnia zastanawiam się, jak rozwiązać ten problem i proceduralnie załadować tę siatkę, teren, zgodnie z frustracją kamery, oszczędzając jak najwięcej wydajności. Przeszedłem przez wiele dokumentów dotyczących proceduralnego generowania siatki i myślę, że mój problem można rozwiązać, odwzorowując siatkę na ósemki. To jest WIELKA praca, przynajmniej dla mnie, i dlatego tu jestem, ponieważ nie chcę ryzykować zejścia bez uprzedniego kontaktu z doświadczonymi ludźmi.

Krótko mówiąc, mam miliony wierzchołków i wskaźników, które razem tworzą teren, ale z oczywistych powodów nie mogę ich narysować w tym samym czasie. Potrzebuje jakiejś procedury. Jaki jest najlepszy sposób, aby potraktować dużą siatkę jako teren? Czy jest na ten temat jakaś konkretna książka? Czy istnieje najlepszy sposób na jego wdrożenie?

Przepraszam za jakikolwiek błąd, jestem bardzo nowicjuszem w tej dziedzinie.

Karl Marny
źródło

Odpowiedzi:

12

Podstawowa porcja to dobry sposób na rozpoczęcie. W razie potrzeby możesz przejść do bardziej wyrafinowanych struktur danych, takich jak oktety. Na razie po prostu podziel teren na części o określonych wymiarach podczas ładowania modelu z dysku.

W zależności od danych możesz podzielić teren na słupy na płaszczyźnie o pełnej wysokości lub w sześcianach w przestrzeni. Kod nie jest kompletny (fmod, inicjalizacja wektorowa, indeksy, ...), ale powinien dać ci początek.

// Load vertices from disk
struct point { double x, y, z; };    
vector<point> vertices;

// Create container for chunks
typedef pair<int, int> key;
unordered_map<key, vector<point>> chunks;
const int chunksize = 10;

// For each vertex
for (int i = 0; i < vertices.size(); ++i) {
    // Fetch global coordinates
    int x = vertices[i].x,
        y = vertices[i].y,
        z = vertices[i].z;

    // Find containing chunk
    key k;
    k.first  = x / chunksize;
    k.second = z / chunksize;

    // Calculate local coordinates
    point p;
    p.x = x % chunksize;
    p.y = y;
    p.z = z % chunksize;

    // Add to chunk
    chunks[k].push_back(p);
}

// Create separate buffers for each chunk
// ...

Ponieważ teraz podzieliłeś siatkę, możesz wykonać na niej LOD i techniki wycinania, aby pominąć renderowanie ukrytych fragmentów.

  • Odległość od miejsca, od którego zaczynasz. Fragmenty byłyby renderowane tylko w obrębie określonej odległości, na przykład odległości widzenia kamery. Im mniejsza odległość widzenia, tym większa wydajność, ponieważ trzeba narysować mniej fragmentów terenu.

  • Ubijanie fragmentów jest powszechną techniką renderowania siatek przecinających się z fragmentem widoku kamery. Zapewni to najprawdopodobniej największy wzrost wydajności.

Eksperymentuj z rozmiarem porcji i odległością widoku, aby uzyskać najlepsze wyniki. Rozmiar porcji jest kompromisem między dokładnym ubijaniem a łatwym obliczeniem. Aby dalej optymalizować, możesz spojrzeć na te bardziej zaawansowane optymalizacje.

  • Culling okluzji można wykonać, renderując siatki na CPU w bardzo niskiej rozdzielczości. Pozwala to wcześnie wykryć siatki ukryte za innymi. Nie muszą być wysyłane do procesora graficznego, więc oszczędzasz wiele wykonań modułu cieniującego wierzchołków, które w innym przypadku zostałyby wykonane przed odrzuceniem trójkątów.

  • Poziom szczegółowości oznacza, że ​​obliczasz siatki o niższej rozdzielczości dla twoich kawałków. Na podstawie odległości do kamery wybierasz jedną z siatek do narysowania. Pozwala to zmniejszyć liczbę wierzchołków, ponieważ odległe fragmenty nie wymagają tak dużej ilości szczegółów. Takie podejście sprawdza się dobrze w przypadku oktetów, ponieważ można scalić wiele kostek w jedną siatkę niskiej rozdzielczości dla obszarów daleko od kamery. Jednak płynne łączenie krawędzi między dwoma kawałkami o innej rozdzielczości nie jest trywialne.

danijar
źródło