Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Sa Jul 12, 2025 19:07

Foren-Übersicht » Programmierung » Einsteiger-Fragen
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 18 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Autor Nachricht
 Betreff des Beitrags: grosze (?) Displaylisten
BeitragVerfasst: Di Apr 07, 2009 06:59 
Offline
DGL Member

Registriert: Mo Apr 06, 2009 17:49
Beiträge: 8
Moin,
kann mir jemand erklaeren, warum eine so

Code:
  1.  
  2. procedure TMyForm.BuildDL;
  3. var
  4.   i: Integer;
  5. begin
  6.   FDLID := glGenLists(1);
  7.   Randomize;
  8.   glNewList(FDLID, GL_COMPILE);
  9.     for i := 0 to 100000 do
  10.       begin
  11.         glPushMatrix;
  12.         glTranslated(Random*640 - 320, Random*480 - 240, 0);
  13.         glColor3d(Random, Random, Random);
  14.         glRotated(Random*360, 0, 0, 1);
  15.         glScaled(Random*100, Random*100, 1);
  16.         glbegin(GL_TRIANGLES);
  17.           glVertex3d(0, 0, 0);
  18.           glVertex3d(1, 0, 0);
  19.           glVertex3d(0, 1, 0);
  20.         glEnd;
  21.         glPopMatrix;
  22.       end;
  23.   glEndList;
  24. end;
  25.  

erzeugte DisplayListe beim rufen 100% CPU-Last erzeugt und ich nur noch 2-3 FPS erreiche? 100000 Dreiecke sind doch nicht sooo viel, oder!?

(Die GraKa ist ne NVIDIA FX5500.)

Dank & Grusz,
Eidechsenlord


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 08:30 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Okt 04, 2006 15:42
Beiträge: 78
Wohnort: Bonn
Programmiersprache: Python, C++, Delphi
Also hier sieht alles so weit normal aus (bis auf das du überall double verwendest).
Ich denke das Pushen und Poppen kannst du dir sparen, wenn du stattdessen
LoadIdentity benutzt (wird ja eh randomisiert).


Gib mal den Codeschnipsel, bei dem du aufrufst.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 09:39 
Offline
DGL Member

Registriert: Mo Apr 06, 2009 17:49
Beiträge: 8
Hallo,
danke vorweg fuer die Hilfe. Hier die Schnipsel:
Code:
  1.  
  2. procedure TMyForm.DrawDL;
  3. begin
  4.   glPushMatrix;
  5.     glTranslated(ClientWidth/2, ClientHeight/2, 0);
  6.     glCallList(FDLID);
  7.   glPopMatrix;
  8. end;
  9.  
  10. procedure TMyForm.Render;
  11. begin
  12.   glViewport(0, 0, ClientWidth, ClientHeight);
  13.   glMatrixMode(GL_PROJECTION);
  14.   glLoadIdentity;
  15.   glOrtho(0,ClientWidth,0,ClientHeight,NearClipping,FarClipping);
  16.  
  17.   glMatrixMode(GL_MODELVIEW);
  18.   glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);// or GL_ACCUM_BUFFER_BIT or GL_STENCIL_BUFFER_BIT);
  19.   glLoadIdentity;                  
  20.  
  21.   glDisable(GL_LIGHTING);
  22.   glDisable(GL_TEXTURE_2D);
  23.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  24.   glEnable(GL_DEPTH_TEST);
  25.   glEnable(GL_POINT_SMOOTH);  
  26.   glEnable(GL_LINE_SMOOTH);    
  27.   glDisable(GL_POLYGON_SMOOTH);
  28.   glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);             // Antialias the lines
  29.   glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);      // Antialias the polygons
  30.   glHint(GL_POINT_SMOOTH_HINT, GL_FASTEST);         // Make round points, not square points
  31.   glEnable(GL_BLEND);
  32.   glDepthFunc(GL_ALWAYS);                            
  33.   glLineWidth (1.125);
  34.  
  35.   [ ... ]
  36.   DrawDL;
  37.   [ ... ]
  38.   SwapBuffers(FDC);
  39. end;
  40.  
  41.  


