OpenGL Performanceproblem
-
Hi!
Ich hab in eine GUI-Oberfläche OpenGL eingebettet, um eine Landschaft abzubilden. Leider hab ich nicht so viel Ahnung von OpenGL (fast gar keine) und das Ganze läuft recht langsam. Ich hab gestern ein wenig rum-gegoogelt und bin auf die OpenGL-Listen gestoßen, also glNewList, glCallList usw. Damit läuft es nun ein wenig schneller, aber noch lang nicht so schnell, wie ich's gerne hätte.
Meine Frage: Hab mitzählen lassen, es sind z.Zt. insgesamt 218.300 Dreiecke, ist das vielleicht einfach zuviel? Ich baue am Anfang die Liste und mache mit glVertex3d meine Dreiecke. Zum Aufbauen der Liste ist die Geschwindigkeit egal, nur wenn ich das Ding (mit der Maus) drehe, rotiere ich das Ganze ein wenig, was mir halt zu langsam ist. Zu viele Polygone oder falsche Technik?
Vielen Dank und Grüße,
Badestrandedit: Läuft auf einem recht neuen Rechner unter Windows, ich könnte auch den Quellcode (MSVC++2003)posten, aber der sieht _wirklich_ grausig aus

-
so wie ich das mitgekriegt habe, lässt du immer deine GANZE landschaft zeichnen, was aber nicht sonderlich sinnvoll ist (je nach anwendungszweck). Es gibt algorithmen (du kannst dir auch welche selbst schreiben), die das terrain bei zunehmender entfernung von der kamera vereinfachen, also z.B. anstatt vier polygone nur noch eins zeichnen, das den Mittelwert dieser vier polygone darstellt. das ist ganz gut hier beschrieben.
-
218.300 Dreiecke
ist eigentlich nicht sehr viel.
versuche sicherzustellen, dass eine displayliste nicht mehr als 64000 unterschiedliche vertices enthaellt.
-
Gut, danke euch beiden, ich versuche mich mal dran

-
Das Wichtigste ist, das du vorher berechnest was von deiner Landschaft zu sehen ist und was nicht.
http://wiki.delphigl.com/index.php/Frustum_CullingDenn jedes unnötig gezeichnete Dreieck verschwendet Geschwindigkeit.
(Das Hauptproblem wird überigens nicht die Grafikkarte sein sondern der Bus zur Grafikkarte.)Außerdem kannst du versuchen z.B mit
glBegin(GL_TRIANGLE_STRIP);zu arbeiten anstatt mit
glBegin(GL_TRIANGLES);Dann sparst du ab dem 2. Dreieck 2 Vertics pro Dreieck ein.
Dann wie schon im Beitrag von "Heinzelotto" erwähnt kannst du LOD Algorythmen verwenden.
(Ein einfacher ist z.B landschaft die nah an der kamera ist genau zu zeichnen und wenn die Landschaft weiter weg ist nur noch doppelt so große Flächen zu zeichnen. Pass aber auf das keine T Stellen entstehen wie diese:----------------- | | | | |------- | | | ----------------In der Mitte da wo es aussieht wie ein auf der Seite liegendes T können Lücken entstehen wenn man unterschiedlich große Vierecke aneinander zeichnet.
(Vor allem wenn eins mehr als doppelt so groß ist wie das andere)Hier ein komplizierterer Algorithmus http://wiki.delphigl.com/index.php/Tutorial_Terrain3
Ich bastele auch als Hobby an der Anzeige einer landschaft. Als ich noch keine Ahnung von all diesen Techniken zur Geschwindigkeitsverbesserung hatte erreichte ich 35 Bilder pro Sekunde.
Jetzt wo ich vieles (noch längst nicht alles) eingebaut habe erreiche ich bei gleich aussehender Landschaft auf dem selben Computer ca. 420 Bilder pro Sekunde.Schau dir mal generell diese 3 Tutorials an. (ist zwar kein c++ aber die Idee sollte rüberkommen)
http://wiki.delphigl.com/index.php/Tutorial_Terrain1
http://wiki.delphigl.com/index.php/Tutorial_Terrain2
http://wiki.delphigl.com/index.php/Tutorial_Terrain3
-
Verwende VBOs (Vertex Buffer Objects) anstelle der Display List.
-
Verwende VBOs (Vertex Buffer Objects) anstelle der Display List.
das passiert im treiber sowieso schon. je nach treiber-qualitaet passieren im rahmen der display-liste auch noch zusaetzliche optimierungen die allerhand eigeninitiative erfordern wuerden. vbos sind nur bei nicht-statischer geometrie zu bevorzugen.
-
Badestrand schrieb:
das Ganze läuft recht langsam
wir programmierer moegen das lieber genauer als diese weihen gefuehls definitionen

Badestrand schrieb:
edit: Läuft auf einem recht neuen Rechner unter Windows
bitte ein wenig genauer, besonders was die graka angeht.
hellihjb schrieb:
218.300 Dreiecke
ist eigentlich nicht sehr viel.
versuche sicherzustellen, dass eine displayliste nicht mehr als 64000 unterschiedliche vertices enthaellt.64000 ist bei displaylisten kein gutes limit. einfach soviel in die DL reinstecken wie man auf einmal kann und dann wird man schon sehen was rauskommt.
Andreas XXL schrieb:
(Das Hauptproblem wird überigens nicht die Grafikkarte sein sondern der Bus zur Grafikkarte.)
bei einer Statischen Displayliste ist der Bus sicherlich nicht das problem. das muss woanders liegen.
-
rapso schrieb:
Badestrand schrieb:
das Ganze läuft recht langsam
wir programmierer moegen das lieber genauer als diese weihen gefuehls definitionen

Verständlich
Ist aber schwer das an irgendwas festzumachen, weil ich ja nicht mit Frames oder so arbeite; das Bild wird einfach angezeigt (etwa Vogelperspektive, alle Dreiecke sind im Bild) und das Einzige, wo man die "Langsamkeit" merkt, ist beim Drehen oder Verschieben mit der Maus (steht ja sonst auch still :))rapso schrieb:
Badestrand schrieb:
edit: Läuft auf einem recht neuen Rechner unter Windows
bitte ein wenig genauer, besonders was die graka angeht.
Geforce 8800 GTS mit 256 MB RAM, es soll aber auch auf wesentlich schwächeren Rechnern laufen, wenn ich's hinkrieg auch auf Rechnern, wo das Mainboard die Grafikausgabe übernimmt

