Brauche Hilfe bei der Verwendung des Vertex Buffers

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Brauche Hilfe bei der Verwendung des Vertex Buffers

    Schönen Abend,
    in meinem Projekt möchte ich nun doch zur Verwendung des Vertex Buffers greifen, doch mein Spiel hängt sich dadurch auf bzw. der exe Runner. Manchmal jedoch nicht aber die FPS liegen dann bei nur Eins. EIgentlich wollte ich durch die Verwendung die Performance erhöhen. Vielleicht mache ich ja was falsch. Mein Code sieht so aus:

    Das Objekt das mit Hilfe eines Grids eine Landschaft erzeugen soll hat den Code:

    GML-Quellcode

    1. scr_vertex_format_begin();
    2. global.v_buff = vertex_create_buffer(); //Vertexbuffer erstellen
    3. vertex_begin(global.v_buff, global.my_format); //Buffer nun beschreiben (nach dem vorher definierten format)
    4. for (i = 0; i < ds_grid_width(global.heightmap); i += 1)
    5. {
    6. for (j = 0; j < ds_grid_height(global.heightmap); j += 1)
    7. {
    8. var height = ds_grid_get(global.heightmap,i,j);
    9. for (k = 0; k < height; k += 1)
    10. {
    11. //if k > 12 model = global.model_rocks else model = global.model_grass;
    12. global.walls += 1;
    13. scr_add_vertex_floor(i*16,j*16,height*16,i*16+16,j*16+16,height*16);
    14. if ds_grid_get(global.heightmap,i-1,j) <= k
    15. {
    16. //d3d_model_wall(model,i*16,j*16,k*16,i*16,j*16+16,k*16+16,1,1);
    17. }
    18. if ds_grid_get(global.heightmap,i+1,j) <= k
    19. {
    20. //d3d_model_wall(model,i*16+16,j*16,k*16,i*16+16,j*16+16,k*16+16,1,1);
    21. }
    22. if ds_grid_get(global.heightmap,i,j-1) <= k
    23. {
    24. //d3d_model_wall(model,i*16,j*16,k*16,i*16+16,j*16,k*16+16,1,1);
    25. }
    26. if ds_grid_get(global.heightmap,i,j+1) <= k
    27. {
    28. //d3d_model_wall(model,i*16,j*16+16,k*16,i*16+16,j*16+16,k*16+16,1,1);
    29. }
    30. }
    31. }
    32. }
    33. //abschluss
    34. vertex_end(global.v_buff);
    Alles anzeigen



    Skript "scr_vertex_format_begin":

    GML-Quellcode

    1. vertex_format_begin();
    2. vertex_format_add_position_3d();
    3. vertex_format_add_colour();
    4. vertex_format_add_textcoord();
    5. global.my_format = vertex_format_end();



    Skript "scr_add_vertex_floor":

    GML-Quellcode

    1. var x1 = argument0;
    2. var y1 = argument1;
    3. var z1 = argument2;
    4. var x2 = argument3;
    5. var y2 = argument4;
    6. var z2 = argument5;
    7. //Vertex 1 (Jeder vertex muss nach dem schema des Vertexformats gebaut werden!)
    8. vertex_position_3d(global.v_buff, x1, y1, z1);//3d position
    9. vertex_colour(global.v_buff, c_white, 1);//farbe
    10. vertex_texcoord(global.v_buff, 0, 0);//uv koordinate
    11. //Vertex2
    12. vertex_position_3d(global.v_buff, x1, y2, z2);//3d position
    13. vertex_colour(global.v_buff, c_white, 1);
    14. vertex_texcoord(global.v_buff, 1, 0);
    15. //Vertex3
    16. vertex_position_3d(global.v_buff, x2, y1, z1);//3d position
    17. vertex_colour(global.v_buff, c_white, 1);
    18. vertex_texcoord(global.v_buff, 1, 1);
    19. //Vertex4
    20. vertex_position_3d(global.v_buff, x2, y2, z2);//3d position
    21. vertex_colour(global.v_buff, c_white, 1);
    22. vertex_texcoord(global.v_buff, 1, 1);
    Alles anzeigen



    Das Objekt das die ganze Schoße dann zeichnet:

    GML-Quellcode

    1. d3d_set_perspective(true);
    2. //Vertexbuffer zeichnen
    3. tex = background_get_texture(tex_grass);
    4. shader_set(shader0); // verwende den Standartshader also den Code der schon da steht wenn man einen Shader erstellt
    5. vertex_submit(global.v_buff, pr_trianglestrip, tex);//muss doch trianglestrip in meinem Fall sein, richtig?
    6. shader_reset();


    Also wo liegt das Problem? Mit den d3d_model-Funktionen kam ich bei einer riesiegen Landschaft aus Würfeln (alá Minecraft) wenigstens auf 20 FPS. Und wenn wir schon dabei sind... wie funktioniert das Setzen der UV-Koordinaten?

    Das soll mal flüssig laufen:


    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Morpheus ()

  • Auf den ersten Blick schaut das ganze korrekt aus. Woran es aber scheitern könnte ist die art an der du die TriangleStrip modell befüllst.

    Schau dir mal das bild an:


    In der Mitte ist ein Trianglestrip dargestellt.
    Nehmen wir mal an wir schauen uns die ersten 2 Quads an. Das erste Quad wäre das Triangle 1 und 2, das 2te Quad wäre das triangle 3 und 4.
    Wenn du dir die reihenfolge der vertexerstellung beider Quads anschaust, wirst du merken dass dafür nur 6 vertexe verwendet wurden. (Vertex 1 bis 6)

    Das liegt daran dass bei Trianglestrip das gerade verarbeitete Vertex sich automatisch mit dem vor-vorletzten (2 vertexe dahinter) vertex automatisch verbindet.

    Bei deinem erstellungsskript beachtest du dies zwar für ein einzelnes quad, aber das Problem ist wenn du ein weiteres Quad hinzufügst, du die informationen nicht so ausrichtest wie es das trianglestrip haben möchte. (Nach dem 2ten Quad hast du bereits 8 vertexe definiert statt 6.)

    Es könnte auch sein dass der Crash darauf zurückzuführen ist.

    Mein Tipp:
    Vertwende eine trianglelist. Du musst dann zwar die Dreiecke einzeln definieren (etwas mehr code-aufwand) aber es ist wesentlich einfacher zu handhaben wodurch solche fehler vermieden werden können. (Ausserdem ist bei trianglelists die reihenfolge der einzelnen Triangles egal, was bei trianglestrips nicht der fall ist.)

    Und wenn wir schon dabei sind... wie funktioniert das Setzen der UV-Koordinaten?

    Wie meinst du das? Geht es um das verständniss der UV-koordinaten im allgemeinem?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von LEWA ()

  • Vielen Dank, jetzt kapier ich wie Fan, Strip und List funzt. Habs jetzt mit List gemacht und die Vertexkoordinaten sollten jetzt stimmen. Aber es stürzt dennoch ab. Außer den Vertex Buffer hab ich nichts geändert, also stimmt da noch was nicht. Vielleicht passiert das auf Grund der falsch gesetzten UV-Koordinaten. Wenn das Spiel startet sieht man ganz kurz das grafische Ergebnis, die Textur sieht nicht ganz so aus wie sie soll, ganz verzerrt und mit Farben die darin eigentlich gar nicht vorkommen. Wie muss ich bei den UVs vorgehen?

    Mein Code sieht so aus (Skript um einen Floor zuzeichnen):

    GML-Quellcode

    1. var x1 = argument0;
    2. var y1 = argument1;
    3. var z1 = argument2;
    4. var x2 = argument3;
    5. var y2 = argument4;
    6. var z2 = argument5;
    7. //Vertex 1 (Jeder vertex muss nach dem schema des Vertexformats gebaut werden!)
    8. vertex_position_3d(global.v_buff, x1, y1, z1);//3d position
    9. vertex_colour(global.v_buff, c_white, 1);//farbe
    10. vertex_texcoord(global.v_buff, 0, 0);//uv koordinate
    11. //Vertex2
    12. vertex_position_3d(global.v_buff, x1, y2, z2);//3d position
    13. vertex_colour(global.v_buff, c_white, 1);
    14. vertex_texcoord(global.v_buff, 1, 0);
    15. //Vertex3
    16. vertex_position_3d(global.v_buff, x2, y1, z1);//3d position
    17. vertex_colour(global.v_buff, c_white, 1);
    18. vertex_texcoord(global.v_buff, 1, 1);
    19. //Vertex4
    20. vertex_position_3d(global.v_buff, x2, y1, z2);//3d position
    21. vertex_colour(global.v_buff, c_white, 1);
    22. vertex_texcoord(global.v_buff, 1, 0);
    23. //Vertex5
    24. vertex_position_3d(global.v_buff, x1, y2, z1);//3d position
    25. vertex_colour(global.v_buff, c_white, 1);
    26. vertex_texcoord(global.v_buff, 1, 1);
    27. //Vertex6
    28. vertex_position_3d(global.v_buff, x2, y2, z2);//3d position
    29. vertex_colour(global.v_buff, c_white, 1);
    30. vertex_texcoord(global.v_buff, 1, 1);
    Alles anzeigen


    DIe Koordinaten sollten stimmen und is ja eh triangle_list jetzt. Aber die UV-Koordinaten... vielleicht stürzt's darum noch ab.
  • Auf dem ersten Blick kann ich nichts erkennen was den Absturz verursachen könnte.
    Die UV-koordinaten sollten da nicht für den Absturz verantwortlich sein. Die Ursache ist eine ganz andere.

    Hast du zufällig ein example mit dem Problem das ich mir anschauen könnte?
  • LEWA schrieb:

    Auf dem ersten Blick kann ich nichts erkennen was den Absturz verursachen könnte....

    also ich seh da die wurzel aus 1360033 (1166.2x1166.2) bloecken! Das ganze mal 12 Triangles ueber eine Aufloesung von 1920x1080...


    edit1: *ich lach mich tot*
    edit2: *ich reg mich auf*
    edit3: *beruhig mich etwas*
    edit4: *beruhig mich etwas mehr...*
    edit5: *finde mich damit ab, dass "Morpheus und seine zwei bis drei FOR-Schleifen" nun ueber 12Million "BERECHNETTE" und "99% UNSICHTBARE" Triangles versucht auf einmal zu zeichnen...
    edit6: *gebe ihm sogar einen Loesungsvorschlag... den er ignorieren wird* : Nichts versuchen zeichnen zu lassen, was man nicht sieht! ...du wirst erstaunt sein, was das ausmacht :)
    edit7: *hoffe das Morpheus nicht sauer mit mir ist.*
    edit8: *nochmal alles durch den Kopf gehen lasse*
    edit9: *mehr Lust auf's Editieren bekomme*
    edit10: *kommt warscheinlich noch*

    Dieser Beitrag wurde bereits 9 mal editiert, zuletzt von Nightrage ()


  • also ich seh da die wurzel aus 1360033 (1166.2x1166.2) bloecken! Das ganze mal 12 Triangles ueber eine Aufloesung von 1920x1080...

    Ich bin erst beim analysieren des examples welches Morpheus mir über PN geschickt hat darauf gekommen dass die Anzahl an Polygonen die generiert werden schuld daran sind. (Hab den Screenshot nicht wirklich beachtet. XD)
    Das Problem war nicht dass es einfach gecrasht ist (vielleicht würde es crashen wenn man es lang genug laufen lassen würde), sodern die tatsache dass der Algorithmus eine halbe ewigkeit die for-schleifen abgearbeitet hat.

    Dieses Problem wirklich performancefreundlich zu lösen ist auch eine etwas komplexere sache.
    Zum einem: Erstelle keine polygone die für den spieler nicht sichtbar sind. Wenn man sich den Screenshot anschaut, sieht man jetzt z.B: nur die Oberfläche der Map. Unter die Map sehen kann man nicht, solange man nicht.
    Von daher solltest du beim generieren eine überprüfung einbauen ob der Block nicht von anderen Blöcken umgeben ist die ihn defakto "unsichtbar" machen. Falls dies der Fall ist, generiere diesen Block nicht da es einfach ressourcenverschwendung wäre.

    Zum anderen würde ich auf ein Chunk-system wie minecraft zurückgreifen. Da wird die Welt in kleine teilstücke (chunks) aufgeteilt die bei bedarf (z.B: wenn sie in der renderdistanz sichtbar werden sollen) von der HDD geladen und dan ngezeichnet werden. Ist sozusagen eine Art "Map-streaming".
    Das Problem beim GM ist nur dass du nicht auf hilfreiche features wie Multithreading zurückgreifen kannst, was es etwas schwierig macht die richtige balance zwischen ladegeschwindichkeit und performance (während der ladezeit) zu finden.

    Minecraft verwendet beide methoden. Falls ein Block bei Minecraft abgebaut wird, muss aus diesem grund der ganze Chunk neu generiert werden (im bezug auf das 3D modell) um die Polygone des Blocks zu entfernen und darunterliegende Polygone dazuzugenerieren um die lücke zu füllen.

    Aber wie gesagt, das ist eine etwas komplexere angelegenheit wenn man es von der performance richtig machen möchte.
    Da kommen dann so fragen auf wie:
    • Wie speichert/ladet man die chunks am effizientesten? (Beispielsweise sind binärdateien wesentlich besser dafür geeignet als reine textdateien.)
    • Was ist die richtige balance zwischen chunkgröße und chunkanzahl? (generierungszeit vs draw-calls) wirkt sich vor allem auf die ladezeiten eines chunks aus (insbesondere da du kein multithreading verwenden kannst).
    • wie könnte man den generierungsalgorithmus so effizient wie nur möglich gestalten?
    etc...

    Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von LEWA ()

  • Nightrage schrieb:

    LEWA schrieb:

    Auf dem ersten Blick kann ich nichts erkennen was den Absturz verursachen könnte....

    also ich seh da die wurzel aus 1360033 (1166.2x1166.2) bloecken! Das ganze mal 12 Triangles ueber eine Aufloesung von 1920x1080...


    Nein, ich lasse ja schon nur den Deckel des Blocks und die Seiten die man sieht zeichnen. Sind maximal 10 Trriangles und minimum 2.

    Zum anderen würde ich auf ein Chunk-system wie minecraft zurückgreifen. Da wird die Welt in kleine teilstücke (chunks) aufgeteilt die bei bedarf (z.B: wenn sie in der renderdistanz sichtbar werden sollen) von der HDD geladen und dan ngezeichnet werden. Ist sozusagen eine Art "Map-streaming".
    Das Problem beim GM ist nur dass du nicht auf hilfreiche features wie Multithreading zurückgreifen kannst, was es etwas schwierig macht die richtige balance zwischen ladegeschwindichkeit und performance (während der ladezeit) zu finden.


    Das war auch schon meine Idee, die ich aber nicht umsetzten konnte. Dafür hatte ich zwei weitere For-Schleifen, für die Chunks, in denen die drei For-Schleifen für x,y und z drin steckten. Aber dass waren wahrscheinlich zu viele ineinandergeschachtelte Schleifen, da es sich dann immer aufhing. Mir muss da wohl eine andere Lösung einfallen.

    Ich versteh einfach nicht, warum bei der Verwendung von d3d_model_wall die for-Schleifen schneller abgearbeitet werden als mit Vertexen. Und mit den Modell komme ich ja eben, wie man oben sehen kann auf immerhin 20 FPS. Mit dem Vertexbuffer nicht. Obwohl der schneller sein sollte.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Morpheus ()

  • Das war auch schon meine Idee, die ich aber nicht umsetzten konnte. Dafür hatte ich zwei weitere For-Schleifen, für die Chunks, in denen die drei For-Schleifen für x,y und z drin steckten. Aber dass waren wahrscheinlich zu viele ineinandergeschachtelte Schleifen, da es sich dann immer aufhing. Mir muss da wohl eine andere Lösung einfallen.

    Was du machen musst ist die verarbeitung der Chunks auf mehrere steps zu verlagern (defakto threading selbst einbauen.)
    Anstatt alle chunks zu beginn in den Ram laden, ladest du z.B: nur ein einziges Chunk (und zwar das in welchem sich der spieler gerade befindet) sodass der spieler sich schonmal auf festem grund und boden bewegen kann.
    Dannach werden pro step ein teil des nächsten Chunks geladen. Dabei ist es wichtig dass du nicht gleich ein ganzes chunk auf einmal ladest sondern immern nur einen kleinen teil.
    Auf die weise kann sich der Spieler immernoch frei in der Welt bewegen während das Spiel im Hintergrund die Welt ladet.
    > Das spielt hängt sich dadurch beim laden nicht gleich auf da das laden der Spielwelt auf mehrere steps verlagert wird.

    Das ganze währe natürlich mit multithreading wesentlich besser umsetzbar (vor alle da man dann einen weiteren CPU Kern verwenden könnte was die performance ordentlich boosten würde) aber ja... beim GM muss man da drumherumarbeiten.

    Ich versteh einfach nicht, warum bei der Verwendung von d3d_model_wall die for-Schleifen schneller abgearbeitet werden als mit Vertexen.

    Ich bin mir da nicht sicher ob das zutrifft da ich nie benchmarks in der richtung gemacht habe, aber es könnte sein dass die geschwindichkeit (zugunsten der d3d funktionen) auf die anzahl an aufrufen zurückzuführen ist.
    Wenn du den YYC nicht verwendest wird der interpreter verwendet. Bei den vertexbuffern hast du für das erstellen eines Quads mehrere aufrufe (pro vertex) > koordinaten, farbe und uv. (Jeder dieser befehle wird vom Interpreter verarbeitet)
    Bei den d3d modellen hast du nur einen aufruf (d3d model wall) wodurch der overhead der funktionsaufrufen minimiert wird. (Da evtl die d3d_model_ funktionen bereits nativ im GM vorgegeben sind was die ausführgeschwindichkeit erhöht.)
    Ist aber jetzt mal reine spekulation von meiner seite.

    Und mit den Modell komme ich ja eben, wie man oben sehen kann auf immerhin 20 FPS. Mit dem Vertexbuffer nicht. Obwohl der schneller sein sollte.

    Hast du schon versucht den buffer am ende (nach vertex_end() ) mit

    GML-Quellcode

    1. vertex_freeze(buffer);

    zu "freezen"? Auf die weise können beim zeichenaufruf so einige FPS rausgeholt werden.

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von LEWA ()

  • Was du machen musst ist die verarbeitung der Chunks auf mehrere steps zu verlagern (defakto threading selbst einbauen.)
    Anstatt alle chunks zu beginn in den Ram laden, ladest du z.B: nur ein einziges Chunk (und zwar das in welchem sich der spieler gerade befindet) sodass der spieler sich schonmal auf festem grund und boden bewegen kann.
    Dannach werden pro step ein teil des nächsten Chunks geladen. Dabei ist es wichtig dass du nicht gleich ein ganzes chunk auf einmal ladest sondern immern nur einen kleinen teil.
    Auf die weise kann sich der Spieler immernoch frei in der Welt bewegen während das Spiel im Hintergrund die Welt ladet.
    > Das spielt hängt sich dadurch beim laden nicht gleich auf da das laden der Spielwelt auf mehrere steps verlagert wird.


    Und das habe ich jetzt gemacht und ich bin mit dem Ergebnis sehr zufrieden. Sehet und stauned^^:



    Wobei ich mir nicht ganz die Mühe gemacht hab. Jeder Chunk wird komplett geladen. Dadurch "hakt" das Spiel manchmal kurz, wenn ein oder evtl. mehrere Chunks zum ersten Mal geladen werden. Aber ansonsten läuft das DIng jetzt bei 35 - 45 FPS.


    Ich bin mir da nicht sicher ob das zutrifft da ich nie benchmarks in der richtung gemacht habe, aber es könnte sein dass die geschwindichkeit (zugunsten der d3d funktionen) auf die anzahl an aufrufen zurückzuführen ist.
    Wenn du den YYC nicht verwendest wird der interpreter verwendet. Bei den vertexbuffern hast du für das erstellen eines Quads mehrere aufrufe (pro vertex) > koordinaten, farbe und uv. (Jeder dieser befehle wird vom Interpreter verarbeitet)
    Bei den d3d modellen hast du nur einen aufruf (d3d model wall) wodurch der overhead der funktionsaufrufen minimiert wird. (Da evtl die d3d_model_ funktionen bereits nativ im GM vorgegeben sind was die ausführgeschwindichkeit erhöht.)
    Ist aber jetzt mal reine spekulation von meiner seite.


    Könnte durchaus sein. Von deinem WIssen kann ich noch Manches lernen. :)

    Hast du schon versucht den buffer am ende (nach vertex_end() ) mit vertex_freeze...


    Ja und das bringt nicht viel weil das nur Frames bringt wenn man die Vertexe nicht anschaut. Also wenn man "wegguckt" gehen die FPS hoch und wenn man hinschaut gehen se wieder runter.
    Unter Global Game Settings -> Windows, kann man doch das Häkchen bei "Force Software Vertex Processing" setzen. Hat das was mit dem Vertex Buffer zutun? Oder was ist das?
  • Und das habe ich jetzt gemacht und ich bin mit dem Ergebnis sehr zufrieden. Sehet und stauned^^:

    Nicht schlecht. :) Jetzt das laden eines chunks auf mehrere steps verlagern und du hast es praktisch schon geschafft.^^

    Unter Global Game Settings -> Windows, kann man doch das Häkchen bei "Force Software Vertex Processing" setzen. Hat das was mit dem Vertex Buffer zutun? Oder was ist das?

    Aktivier das ja nicht.
    Damit aktivierst du sozusagen eine art "Software renderer" der kalkulationen (die normalerweise von der GPU übernommen werden) auf die CPU verlagert. Beispielsweise konnte man dadurch mehr als 8 lichter bei den d3d modellen setzen (die 8 lichter sind einfach eine limitierung der GPU da man gerade mal informationen für 8 lichter an den shader senden kann), das ging jedoch sehr stark auf die kosten der performance da die lichtkalkulationen auf der CPU seite ausgeführt wurden. (großes no-go)
    Da ich den source-code vom GM nicht habe kann ich auch nicht sagen was sonst noch alles auf die CPU verlagert wird. Da yoyogames (glaub das habe ich in der dokumentation gelesen) gesagt hat das diese option die kompatibilität mit älteren Rechner deutlich erhöhen kann (da die GPU teils durch die CPU ersetzt wird) nehme ich mal an dass da wesentlich mehr dahintersteckt.

    Kurzum: Die option ja nicht aktivieren.

    Hast du das etwa aktiviert gehabt?