Was ist die schnellste Art eine Dreicksnetz Landschaft zu zeichnen?



  • Hi,

    was ist aktuell die schnellste Art eine Landschaft als Dreiecknetz zu zeichnen?
    (Ohne Geometrieshader)

    Ich denke man teilt die Landschaft in z.B 64*64 Blöcke und zeichnet diese.
    (Soweit man eben sehen will)

    Ist es hier sinvoll alle diese 64*64 Blöcke zu zeichnen oder vorher Frustum Culling für jeden Block durchzuführen, mit der CPU?

    Lohnt es sich innerhalb der Blöcke LOD Algorithmen anzuwenden?
    Wenn ja, welcher wird da so verwendet?

    Ich nehme an die Geometriedaten der für die 64*64 Blöcke werden in VBOs (Vertex Buffer Objects) übergeben und die Höhe wird aus einer Highmap (Textur) im Shader ausgelesen. Stimmt diese Annahme?

    Berechnet man die Normalen der Dreiecke der Landschaft für die Beleuchung im Shader? Oder sollte man diese mit der CPU vorberechnen und mit übergeben?

    Sollte man bei einer Bewegung durch die Landschaft die VBOs der neu sichbar werdenden 64*64 Blöcke neu erstellen oder den Inhalt der vorhandenen VBOs mit glBufferSubData() ändern?

    Oder verwendet man eine ganz andere Idee?



  • Bei den meisten deiner Fragen lautete die Antwort: it depends.

    Ichd enke, dass Frustum Culling viel Sinn macht, wenn du direkt die kompletten 64x64 Blöcke raushauen kannst. Kommt natürlich auf die Skalierung der Blöcke an, obs was bringt.

    Bei LOD lautete die Antwort: Wenn deine Framerate geometrie limitiert ist, macht das Sinn. Sonst ists nur hässlich :).



  • Andreas XXL schrieb:

    Hi,

    was ist aktuell die schnellste Art eine Landschaft als Dreiecknetz zu zeichnen?
    (Ohne Geometrieshader)

    Ich denke man teilt die Landschaft in z.B 64*64 Blöcke und zeichnet diese.
    (Soweit man eben sehen will)

    Gute idee. Dann bitte mit Triangle strips rendern. Und mit der Länge der strips experimentieren. Es macht ggf. keinen Sinn, pro Zeile des Blocks einen Strip mit 64*2 Dreiecken rauszuhauen, da dann, wenn du die nächste Zeile 'verstripst' die Vertices, die die Zeilen teilen nicht mehr im Vertex Cache sind.
    d.H., wenn du den Chunk mit folgenden strips renderst

    11116666
    22227777
    33338888
    44449999
    5555

    bist du unter Umständen bis zu doppelt so schnell als wenn du ihn so

    11111111
    22222222
    33333333
    44444444

    renderst

    Andreas XXL schrieb:

    Ist es hier sinvoll alle diese 64*64 Blöcke zu zeichnen oder vorher Frustum Culling für jeden Block durchzuführen, mit der CPU?

    Frustum Culling ist immer sinnvoll und wird die Framerate enorm verbessern

    Andreas XXL schrieb:

    Lohnt es sich innerhalb der Blöcke LOD Algorithmen anzuwenden?
    Wenn ja, welcher wird da so verwendet?

    Ja, welchen? Triviales LOD: Vernetze einfach nur jeden 2ten Vertex
    d.h., LOD 0 hat 64*64*2 Dreiecke, LOD 1 hat 32*32*2 Dreiecke ...
    Vorteil: Du kannst in alles LOD Stufen für die Vertices die selbe Geometrie verwenden und musst nur die Topologie mehrfach speichern (was für die Topologie nur ein Mehraufwand von 1/3 ist)

    Andreas XXL schrieb:

    Ich nehme an die Geometriedaten der für die 64*64 Blöcke werden in VBOs (Vertex Buffer Objects) übergeben und die Höhe wird aus einer Highmap (Textur) im Shader ausgelesen. Stimmt diese Annahme?

    Eher nicht. Texturzugriffe sind teuer. Berechne die Vertices und die Normalen ein mal auf der CPU, schiebe sie auf die GPU und lass sie da oben bis du das Programm beendest.

    Andreas XXL schrieb:

    Sollte man bei einer Bewegung durch die Landschaft die VBOs der neu sichbar werdenden 64*64 Blöcke neu erstellen oder den Inhalt der vorhandenen VBOs mit glBufferSubData() ändern?

    Nix ändern! Alles bleibt immer auf der GPU, du entscheidest nur, was mit glDrawElements gerendert wird.



  • @Gast_0025

    Aus was für Gründen würde man überhaupt mehr als nur einen Tri-Strip pro Chunk zeichnen?

    Die Strips für die einzelnen Zeilen kann man ja über ein degeneriertes Dummy-Dreieck zusammenhängen.



  • hustbaer schrieb:

    @Gast_0025

    Aus was für Gründen würde man überhaupt mehr als nur einen Tri-Strip pro Chunk zeichnen?

    Die Strips für die einzelnen Zeilen kann man ja über ein degeneriertes Dummy-Dreieck zusammenhängen.

    Nach meinen Erfahrungen bringt es Vorteile, den Vertex Cache voll auszunutzen. Wenn du mein Pattern verwendest, kannst du mit nur einem neuen Vertex zwei Dreiecke zeichnen. Wenn du immer ganze Zeile 'verstripst', kannst du mit einem Vertex der durch die Pipeline muss nur ein Dreieck zeichnen.

    Aber du hast natürlich recht, es wird am besten sein, die kleinen Strips von denen ich gesprochen habe durch degenerierte Dreiecke zu zeichnen. Andererseits habe ich die Erfahrung gemacht, dass indexed face sets inzwischen auch nicht mehr langsamer als strips sind. Immer unter der prämisse 'keep it lokal' i.e., nutze den Cache voll aus!

    Gruss, Gast



  • Wenn es dir darum geht, den Vertexcache voll auszunutzen, dann verwendest du keine Trianglestrips sondern cacheoptimierte indizierte Trianglelists. Die sind nicht nur nicht langsamer, sondern rein prinzipiell effizienter als Strips. Das Märchen von den Strips hält sich leider sehr hartnäckig...



  • Ich würde auch indizierte Tri-Lists verwenden.
    Ich meinte nur: wenn schon Tri-Strips, dann auch mit Dummy-Triangles zusammenhängen. Sonst hat man wieder unnötig viele Draw-Calls, und je nach API/Implementierung kann das bremsen.



  • dot schrieb:

    Wenn es dir darum geht, den Vertexcache voll auszunutzen, dann verwendest du keine Trianglestrips sondern cacheoptimierte indizierte Trianglelists. Die sind nicht nur nicht langsamer, sondern rein prinzipiell effizienter als Strips. Das Märchen von den Strips hält sich leider sehr hartnäckig...

    Wie macht man cacheoptimierte indizierte Trianglelists?
    Wie sieht diese Cacheoptimierung aus?



  • Andreas XXL schrieb:

    Wie sieht diese Cacheoptimierung aus?

    Naja: Deine indizes so ordnen, dass maximal viele Vertices möglichst knapp hintereinander wiederverwendet werden. Normalerweise bedient man sich da z.B. raumfüllender Kurven.


  • Mod

    nein, nicht wirklich, bei terrain bedient man sich normalerweise des "cache priming" und geht dann simpel zeilenweise weiter, das ist das cache effizienteste
    sieh z.B.
    http://www.gamedev.net/topic/371052-rendering-vertices-for-my-terrain/page__view__findpost__p__3445377



  • Damit das optimal ist, muss der Vertexcache aber mindestens so viele Einträge halten können, wie eine Zeile Vertices hat, was bei Terrain wohl eher kaum der Fall ist!?


  • Mod

    die zeilenbreite waehlt man natuerlich so dass sie der cachebreite entspricht 🙄



  • Das ist schon klar. Aber wenn man das Terrain in Spalten oder Tiles splittet, dann hat man dort an den Nähten überall Cache-misses. Ohne es mir jetzt genau durchüberlegt zu haben, würde ich rein intuitiv mal davon ausgehen, dass man da z.B. mit einer Hilbertkurve näher ans Optimum kommt.



  • dot schrieb:

    Das ist schon klar. Aber wenn man das Terrain in Spalten oder Tiles splittet, dann hat man dort an den Nähten überall Cache-misses.

    die hast du bei einer hilberkurve auch, nur eben viel frueher, weil die halbe cacheline wiederverwendet wird in am anfang.

    Ohne es mir jetzt genau durchüberlegt zu haben, würde ich rein intuitiv mal davon ausgehen, dass man da z.B. mit einer Hilbertkurve näher ans Optimum kommt.

    Cache priming ist eigentlich das allgemein bekannte optimum fuer ein grid.
    http://www.gamedev.net/topic/493518-terrain-triangles-or-trianglestrips/page__view__findpost__p__4220392



  • Gut, Ok. Mir war das Verfahren ja durchaus bekannt, ich ging nur immer davon aus, dass es nur dann optimal ist, wenn die Cachesize >= der Zeilenlänge ist. Aber wenn ich so drüber nachdenk, dann hast du wohl recht...



  • ich denke, vielleicht waere die hilbert curve besser wenn man die cache breite nicht kennt. leider ist dieses afaik auch nur der effektivste algorithmus nach cache primming wenn die cache size power of 2 ist, viele GPUs nutzen nicht PO2, da sie wohl einige cache baenke als "temp" nutzen in die die Vertexshader schreiben, bei GF1/2 war das glaube ich 14 und gf 3/4 waren es "bis 23".


Anmelden zum Antworten