rapso schrieb:
64000 ist bei displaylisten kein gutes limit. einfach soviel in die DL reinstecken wie man auf einmal kann und dann wird man schon sehen was rauskommt.
Gut, wäre sonst wahrscheinlich kompliziert geworden

Der Tipp mit dem Frustrum-Culling ist zwar gut, aber hab ja leider, wie gesagt, die meiste Zeit alles auf dem Schirm, deshalb werde ich das erstmal nicht einbauen.
Bezgl. LOD werde ich mich auf jeden Fall näher einlesen, auf die Entfernung sieht man ja lange keine Details mehr, da sehe ich momentan das größte Optimierungspotential.
Mittlerweile hab ich auch die Anzahl der Dreiecke reduziert, sind jetzt nur noch 94k. Das Gute ist: Es sieht jetzt sogar besser aus
Läuft auch schon etwas flüssiger und es ruckelt auch fast nicht mehr beim Verschieben, ich werde es erstmal auf dem Labtop meiner Freundin ausprobieren. Demnächst will ich aber auch größere Gebiete darstellen, weshalb ich auf jeden Fall das LOD-Zeug einbauen will.
-
64000 ist bei displaylisten kein gutes limit. einfach soviel in die DL reinstecken wie man auf einmal kann und dann wird man schon sehen was rauskommt.
grundlegend gilt unter opengl auch das "MaxVertexIndex"-limit von direct3d (kann man im DXCapsViewer nachschauen). um unangenehmen ueberaschungen aus dem weg zu gehen, tut man gut daran 16bit indices (fuer gewoehnlich abzueglich ein paar steuercodes) anzunehmen.
Geforce 8800 GTS
wenn du da mit 200k triangles geschwindigkeitsprobleme hast, laeuft aber irgendwas verkehrt...
-
Badestrand schrieb:
rapso schrieb:
Badestrand schrieb:
das Ganze läuft recht langsam
wir programmierer moegen das lieber genauer als diese weihen gefuehls definitionen

