Objekte nur im SIchtfeld des Spielers zeichnen (3d)

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

  • Objekte nur im SIchtfeld des Spielers zeichnen (3d)

    Hallo, hat jemand eine Idee wie ich Dinge nur im SIchtfeld des Spielers zeichnen lasse, im 3d-Modus? Momentan lasse ich nur die Instanzen zeichnen, deren Distanz zum Spieler gering ist. Außerdem benutze ich einen Fog, damit es nicht so ausieht, als würden DInge aus dem Nichts auftauchen. Das macht das Spiel schon wesentlich schneller allerdings werden aber ja immernoch DInge gezeichnet zu denen der SPieler den Rücken zuwendet. Es könnte noch schneller laufen wenn nur das gezeichnet wird, was der Spieler sieht. (Oh man, der GM mag einfach nicht, dass man 3d-Spiele mit ihm entwickelt :----S) Hat jemand eine Idee, jemand der sich damit vll schon beschäftigt hat? LEWA vielleicht?
  • Was du da beschreibst ist als "Occlusion Culling" bekannt.

    Nunja, sowas im GM zu implementieren ist ... in den seltensten Fällen sinnvoll.

    Das Problem ist dass du die Berechnungen (ob was innerhalb der kamera sichtbar ist oder nicht) auf der CPU durchführen musst, was zu einem Performanceoverhead auf der CPU seite führt.
    (Evtl. könnte da der YYC aushelfen... müsste man austesten inwieweit sich das lohnen würde...)

    Das Problem am GM ist dass die meisten Bottlenecks auf die CPU performance zurückzuführen sind. Die GPU hingegen hat oftmals noch sehr viel Spielraum was Auslastung angeht.
    Mein Ansatz war immer der, dass ich versucht habe so viele Berechnungen wie nur möglich auf die GPU zu verlagern um die CPU zu entlasten. (ermöglicht es niedrigere CPU leistung vorauszusetzen oder man kann die gewonnene leistung für weiteren spielcode verwenden.)

    Da die CPU meistens mit Spielcode belastet wird und die GPU (da ich mal stark annehme dass du keine High-poly modelle verwendest und die Spiele nicht wie das nächste Crysis ausschauen) meistens trotz des Renderings immernoch genug Raum zum atmen hat, würde das Occlusion culling nur weitere Leistung von der GPU auf die CPU verlagern. (Was nicht optimal ist.)

    Das würde sich also wirklich nur lohnen wenn das Spiel stark GPU belastend ist und die CPU noch genug Leistungsreserven bereitstellt um pro objekt aufwändigerere Berechnungen durchzuführen.

    Versuche stattdessen die Draw-calls zu verringern. Fasse mehrere kleinere Modelle zu einem großen zusammen sodass die CPU mit geringem aufwand der GPU befehlen kann die ganze Szene zu zeichnen.
    (Die draw-calls sind in 99% der Fälle der Bottleneck! > Das ist ein CPU seitiges Problem. Im worst-case Szenario könnte Occlusion culling die Performance sogar noch stärker belasten.)

    Oder gibt es da in deinem Projekt etwas spezielles was man beachten muss?

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

  • Leider gibt es in meinen Projekt sehr viele Draw-calls, da das Level (ein Dungeon) random aus vielen, vielen kleinen Würfeln generiert wird. Und jeder Würfel ist eine Instanz, die im Drawevent Wände zeichnet. Es werden nur die Würfel gezeichnet die man sehen könnte, nicht die dahinter. Und die Sichtweite ist schon sehr gering (mit fog) damit es mit (leider nur) 30 FPS flüssig läuft. (Intel Core Duo 2,10 GHz) Ich hab auch schon versucht, dass zu beschleunigen wenn ich von einem Objekt aus das Draw-Event für alle sichtbaren Würfel calle. Macht's sogar noch langsamer. Ich habe absolut keine Idee, wie ich das schneller machen kann, ohne die Würfel einfach größer zumachen, was die Höhle nicht mehr so nach Höhle aussehen lassen würde.
  • Naja die würfel könntest du doch alle zu einem Modell (zur laufzeit) zusammenpacken.
    Bei mir hatte ich das im Projekt auch: Viele kleine Blöcke die im der Spielwelt plaziert werden.
    Da hätte ich bei 1000 Blöcken rund 1000 draw-calls. (ohne den Spiegelungen mit den ganzen Post-processing effekten die weitere renderpasses benötigen...)

    Stattdessen habe ich ein einziges 3D level modell welches anfangs leer ist. (keine vertexe)
    Beim start eines levels durchlaufe ich die einzelnen Objekte mit einer Schleife und generiere mir anhand deren Parameter (xyz Koordinate, farbe, hoehe, breite, etc...) ein 3D modell was direkt in das Levelmodell gespeichert ist.
    > Dadurch habe ich die ganze Levelgeometrie in einem VertexBuffer was die Performance enorm steigert. (> ich arbeite auf einem Core 2 Quad mit 2.0 GHz. Der Unterschied bei der Kernanzahl zwischen deinem Duo und meinem Quad ist hier irrelevant, da GM Studio sowieso nur singlethreaded ist.)
    Ich kann dadurch problemlos über tausend Blöcke in der Szene haben ohne das mir die Framerate einbricht. (auf GM Studio bekomme ich mit den ganzen Shadern ca 200 FPS. > liegt an der GPU. Ohne den Post-processing effekten komme ich auf ca 400-500 FPS. Das alles ohne den YYC (edit: gerade nochmal geschaut. Stellenweise komme ich sogar auf 600-700 FPS. Schwankt recht stark.)

    Wenn deine Blöcke komplexere 3D modelle sind (sodass das nachgenerieren per code umständlich bzw. langsam wäre) würde ich dir u.a. zu Blender raten.
    Dort könntest du das ganze Level modellieren und es vor dem Export als .obj datei in ein ganzes Modell zusammenfassen. (Da kannst du sogar etwas optimieren, da du genau entscheiden kannst was wie zusammengefasst wird.)

    Ich habe für den GM einen .obj importer geschrieben (welcher sogar spezifisch für Blenders .obj formatierung gemacht wurde) sodass du problemlos Modelle von Blender in den GM laden kannst.

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

  • Ist ja lustig, während ich grad eine rauchen war bin ich auch auf die Idee gekommen alle Würfel in einem Model zuspeichern. Dass werde ich gleich ma umsetzen. Als 3d-Anfänger kam ich da halt nicht gleich drauf. :) Dank dir für deine ausführlichen und kompetenten Antworten LEWA. :)
  • Vielleicht übersiehst du da was in deinem Code.
    Prüf nochmal nach ob du z.B: pro block nicht die ganze levelgeometrie nochmals neu zeichnest.

    Ansonsten kann ich nicht sagen was da los sein könnte, da ich keinerlei Informationen über deinen Code habe.
  • Also mein Code sieht so aus: Einmal in einem Objekt:

    GML-Quellcode

    1. //Dungeon erzeugen
    2. global.mod_dungeon = d3d_model_create();
    3. for (i=0; i<room_width; i+=8)
    4. {
    5. for (j=0; j<room_height; j+=8)
    6. {
    7. if ds_grid_get(global.grid, i, j) = 0
    8. {
    9. instance_create(i,j,obj_block);
    10. d3d_model_block(global.mod_dungeon, i, j, 0, i+8, j+8, 48, .5, 4)
    11. }
    12. }
    13. }
    Alles anzeigen


    Und dann in einem anderen, dass das Dungeon zeichnen soll im Drawevent:

    GML-Quellcode

    1. //Wände
    2. d3d_model_draw(global.mod_dungeon, 0, 0, 0, tex);


    Sind dass vielleicht doch zuviele Würfel für den Vertexbuffer? Denn die Raumgröße ist 2400*2400.
  • Sind dass vielleicht doch zuviele Würfel für den Vertexbuffer? Denn die Raumgröße ist 2400*2400.

    kann das nicht so pauschal sagen. Wenn ich das richtig sehe sollten das ca 90000 würfel sein.

    Wenn wirklich nichts anderes (asser das dungeon) gezeichnet wird, könnte es durchaus sein dass deine GPU ein bottleneck ist.
    Was für eine GPU hast du denn? Evtl könntest du ein kompiliertes example hochladen wo ich mal die performance auf meinem Rechner testen könnte?

    Ausserdem:
    Die d3d_model ... formen sind in deinem Bereich etwas ineffizient.
    Ich nehme mal an die Blöcke sind alle am Boden positioniert. Der d3d_model_block erstellt auf jeder Seite 2 Triangles. (auc hauf der unterseite) was bei so einer masse an Polygonen doch einen merkbaren performanceeinbruch mit sich ziehen kann. (vor allem auf schwachen GPUs.)
    Lösung: Blöcke mit den integrierten Vertexfunktionen selber machen.

    /Edit: bzw. der Code schaut so wie er ist richtig aus.
    /Edit2:
    Um noch mehr performance rauszuholen solltest du Vertex-Buffer verwenden (die sind nochmals schneller als die d3d modelle)

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

  • Der Code ist jetzt wesentlich effizienter. Der Raum wird jetzt in mehrere Bereiche unterteilt und jeder Berreich zeichnet ein Model für alle Würfel in diesem Bereich wenn der Spieler in der Nähe ist. Außerdem werden den Modellen nur noch Wände hinzugefügt die sichtbar sind und nicht Wände hinter Wänden. Der Code sieht jetzt so aus:

    GML-Quellcode

    1. //Dungeon erzeugen
    2. for (n=0; n<room_width; n+=480)
    3. {
    4. for (m=0; m<room_height; m+=480)
    5. {
    6. modnumber += 1;
    7. global.mod_dungeon[modnumber] = d3d_model_create();
    8. for (i=n; i<n+480; i+=8)
    9. {
    10. for (j=m; j<m+480; j+=8)
    11. {
    12. if ds_grid_get(global.grid, i, j) = 0
    13. {
    14. instance_create(i,j,obj_block);
    15. if ds_grid_get(global.grid, i-8, j) = 1 d3d_model_wall(global.mod_dungeon[modnumber],i,j+8,0,i,j,48,.5,4)
    16. if ds_grid_get(global.grid, i+8, j) = 1 d3d_model_wall(global.mod_dungeon[modnumber],i+8,j,0,i+8,j+8,48,.5,4);
    17. if ds_grid_get(global.grid, i, j-8) = 1 d3d_model_wall(global.mod_dungeon[modnumber],i+8,j,0,i,j,48,.5,4);
    18. if ds_grid_get(global.grid, i, j+8) = 1 d3d_model_wall(global.mod_dungeon[modnumber],i,j+8,0,i+8,j+8,48,.5,4);
    19. }
    20. }
    21. }
    22. with (instance_create(n+240,m+240,dungeon_draw)) direction = other.modnumber; //in der direction wird die Modelnummer gepeichert
    23. }
    24. }
    Alles anzeigen


    Aber wenn du magst könntest du mir noch erklären wie ich den Vertex-Buffer verwenden kann, LEWA. Muss ich da mit d3d_primitive_begin arbeiten? Wenn ja müssted man mir da ein bißchen helfen, denn das hab ich noch nie verwendet und ich hab kein Plan wie ich die Würfel, mit korrekt gesetzter Textur damit zeichnen lasse.
  • Sofern deine Performance sich jetzt im grünen Bereich befindet, musst du nicht auf Vertex-buffer umsteigen.
    Vertex buffer können aber die performance erhöhen, da du wesentlich mehr optionen (und deshalb auch optimierungsmöglichkeiten) bei diesen hast.
    Ausserdem habe ich auf der GMC gelesen dass diese von der Performance her auch generell schneller sein sollen. (Hab selbst keine performacnetests gemacht, aber laut einigen Usern die benchmarks durchgeführt haben sind diese wirklich schneller.)

    Du kannst zu Vertexbuffern auf in der Game Maker Dokumentation weiteres nachlesen:
    docs.yoyogames.com

    Vertexbuffer sind defakto zwischenspeicher für 3D Modell daten, bei denen du selbst entscheiden kannst was (und wie) etwas gespeichert wird.

    Als erstes musst du z.B: ein Vertexformat erstellen, nach dem du deine Meshes ausrichten wirst:

    GML-Quellcode

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

    Das obere Format speichert somit die 3D Position des vertexes, die farbe und die texturcoordinate. (Normals werden nicht gespeichert.)
    Falls du Normals brauchen solltest, musst du sie hier auch einfügen.

    Dannach kannst du den Vertexbuffer befüllen. Bedenke dass du die Vertexe mitsamt der Informationen (3d position, farbe, uv koordinaten)
    selbst einfügen musst. Es gibt auch keine "d3d_model_wall",etc.. funktionen. Du wirst dir die ganzen formen selbst zusammenbauen müssen.

    GML-Quellcode

    1. v_buff = vertex_create_buffer(); //Vertexbuffer erstellen
    2. vertex_begin(v_buff, global.my_format); //Buffer nun beschreiben (nach dem vorher definierten format)
    3. //-------erstellen eines Triangles--------
    4. //Vertex 1 (Jeder vertex muss nach dem schema des Vertexformats gebaut werden!)
    5. vertex_position(v_buff, 10, 10);//3d position
    6. vertex_colour(v_buff, c_white, 1);//farbe
    7. vertex_texcoord(v_buff, 0, 0);//uv koordinate
    8. //Vertex2
    9. vertex_position(v_buff, 110, 10);
    10. vertex_colour(v_buff, c_white, 1);
    11. vertex_texcoord(v_buff, 1, 0);
    12. //Vertex3
    13. vertex_position(v_buff, 110, 110);
    14. vertex_colour(v_buff, c_white, 1);
    15. vertex_texcoord(v_buff, 1, 1);
    16. ----------------------------------------
    17. //abschluss
    18. vertex_end(v_buff);
    Alles anzeigen


    Hier würde sich es anbieten eigene Scripts für die Grundformen zu schreiben um die d3d_model_... Funktionen zu ersetzen.

    So zeichnet man den Buffer

    GML-Quellcode

    1. //Vertexbuffer zeichnen
    2. var tex = background_get_texture(background1);
    3. shader_set(shader_prim); // shader muss verwendet werden (erstelle einfach einen neuen Shader. Der defaultcode reicht aus.)
    4. vertex_submit(v_buff, pr_trianglelist, tex);//zeichnen (wie d3d_model_draw)
    5. shader_reset();


    Wie gesagt, wenn es aktuell bei dir flüssig genug läuft, musst du das nicht unbedingt machen. Willst du jedoch die Kontrolle darüber haben und weitere Optimierungen durchführen, so kann ich Vertexbuffers nur empfehlen.
    bzw. Was für eine GPU hat denn dein Rechner?

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

  • Echt cool das du dir immer so viel Mühe machst bei deinen Antworten. Es läuft jetzt flüssig, daher werde ich es wahrscheinlich erst mal so lassen. Meine GPU ist eine GeForce 9650M GT 32 @ 550 MHz128 Bit @ 800 MHz Speicher 1024 MB
  • Ich würde dass jetzt doch mal gerne mit Vertexen probieren, da die fps jetzt doch etwas runter gehen, da ich jetzt mehr Modelle verwende. Den COde den du geschriben hast LEWA, der funzt nur in GM STudio. Ich verwende aber GM 8.1. Wie muss ich das da coden? Und wenn wir schon dabei sind, wie kann ich einen Wüfel mit korrekt gesetzter Textur mit Vertexen coden. Ist die Benutzung von Vertexen in GM 8.1 acuh schneller als die von Modellen?
  • Den COde den du geschriben hast LEWA, der funzt nur in GM STudio. Ich verwende aber GM 8.1. Wie muss ich das da coden?

    Die Vertexbuffer funktionen gibt es nur seit Studio. In GM 8.1 kannst du nur die d3d Funktionen zur modellerstellung verwenden.

    Und wenn wir schon dabei sind, wie kann ich einen Wüfel mit korrekt gesetzter Textur mit Vertexen coden. Ist die Benutzung von Vertexen in GM 8.1 acuh schneller als die von Modellen?

    Die Grundformen selber mit Vertexen zu bauen (in bezug auf d3d modelle) hat nur dann einen performancevorteil wenn du nicht benutzte Polygone einfach weglässt. (also wie bei den Blöcken wo am Boden keine Polygone plaziert werden müssen.)
    Beim GM 8.1 ist man was dies angeht etwas limitiert.

    Ich würde dass jetzt doch mal gerne mit Vertexen probieren, da die fps jetzt doch etwas runter gehen, da ich jetzt mehr Modelle verwende.

    Deinen PC-Daten nach zu urteilen hast du defakto eine etwas schwächere Mobil-variante meines Heimrechners vor dir stehen. (Du hast einen mobilen Dualcore, ich einen Quad, beide auf ca 2GHz getaktet. Du hast eine GeForce 9650M GT und ich eine Geforce 9600 GT mit 512 MB Ram.)
    Und da dein GPU Speicher scheinbar auf 800MHz getaktet ist, hast du auch das schnellere GDDR3 V-Ram statt das langsamere GDDR2.
    Zwar ist deiner auch ein Laptop, ich kann mir aber nicht vorstellen dass dieser wirklich so schlechte performance aufweist.

    Zitat von Notebookcheck.com:
    Im Vergleich zu Desktop Grafikkarten lässt sich die 9650M GT am besten mit der ebenfalls auf den G96 Kern basierenden Geforce 9500 GT vergleichen (die Desktop 9600 GT hat einen breiteren Speicherbus und ist dadurch deutlich schneller).

    Link

    Von daher habe ich aktuell auch keine Ahnung ob die langsame performance jetzt auf die Rechenleistung des Rechners zurückzuführen ist oder ob du bei deinem Projekt noch irgendwo einen Bottleneck hast.

    /Edit: Verwendest du irgendwelche 3D Lichter in der Scene?

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

  • Ok danke erstamal aber das stimmt mich jetzt etwas ärgerlich. Die Modelle die ich verwende haben wirklich nur sehr wenig faces, nicht zu vergleichen mit deinem coolen Echsenviech aus deinem Celaria. Da ich glaube, dass der GM 8 von der Performance her, nicht sehr viel schlechter als GM Studio ist, muss ich wohl in meinem Projekt irgendwo ein oder mehrere Bottlenecks haben. Doch wie finde ich die jetzt am besten? Wie geht man denn dabei am besten vor.... moment ich hab ne Idee, eigentlich wollte ich damit warten aber hier kann mal mal mein Spiel runterladen:

    file-upload.net/download-10163452/rogue_3d---Kopie.rar.html

    Wie gut läuft das bei euch? Bei mir gehen die fps schon ab und zu runter und das nervt mich.
    Achso wenn's schon getestet wird: Nicht wundern, die ersten paar Sekunden wird die Map generiert, dass dauert paar Sekunden und bedeutet, dass der Bildschirm schwarz bleibt. Haltet "M" gedrückt um eine Karte anzeigen zulassen. Linksklick schießen und mit "E" öffnet man Truhen.
  • Könnte es sein dass du die FPS bei der 120fps version nicht verändert hast? Ich komme bei beiden auf maximal 30 (größtenteils stabil) wobei hier und da framerateeinbruche auf ca 25-27 FPS auftauchen.

    Habe mal kurz in den Taskmanager reingeschaut und siehe da: Der CPU kern wird voll ausgelastet.
    Du hast also wirklich irgendwo sehr viele Draw-calls die dies verursachen oder deine Spiellogik ist rechenintensiv.
    Ausserdem hast du eine Memoryauslastung vom 500MB ram... Hast du so viele Instanzen im Spiel, oder was genau verursacht den hohen Ram verbrauch? (Die 500 MB erscheinen mir für so ein Spiel etwas zu viel.) Wenn es wirklich viele Instanzen sind die z.B: zur kollissionsberechnung verwendet werden, dann macht es durchaus Sinn die instance_activate und instance_deactivate funktionen zu verwenden (um die Instanzen die ausserhalb eines bestimmten Bereichs liegen zu deaktivieren), da jede aktive Instanz an der Performance zerren kann, sofern die für irgendwelche Berechnungen verwendet wird oder Code ausführt.

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

  • Ich hab nur die 120-FPS Version getestet, hab damit immer über 30 FPS, aber stark schwankend und meist unter 40. Das obwohl das Spiel nur 7% CPU Last bringt und auch die Grafikkarte auf minimal Geschwindigkeit läuft. Das die Auslastung nicht allzu hoch ist, ist bei meinem aktuellen Rechner nicht verwunderlich, aber das die FPS trotzdem nicht über 40 kommen allerdings schon.
    Memoryauslastung ist natürlich dasselbe wie bei LEWA.
  • Ich habe jetz nicht auf meine CPU auslastung geschaut aber ich hatte kein Problem mit der 30FPS Version und bei der 120er hatte ich meistens konstant 30 oder 60 FPS und hin und wieder ist er irgendwo dazwischen gewesen. Aber ich hatte oft im Spawnraum zuerst 60 und später nurmehr 30 FPS.

    ancient-pixel.com
    youtube.com/user/SebastianMerkl <<< ich freu mich über einen Besuch ;)