Verzwickte Vertex Buffer GMS 1.4

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

  • Verzwickte Vertex Buffer GMS 1.4

    Guten Tag zusammen

    Ich bräuchte ein wenig Hilfe mit den Vertex buffern da ich noch nicht so viel Erfahrung haben mit denen.
    Mein Projekt ist ein 2D-Platform-block-random-Terrain Spiel, btw.

    Referenz (nicht teil des Problems):

    GML-Quellcode

    1. if (vertex_submitted == false)
    2. {
    3. var b = global.v_buff;
    4. var v = global.v_format;
    5. vertex_begin(b, v);
    6. for (var i = 0; i < 128; i++)
    7. {
    8. // get x positions
    9. var x1 = i * 16;
    10. var x2 = x1 + 16;
    11. for (var j = 0; j < 128; j++)
    12. {
    13. var cell = tiles[@ i, j]; // the array is either 0, 1, 2 or 3
    14. if (cell != 0)
    15. {
    16. var spr = lut[@ cell]; // the numbers 1, 2, 3 will declare the sprite
    17. var img = irandom(10); // for now random
    18. var vec4 = sprite_get_uvs(spr, img);
    19. // get y positions
    20. var y1 = j * 16;
    21. var y2 = y1 + 16;
    22. // 1st triangle
    23. vertex_position(b, x1, y1);
    24. vertex_texcoord(b, vec4[0], vec4[1]);
    25. vertex_position(b, x2, y1);
    26. vertex_texcoord(b, vec4[2], vec4[1]);
    27. vertex_position(b, x2, y2);
    28. vertex_texcoord(b, vec4[2], vec4[3]);
    29. // 2nd triangle
    30. vertex_position(b, x2, y2);
    31. vertex_texcoord(b, vec4[2], vec4[3]);
    32. vertex_position(b, x1, y2);
    33. vertex_texcoord(b, vec4[0], vec4[3]);
    34. vertex_position(b, x1, y1);
    35. vertex_texcoord(b, vec4[0], vec4[1]);
    36. }
    37. }
    38. }
    39. //terminate
    40. vertex_end(b);
    41. tex = sprite_get_texture(spr, 0);
    42. vertex_submitted = true;
    43. }
    44. else
    45. {
    46. vertex_submit(global.v_buff, pr_trianglelist, tex);
    47. }
    Alles anzeigen


    Das ist mein code, dieser Funktioniert einwandfrei. Auch das Format funktioniert (vertex_position und vertex_texcoord).
    Das Problem ist nur das der eigentlich Dynamisch sein sollte, bez. Der vertex buffer soll in real time editierbar sein.
    Natürlich ist das nicht möglich mit den built-in Funktionen von GMS 1.4

    Aber vielleicht weiss hier Jemand wie sowas machbar ist.
    Und wenn die einzige Möglichkeit wirklich nur mit dem vertex-shader ist, wäre diese Person bereit mir das zu erklären.
    Ich hab sowas keine Ahnung von vertex-shadern. Ich komm bei fragment-shadern gut draus aber das ist mir unnütz für dieses Problem.

    Fakten und Zahlen:
    Den vertex Buffer jeden Frame erneuern brauch etwa 50 ms, was absolut nicht brauchbar ist.
    der vertex_submit brauch etwa 3 ms (not frozen), was genügend aber nicht optimal ist.

    Der vertex Buffer wird die Grösse 128 x 128 nicht überschreiten da jeder Block 16 x 16 ist, und die Auflösung maximal 1920 x 1440.
    -> 16384 iterationen.

    Auch Vorschläge welche nicht die Lösung sind, sind willkommen :)
  • Ich hab mir ein par Überlegungen gemacht und habe eine Idee:
    Ich könnte die vertex_buffer_create_from_buffer benutzen.
    Wie in der Illustration könnte ich versuchen nur die normalen buffer zu ändern und sie dann zu den vertex buffern transformieren.

    Bin mir nur nicht sicher wie lange die transformation dauert.
    Und wahrscheinlich gibt es probleme mir der aufflistung des buffers, da es sich im 2D bereich befindet und buffer nur 1D sind.

    Meinungen willkommen
    Bilder
    • test.png

      2,57 kB, 450×159, 124 mal angesehen
  • Vielleicht ne bessere Methode, ohne die vertex buffer zu editieren. sprite-batching ist wahrscheinlich der Weg zum Ziel.
    Nur stelle ich mir die Frage ob vertex_submit() den vertex Batch auseinander reisst. Teste das mal wenn ich zuhause bin.

    [EDIT]
    Der Batch wird zerrissen was natürlich nicht optimal ist, teste weiter...

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

  • Gute Neuigkeiten (für mich immerhin)

    Im GMC habe ich ungefähr die selbe Fragen gestellt und dort sind mir fel666 und mishmash beigestanden.
    Wir haben herausgefunden, dass jeder vertex submit, den Batch zerreisst und man somit nur an vram sparen kann beim vergleich mit surfaces.
    fel666 hat vorgeschlagen einen buffer to vbuffer chunk System zu kreieren, was ich aber erwidert habe.

    Eine weile später bin ich dann auf die Idee gekommen, mit einem Shader alles manuell zu zeichnen, dort hat mir mishmash zugestimmt und mir die Basics erzählt.

    Ich hab mich hingesessen und einfach mal angefangen. Ich bin fast fertig, es fehlt nur noch die licht-Funktionen.
    Die Performance ist (bis jetzt) überwältigend.

    Ich werde dann wenn ich fertig bin, meine Ergebnisse hier übertragen.
    Hier noch der thread im GMC forum.yoyogames.com/index.php?…drawing-clunkiness.25367/
  • Rhazul schrieb:

    Gut das es für dich vorangeht, vertexbuffer hab ich leider noch nicht benutzt in GM.Bin mal gespannt.


    Naja vertex buffer hab ich ganz weg geschmissen. Sie sind eher so für 3D geeignet.
  • Probleme gelöst!
    Wie es funktioniert:
    Spoiler anzeigen

    In dieser Welt die random generiert wurde werden alle Block Informationen in einem Array gepeichert.
    Zuvor beim rendern habe ich alle Block-sprites auf einen 2048 x 2048 surface gezeichnet und den dann strip-weise aktualisiert und schliesslich in den Backbuffer gezeichnet.
    Da diese Surfaces aber extrem viel vram brauchen und ich mindestens 6 dieser Monster brauchte, war ich garantiert in ein Problem gelaufen. Zudem war das Strip-zeichnen relativ langsam.
    Das Licht vorher sah anders aus und war etwa 256 mal langsamer als jetzt.

    Nun habe ich ein kleiner surface 128 x 128 auf dem ich alle Informationen vom Array als Farbcode daraufzeichne. Aktualisiert wird immer noch strip-weise. Sobald der Surface voll ist (oder leer) schick ich den in den shader.
    Dort wird mit komplizierten Berechnungen den Block manuell gezeichnet UND automatisch richtig gestellt (auto tiling). Die Informationen damit die richtigen Blöcke gezeichnet werden befinden sich auf einem surface auf dem ich alle Block-Graphiken gezeichnet habe. Der Shader zeichnet das ganze auf einen herkömmlichen sprite welcher dann in den Backbuffer getan wird.

    Bevor die Pixel im Shader aber gezeichnet werden gebe ich noch den anderen surface mit den Licht-Informationen hinzu.
    Das ganze ist extrem kompliziert und definitiv auf experten Level.
    Bilder
    • screenshot6.png

      69,64 kB, 1.920×1.080, 110 mal angesehen
  • Erinnert mich an das uralte Projekt hier (von 2014):


    Wer will kann sich das ganze gern mal hier runterladen und verwenden wenn er irgendwas hilfreiches darauß zieht, allerdings keine Gewähr für index out of bound errors und so Späße. Die Welt wird mit einem Perlin noise generiert der für Höhlen sorgt, die Beleuchtung ist mit einem Shader realisiert worden(nicht meiner).

    DOWNLOAD
    132 little bugs in the code. 132 little bugs. Fix a few, set the compiler to stew, 172 little bugs in the code... :vogel:
  • Husi012 schrieb:

    Autotiling mit einem Shader? Why not.
    Der Code interessiert mich :D

    Ich kann den Code teilen, das Problem ist nur das alles so zusammenhängend ist und man alles brauch damit nur das Eine funktioniert.
  • tile Rendering

    GML-Quellcode

    1. varying vec2 v_vTexcoord;
    2. varying vec4 v_vColour;
    3. uniform sampler2D texture; // Informationen der Umgebung des Spielers
    4. uniform sampler2D tex_page; // Textur mit allen tile-graphiken
    5. uniform sampler2D luminous; // Textur für das Lichtsystem
    6. vec2 base_pos;
    7. vec2 position;
    8. vec4 color = vec4(0.0, 0.0, 0.0, 0.0);
    9. float mX = 1.0 / 2048.0; // texel der tex_page
    10. float mY = 1.0 / 2048.0;
    11. float fX = 1.0 / 128.0; // texel der texture und luminous
    12. float fY = 1.0 / 128.0;
    13. void main()
    14. {
    15. // color
    16. float red = texture2D( texture, v_vTexcoord ).r; // rot = block Informationen (stein, erde, grass) ( x Richtung auf der tex_page)
    17. float grn = 0.0; // tile index ( y Richtung auf der tex_page)
    18. float blu = texture2D( luminous, v_vTexcoord ).b; // blau = licht (1.0 = hell, 0.0 = dunkel)
    19. vec4 light = vec4(blu, blu, blu, v_vColour.a); // licht einsetzen
    20. // frame (4-weg autotiler)
    21. float lft = texture2D( texture, vec2(v_vTexcoord.x - fX, v_vTexcoord.y)).r;
    22. if (lft == 0.0) grn += 8.0;
    23. float top = texture2D( texture, vec2(v_vTexcoord.x, v_vTexcoord.y - fY)).r;
    24. if (top == 0.0) grn += 4.0;
    25. float rgt = texture2D( texture, vec2(v_vTexcoord.x + fX, v_vTexcoord.y)).r;
    26. if (rgt == 0.0) grn += 2.0;
    27. float bot = texture2D( texture, vec2(v_vTexcoord.x, v_vTexcoord.y + fY)).r;
    28. if (bot == 0.0) grn += 1.0;
    29. // base position
    30. float xx = mod(v_vTexcoord.x, fX); // damit alle Pixel von der richtigen Position auf der tex_page genommen werden
    31. float yy = mod(v_vTexcoord.y, fY); //
    32. // calculate
    33. if (red > 0.0)
    34. {
    35. float frameX = red * 255.0 * 16.0; // sprite
    36. float frameY = grn * 16.0; // index
    37. base_pos = vec2(frameX * mX, frameY * mY);
    38. position = vec2(base_pos.x + xx , base_pos.y + yy);
    39. color = texture2D( tex_page, position );
    40. }
    41. // terminate
    42. gl_FragColor = light * color;
    43. }
    Alles anzeigen

  • Ah, sehr interessant. Dachte erst, du willst das Autotiling im Shader selbst machen, also ohne dass du das vorher präparierst :D
    Ein Bug ist mehr als nur ein Bug, es ist ein... Käfer!
    Egal, wie gut du eine Mauer baust, sie fällt um.... der klügere gibt nach :D

    Willst du mit mir auf Discord Chatten/Quatschen?
    Meine Husi's Tutorial Reihe
  • glim888 schrieb:

    Ich habe es nur mal kurz angeschaut.

    Ich würde das:

    GML-Quellcode

    1. if (lft == 0.0) grn += 8.0;


    runden und dann abfragen.


    Warum denn runden?
    0.0 ist einfach wenn keine Farbe dort ist.
    Könnte aber auch anstatt "keinen Block auf Seite", "Der selbe Block auf Seite" abfragen.
  • Husi012 schrieb:

    Ah, sehr interessant. Dachte erst, du willst das Autotiling im Shader selbst machen, also ohne dass du das vorher präparierst :D


    Bin mir jetzt nicht sicher was genau du meinst.
    Also direkt im Shader die Pixel anpassen damit sie sich "Vermischen"?
    Oder so wie ich, dass sie einfach von einem anderen Ort lesen

    Im Anhang ein screenshot.
    Der Erste surface ist kaum erkennbar. Aber da sind definitiv einige Pixel nicht ganz schwarz.
    Der Zweite ist für das Licht.
    Der Dritte ist der mit den Block-Graphiken die gepullt werden.
    Bilder
    • screenshot7.png

      114,9 kB, 1.920×1.080, 124 mal angesehen
  • glim888 schrieb:

    Ich habe vor einiger Zeit mal einen "Anschiss" bekommen, weil ich das so wie du gemacht habe.

    Also, you should never compare a float exactly equal to something because of imprecision with the floating point data type.


    Ah ja das macht Sinn.