Verständlich
Ist aber schwer das an irgendwas festzumachen, weil ich ja nicht mit Frames oder so arbeite; das Bild wird einfach angezeigt (etwa Vogelperspektive, alle Dreiecke sind im Bild) und das Einzige, wo man die "Langsamkeit" merkt, ist beim Drehen oder Verschieben mit der Maus (steht ja sonst auch still :))Du hast also 120fps und dann bricht das auf so ca 60runter?... du solltest alleine schon um festzustellen was deine optimierungen bringen (und ob ueberhaupt) dir die 10min goennen und nen framecounter einbauen.
einfachste moeglichkeit ist frames zu zaehlen und nach jeder sekunde die zahl ausgeben (und framecounter resetten).rapso schrieb:
Badestrand schrieb:
edit: Läuft auf einem recht neuen Rechner unter Windows
bitte ein wenig genauer, besonders was die graka angeht.
Geforce 8800 GTS mit 256 MB RAM, es soll aber auch auf wesentlich schwächeren Rechnern laufen, wenn ich's hinkrieg auch auf Rechnern, wo das Mainboard die Grafikausgabe übernimmt

ja, damit sollte es eigentlich locker fluessig laufen selbst wenn du das voll in die graka schiebst.
Bezgl. LOD werde ich mich auf jeden Fall näher einlesen, auf die Entfernung sieht man ja lange keine Details mehr, da sehe ich momentan das größte Optimierungspotential.
sag sowas nicht;)
das A und O vom optimieren ist rauszufinden was so langsam ist. sonst verbringst du tage am optimieren und am ende bringt es 0 weil es garnicht das problem behebt.deswegen geh systematisch vor. zeichne mal alles ohne das etwas zu sehen ist. zeichne es mal ohne texturen, zeichne es mal im wireframe, zeichne es mal mit culling fuer front und backfaces (hast du das ueberhaupt schon an?
) usw. auf der nvidia seite findest du viele paper zum optimieren und die wichtigsten sagen dir wie du das bottleneck findest.und mach nen screenshot fuer unseren screenshot thread

-
hellihjb schrieb:
64000 ist bei displaylisten kein gutes limit. einfach soviel in die DL reinstecken wie man auf einmal kann und dann wird man schon sehen was rauskommt.
grundlegend gilt unter opengl auch das "MaxVertexIndex"-limit von direct3d (kann man im DXCapsViewer nachschauen). um unangenehmen ueberaschungen aus dem weg zu gehen, tut man gut daran 16bit indices (fuer gewoehnlich abzueglich ein paar steuercodes) anzunehmen.
nichts fuer ungut, aber um sowas musst du dich nicht kuemmern.
das sollte der treiber intern machen und das mesh fuer sich optimal aufsplitten. blind vermuten bringt da echt nichts, da du sonst zu allen dingen die du in die displaylists stopfst die groesst moegliche dummheit annehmen muesstest und dann gleich selber alles machen kannst.btw. @Badestrand
zeichnest du jedes dreieck einzeln zwischen glbeing und glend, oder stopfst du soviele wie moeglich zwischen nur einem glbegin und glend?
setzt du texturen usw. zwischendurch immer wieder?
-
Gut, dann baue ich den Framecounter mal ein! Ich weiß nur nicht genau wie man das macht (peinlich).. Ich zeichne bei jeder Maus-Verschiebungsaktion mit "glCallList(1)". Soll ich also in einer Schleife ständig "glCallList(1)" (und irgendwelche Matrix- und Identity-Sachen) aufrufen und dabei zählen? Ach, ich probier das morgen einfach einmal, aber danke dafür!
rapso schrieb:
deswegen geh systematisch vor. zeichne mal alles ohne das etwas zu sehen ist. zeichne es mal ohne texturen, zeichne es mal im wireframe, zeichne es mal mit culling fuer front und backfaces (hast du das ueberhaupt schon an?
)Hehe, ich hab weder Texturen, noch wireframe oder culling noch backfaces (glaube ich jedenfalls, keine Ahnung was das ist :D). Also Texturen weiß ich natürlich, was das ist, hab aber keine, die Farbe richtet sich nach der Höhe des Geländes.
Und nen Screenshot mache ich auch gerne, grad hab ich was Wichtiges fertiggekriegt; hab die Dreiecke jetzt so, wie du sie hier (ganz unten) vorgeschlagen hattest, hatte nur ein Zacken-Problemchen mit Hügelketten und Tälern, das hab ich eben gerade rausgekriegt *freu*

Ich lade den Sourcecode (MSVC++ 2003) morgen einfach mal hoch, vielleicht kannst du dann auch mal über die Zeichnen-Methode (glLoadIdentity-, gluPerspective-, glMatrixMode-, usw -Aufrufe) drübergucken? Ist ziemlich chaotisch, ich blicke da nicht wirklich durch..