Die RenderMethode wird von einem RenderThread wie folgt gerufen:
Code:
  1.  
  2. procedure TRenderThread.Execute;
  3. begin
  4.   while not Terminated do begin
  5.     MyForm.Render;
  6.  
  7.     err := glGetError;
  8.     if (err <> GL_NO_ERROR)  then          
  9.       MyForm.OpenGLError := gluErrorString(err);
  10.  
  11.     Sleep(1);
  12.   end;
  13.  
  14.   { Wenn Execute fertig, dann kann das Form geschlossen werden }
  15.   MyForm.FEvent_ThreadExecuteFinished.SetEvent;
  16. end;
  17.  


Dank & Grusz,
Eidechsenlord


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 09:57 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 29, 2005 12:28
Beiträge: 2249
Wohnort: Düsseldorf
Programmiersprache: C++, C#, Java
Ich würde mal sagen es liegt daran das du ständig glBegin aufrufst nur um ein Dreieck zu rendern. Wahrscheinlich schafft OpenGL es nicht das zu optimieren. Du solltest deine Vertices selbst transformieren.

_________________
Yeah! :mrgreen:


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 10:25 
Offline
DGL Member

Registriert: Mo Apr 06, 2009 17:49
Beiträge: 8
Hallo,
Danke fuer den Tip. Hab also mal folgendes probiert:
Code:
  1.  
  2.   glNewList(FDLID, GL_COMPILE);
  3.     glLoadIdentity;
  4.     glbegin(GL_TRIANGLES);
  5.     for i := 0 to 100000 do
  6.       begin
  7.           glColor3f(Random, Random, Random);
  8.           glVertex3f(Random*640 - 320, Random*480 - 240, 0);
  9.           glVertex3f(Random*640 - 320, Random*480 - 240, 0);
  10.           glVertex3f(Random*640 - 320, Random*480 - 240, 0);
  11.       end;
  12.     glEnd;
  13.   glEndList;
  14.  


Bringt leider keine Linderung.

Dank & Grusz,
Eidechsenlord


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 10:41 
Offline
DGL Member
Benutzeravatar

Registriert: Do Sep 02, 2004 19:42
Beiträge: 4158
Programmiersprache: FreePascal, C++
Etwas, das wahrscheinlich garnichts damit zu tun hat: Du benutzt GL_POLYGON_SMOOTH (und andere Smoother). Die sollten nicht verwendet werden. Es kommt da immer wieder zu Problemen mit Kanten bei Dreiecken und ähnlichem, aber auch nicht auf allen Grafikkarten. Ich würde dir empfehlen, dich mal nach Multisampling umzuschauen. Kann es nicht sogar sein, dass OpenGL in den Softwaremodus rennt, wenn man diese Flags aktiviert und die Grafikkarte das nicht kann?

Gruß Lord Horazont

_________________
If you find any deadlinks, please send me a notification – Wenn du tote Links findest, sende mir eine Benachrichtigung.
current projects: ManiacLab; aioxmpp
zombofant networkmy photostream
„Writing code is like writing poetry“ - source unknown


„Give a man a fish, and you feed him for a day. Teach a man to fish and you feed him for a lifetime. “ ~ A Chinese Proverb


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 11:21 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Okt 04, 2006 15:42
Beiträge: 78
Wohnort: Bonn
Programmiersprache: Python, C++, Delphi
Also ich habe noch ein bisschen nachgedacht ^_^

Du sagtest ja, dass die CPU-Last auf 100% geht... d.h. es ist nicht die
Grafikkarte, die an den vielen Dreiecken zerbricht (es sind ja in der Tat gemessen
an dem, was für eine große Scene so normal ist, nicht viel).

D.h. es ist entweder ein Softwaremodus-Problem, weil du irgendeine GL-Funktion
nutzt, die deine Grafikkarte nur schlecht unterstützt (durchprobieren), oder
aber der Treiber optimiert/cached deine Displayliste nicht - was theoretisch
naheliegend ist, da bei dieser Vertexmenge das optimieren recht viel Zeit in Anspruch
nehmen würde. Dies hätte auch zur Folge, dass die CPU die Vertices jedes mal wieder
über den (seeehr langsamen) Bus schaufeln muss - und in der Zeit, während die
CPU auf den langsamen Bus warten muss, ist diese eben blockiert (100% Auslastung).