edit:
rapso schrieb:
zeichnest du jedes dreieck einzeln zwischen glbeing und glend, oder stopfst du soviele wie moeglich zwischen nur einem glbegin und glend?
glNewList( 1, GL_COMPILE ); glBegin( GL_TRIANGLES ); // Riesige Schleife glEnd(); glEndList();Ich hatte erst jedes Dreieck zwischen glBegin und glEnd, hatte aber das Gefühl, dass das langsamer war

-
glNewList( 1, GL_COMPILE );eigentlich ist das so gedacht, dass du dir die id (bei dir "1") fuer eine displaylist von opengl mit glGenLists geben laesst und dir nicht einfach eine ausdenkst...
das sollte der treiber intern machen [...] blind vermuten bringt da echt nichts
und ich haett's nicht erwaehnt, wenn ich das nicht schon mal erlebt haette.
-
@Badestrand:
Du sagst, du hast das Ganze in eine GUI eingebettet? Vielleicht ist das der springende Punkt?! Was ist das für ne GUI? MFC Anwendung? Wie wird das Rendering darin gesteuert?
-
hellihjb schrieb:
glNewList( 1, GL_COMPILE );eigentlich ist das so gedacht, dass du dir die id (bei dir "1") fuer eine displaylist von opengl mit glGenLists geben laesst und dir nicht einfach eine ausdenkst...
Gut, also glGenList um die Listen-ID zu bekommen und wenn ich die Liste neu füllen will, glNewList?
Cpp_Junky schrieb:
@Badestrand:
Du sagst, du hast das Ganze in eine GUI eingebettet? Vielleicht ist das der springende Punkt?! Was ist das für ne GUI? MFC Anwendung? Wie wird das Rendering darin gesteuert?Stimmt, ist MFC! Das Modell wird am Anfang erstellt und bei jeder Höhenänderung oder Farbänderung neu berechnet. Neu gerendert wird bei WM_PAINT oder wenn das Modell mit der Maus gedreht oder geschoben wird. Aber hast Recht, ich hab noch gar nicht dran gedacht, dass die GUI auch etwas langsam sein könnte (mit den Nachrichten), obwohl ich's grad zu Testzwecken in einer kleinen schmalen WinAPI-Anwendung laufen lasse - da fällt mir ein, dass in der MFC-Anwendung ja zwei Modelle nebeneinander angezeigt werden

-
Und ist da ein spürbarer Unterschied zwischen WinAPI und der MFC Anwendung?
-
Das Modell wird am Anfang erstellt und bei jeder Höhenänderung oder Farbänderung neu berechnet
und wie oft passiert das so durchschnittlich?
wenn du deine geometrie haeufig veraenderst, solltest du doch vbos erwaegen.
-
hellihjb schrieb:
Das Modell wird am Anfang erstellt und bei jeder Höhenänderung oder Farbänderung neu berechnet
und wie oft passiert das so durchschnittlich?
wenn du deine geometrie haeufig veraenderst, solltest du doch vbos erwaegen.Das passiert eigentlich recht selten, etwa alle 3 Minuten oder so
(oder was ist 'häufig'?)Cpp_Junky schrieb:
Und ist da ein spürbarer Unterschied zwischen WinAPI und der MFC Anwendung?
Ja, das könnte aber auch daran liegen, dass in der MFC-Anwendung ja zwei der Modelle nebeneinander liegen. Könnte man denn das MFC-Nachrichten-System irgendwie optimieren?
-
Badestrand schrieb:
... Könnte man denn das MFC-Nachrichten-System irgendwie optimieren?
Kommt drauf an wie du das Rendering auslöst und was das für ein Fenster ist. Wenn dein RC an einem Standard MFC Control hängt, solltest du dessen Paint Nachrichten überschreiben, damit nicht vor jedem Frame auch noch das olle Windows-Fenster neu gezeichnet wird.
hellihjb schrieb:
Das Modell wird am Anfang erstellt und bei jeder Höhenänderung oder Farbänderung neu berechnet
und wie oft passiert das so durchschnittlich?
wenn du deine geometrie haeufig veraenderst, solltest du doch vbos erwaegen.Sollte man nicht gerade dann besser normale Vertex Buffer nehmen? Die VBOs müssen doch bei jeder Änderung neu übertragen werden oder nicht?