Lösungsvorschläge:
- Erstmal ein paar glEnables wegmachen (testweise)
- Wenn's nicht hilft: Alle Vertex- und Farbdaten in ein _statisches_ VBO packen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 14:41 
Offline
DGL Member

Registriert: Mo Apr 06, 2009 17:49
Beiträge: 8
Hallo,
vielen Dank fuer die Hilfe!

Zitat:
D.h. es ist entweder ein Softwaremodus-Problem, weil du irgendeine GL-Funktion
nutzt, die deine Grafikkarte nur schlecht unterstützt (durchprobieren), oder

Hm, na viel ist's ja nicht, was benutzt wird. Verzicht auf glColor, glTranslate, glRotate und/oder glScale hat nix gebracht.

Zitat:
aber der Treiber optimiert/cached deine Displayliste nicht - was theoretisch
naheliegend ist, da bei dieser Vertexmenge das optimieren recht viel Zeit in Anspruch
nehmen würde

Klingt plausibel, aber auch die Aufteilung in 1000 DL mit 100 Dreiecken bzw. 100 DL mit 1000 Dreicken (und anschlieszendes Rendern mit glCallLists) hat nicht geholfen. Kleiner sollten doch DL nicht sein muessen ...


Zitat:
- Erstmal ein paar glEnables wegmachen (testweise)

Hab fuer den Testfall mal alles abgestellt. Auch hier: keine Besserung.

Zitat:
- Wenn's nicht hilft: Alle Vertex- und Farbdaten in ein _statisches_ VBO packen.

An VBOs hab ich mich auch schon gewagt. In Wirklichkeit handelt es sich aber nicht um Dreiecke, die darzustellen sind, sondern um beliebige Polygone (auch konkave und welche mit Loechern). Hab also den StencilBuffer zum Rendern verwendet.
Bei einer entsprechend hohen Polygonmenge (5000 Stueck, glaube ich) waren die VBOs dann 10mal langsamer als das Rendern mit DL (in diesem Test besasz jedes Polygon seine eigene DL).

Was koennte das Cachen der DL verhindern? Hat die Hardware evtl. nen Knall?

Dank & Grusz,
Eidechsenlord


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 15:32 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Du benutzt einen Thread zum Rendern? Du weißt, dass ein Kontext an einen Thread gebunden ist. Also um einem Kontext in einem Thread benutzen zu können sollte der auch idealerweise nur dort benutzt werden (auch erstellen und zerstören gehört dazu). Denn ich weiß so direkt nicht ob man einen Kontext so ohne weiteres an einen anderen Thread übergeben kann. Könnte mir gut vorstellen, dass du innerhalb des Threads derzeit tausende von Fehlercodes bekommst (wegen fehlendem aktivem Kontext). Und Fehler wirken mitunter sehr bremsend.

Nichts desto trotz würde ich auf Rendern in einem Thread verzichten. Du kannst alles mögliche innerhalb von Threads laden etc. Das ist in der Regel problemlos machbar. Aber alles was gezeichnet wird sollte besser in einem einzigen Thread (VCLThread) statt finden. Denn sowohl die VCL als auch die GDI ist nicht Threadsicher. Da würde ich eher vorschlagen in einem Timer zu zeichnen oder innerhalb von Application.OnIdle. OnIdle kann man aber auch mit einem kleinen Mechanismus dazu bewegen nur maximal 30Bilder in der Sekunde zu zeichnen. Gepaart mit Timebased Movement vereint man so sparsames rendern und gleichmäßige Bewegungen. Die Anwenundung bleibt trotzdem bestens ansprechbar.

100% CPU Last. Na ja. So pauschal würde ich das nicht sagen wollen. Wenn du nur eine riesen Displayliste oder ein VBO zeichest heißt es nicht, dass die CPU-Last gleich 0 ist. Der Treiber muss spätestens bei SwapBuffers warten bis alles abgearbeitet ist. Und dazu wird er das Ergebniss auf der Grafikkarte dauerhaft pollen. Was sich dann wieder in einer entsprechend CPU-Last äußert. Und das obwohl die Grafikkarte dann vermutlich vollständig ausgelastet ist.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 20:30 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 27, 2005 12:44
Beiträge: 393
Wohnort: Berlin
Programmiersprache: Java, C++, Groovy
Hallo,


100000 Dreiecke sind normalerweise nicht viel, solange sie nicht allesamt komplett ( und ohne Tiefentest ) im Grossformat gerendert werden.
Ich glaube du hast eher ein Problem mit der Anzahl der Fragmente, die auf den Bildschirm gezeichnet werden...


Viele Grüße
dj3hut1

_________________
Wenn Gauß heute lebte, wäre er ein Hacker.
Peter Sarnak, Professor an der Princeton University


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 21:53 
Offline
DGL Member

Registriert: So Apr 01, 2007 17:51
Beiträge: 42
Wohnort: Hamm/Westf.
Ist 900 000 x Random in der Schleife aufzurufen nicht sehr heftig ?

Gento


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Apr 07, 2009 21:54 
Offline
DGL Member
Benutzeravatar

Registriert: Di Jul 29, 2003 00:11
Beiträge: 436
Das passiert aber hoffentlich nur einmal beim Generieren der Displayliste, insofern unproblematisch. :)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Apr 08, 2009 09:05 
Offline
DGL Member

Registriert: Mo Apr 06, 2009 17:49
Beiträge: 8
Hallo,
Danke fuer die zahlreichen Tips und fuer Eure Muehen!

Zitat:
Nichts desto trotz würde ich auf Rendern in einem Thread verzichten.

Die Sache mit den Threads ist sicherlich nicht einfach zu handeln, aber nicht voellig unmoeglich. Die Kontexte werden im jeweiligen Thread erstellt und zerstoert, FehlerCodes werden regelmaeszig abgefragt (gibt keine). Dennoch habe ich nochmal ne Version ohne Threads angehaengt.
Die Entscheidung fuer Threads fiel, da die Anwendung u.U. mehrere OpenGL-Fenster parallel braucht. Threads stellten sich dabei als wesentlich fluessiger heraus als das Rendern mehrerer Fenster ueber eine Schleife in der Idel-Methode. Zu jeder Form gehoert also nun ein Thread, der lediglich rendert und ueber TEvent-Instanzen mit dem Haupthread (Mouse-Events usw.) kommuniziert.

Zitat:
Das passiert aber hoffentlich nur einmal beim Generieren der Displayliste, insofern unproblematisch.

Ja. :-)

Im Anhang wie gesagt mal das Beispiel. Hier: 4 FPS, 96-100% CPU-Last, die GraKa ist nach wie vor eine NVIDIA GeForce FX 5500. Tiefentest sollte m.E. auch funktionieren. Ueber eine Konstante kann man zw. einer groszen und 101 kleinen DL wechseln.
Vielleicht hat ja noch jemand ne Idee.

Gruesze,
Eidechsenlord


Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Apr 08, 2009 11:33 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Threads: Bei der dglOpenGL gibt es die Methode ActivateRenderingContext. Mit der wird normal ein Kontext aktiviert. Anstelle von dieser Methode kannst du auch direkt wglMakeCurrent aufrufen. Bzw musst du sonst aber als dritten Parameter ein False übergeben. Denn sonst lädt die Unit alle Funktionspointer neu. Das kostet massiv Zeit. Aber selbst wenn der dritte Parameter False ist werden die Extensionstrings neu geparst. Also versuchs mal mit wglMakeCurrent. Dann kostet das Wechseln zwar auch noch Zeit aber bei weitem nicht mehr so viel. Denn alles zu Synchronisieren ist deutlich umständlicher zu programmieren und kostet auch Zeit. Du solltest aber mindest ein mal ActivateRenderingContext ohne oder mit True als dritten Parameter aufrufen. Aber im Endeffekt liegt die Entscheidung bei dir.

Zu deiner Displayliste:
Code:
  1.     for i := 0 to 100000 do begin
  2.         glPushMatrix;
  3.         glTranslatef(Random*640 - 320, Random*480 - 240, Random);
  4.         glColor3f(Random, Random, Random);
  5.         glRotatef(Random*360, 0, 0, 1);
  6.         glScalef(Random*100, Random*100, 1);
  7.         glBegin(GL_TRIANGLES);
  8.           glVertex3f(0, 0, 0);
  9.           glVertex3f(1, 0, 0);
  10.           glVertex3f(0, 1, 0);
  11.         glEnd;
  12.         glPopMatrix;
  13.     end;

Das solltest du in einer DL gar nicht machen. Grund: glBegin -> glEnd. Daraus wird eine VBO. Ich weiß nicht ob der Treiber schlau genug ist dort alles in ein VBO zu packen. Allerdings zeichnest du 3 Vertices und anschließend müssen States verändert werden. Selbst ohne den glBegin und glEnd Block sackt die Geschwindigkeit beim Rendern gnadenlos ein. Wenn man dann nur glVertex weglässt liegt die Geschwindigkeit nur kaum unter der kompletten Schleife.

Code:
  1.     for i := 0 to 100000 do
  2.       begin
  3.           glColor3f(Random, Random, Random);
  4.           glVertex3f(Random*640 - 320, Random*480 - 240, 0);
  5.           glVertex3f(Random*640 - 320, Random*480 - 240, 0);
  6.           glVertex3f(Random*640 - 320, Random*480 - 240, 0);
  7.       end;

Diese Schleife ist mitunter auch problematisch. Da die Flächen sehr groß werden können. Damit kann es sein, dass die Füllrate der Grafikkarte wieder sehr stark belastest wird.

Code:
  1.     glbegin(GL_TRIANGLES);
  2.       for i := 0 to 100000 do begin
  3.         glColor3f(Random, Random, Random);
  4.         RandX := Random;
  5.         RandY := Random;
  6.  
  7.         glVertex3f(RandX*640 - 320 + 10, RandY*480 - 240, 0);
  8.         glVertex3f(RandX*640 - 320, RandY*480 - 240 + 10, 0);
  9.         glVertex3f(RandX*640 - 320, RandY*480 - 240, 0);
  10.       end;
  11.     glEnd;

Etwas besser wäre so etwas. Einzige Unterschied besteht eigentlich darin, dass die Flächen maximal 10x10 Einheiten groß sind. Dadurch läuft es mitunter schon reichlich schneller. Du solltest also bei solchen Datenmengen nach Möglichkeit direkt mit Realistischen Daten arbeiten. Und auch möglichst realistisch an dem bleiben was im Endeffekt auch genutzt wird. Dann kannst du es passend darauf optimieren.

Nur einem am Rande. Die Grafikkarte fühlt sich am Wohlsten, wenn du ihr einen Block an Vertices übergibst und sagst "Hier mach mal". Also so viel wie möglich Vertices an einem Stück übergeben. Wenn es dann immer noch hängt, dann liegt es entweder daran, dass ein grober Fehler begangen wurde oder die Grafikkarte zu wenig Leistung hat oder die benötigte Füllrate die Geschwindigkeit des Speichers übersteigt.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Apr 08, 2009 20:32 
Offline
DGL Member

Registriert: Fr Okt 03, 2008 13:32
Beiträge: 367
Ich hab' mir das Programm mal runtergeladen und bei mir getestet. Läuft im original Zustand mit 12FPS.
Wenn ich jetzt nur die "glVertex3f" in die Schleife packe und sonst alles raus, sind es 300FPS. Füge ich wieder "glBegin" und "glEnd" ein, nur noch 250FPS. Und bei zusätzlichen Push- und PopMatrix schließlich nur noch 21FPS.
Also schätze ich mal das die beiden Befehle die meiste Zeit verbrauchen.
Deshalb solltest du vielleicht wirklich nicht die Matrix verändern, sondern die Vertex-Koordinaten. Da das ja nur einmal passiert ist das wohl auch die schnellste Variante


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 18 Beiträge ]  Gehe zu Seite 1, 2  Nächste
Foren-Übersicht » Programmierung » Einsteiger-Fragen


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 5 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.011s | 15 Queries | GZIP : On ]