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

Aktuelle Zeit: Fr Jul 18, 2025 08:57

Foren-Übersicht » Programmierung » OpenGL
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 3 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: VBO langsamer als Immediate Modus?
BeitragVerfasst: So Okt 12, 2008 21:16 
Offline
DGL Member

Registriert: Fr Okt 03, 2008 13:32
Beiträge: 367
In meinem Programm habe ich einen Skydome bestehend aus ca. 3800 Triangles. Nachdem ich diese dann als ein Vertex Buffer Object gespeichert hatte, ist mir aufgefallen, dass ich weniger FPS als vorher hatte. Daraufhin habe ich das Ganze mal getestet und nur den Skydome gezeichnet:

Mit Texturen und Shader habe ich im Immediate Modus 80% mehr Frames in der Sekunde als wenn mit dem VBO gezeichnet wird.
Ohne Texturen und Shader ist das VBO etwas schneller.

Irgendetwas stimmt also nicht. Hier mal der Code dazu, vllt findet jemand von euch den Fehler/Grund für das Ganze.

Das VBO wird so erzeugt:
Code:
  1.  
  2.     glGenBuffersARB(1, @VertexBufferObject);
  3.     glBindBufferARB(GL_ARRAY_BUFFER_ARB, VertexBufferObject);
  4.     glEnableClientState(GL_VERTEX_ARRAY);
  5.     glBufferDataARB(GL_ARRAY_BUFFER_ARB, length(Triangles)*3*SizeOf(TVBO_Skydome_Vertex), nil, GL_STATIC_DRAW_ARB);
  6.     VBOPointer := glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
  7.     VBOSize:=length(Triangles)*3*SizeOf(TVBO_Skydome_Vertex);
  8.  
  9.     for i := 0 to length(Triangles)-1 do
  10.     begin
  11.       VBOPointer^.S:=Vertices[Triangles[i].v1].tx;
  12.       VBOPointer^.T:=Vertices[Triangles[i].v1].ty;
  13.       VBOPointer^.X:=Vertices[Triangles[i].v1].p[0];
  14.       VBOPointer^.Y:=Vertices[Triangles[i].v1].p[1];
  15.       VBOPointer^.Z:=Vertices[Triangles[i].v1].p[2];
  16.       inc(Integer(VBOPointer), SizeOf(TVBO_Skydome_Vertex));
  17.  
  18.       VBOPointer^.S:=Vertices[Triangles[i].v2].tx;
  19.       VBOPointer^.T:=Vertices[Triangles[i].v2].ty;
  20.       VBOPointer^.X:=Vertices[Triangles[i].v2].p[0];
  21.       VBOPointer^.Y:=Vertices[Triangles[i].v2].p[1];
  22.       VBOPointer^.Z:=Vertices[Triangles[i].v2].p[2];
  23.       inc(Integer(VBOPointer), SizeOf(TVBO_Skydome_Vertex));
  24.  
  25.       VBOPointer^.S:=Vertices[Triangles[i].v3].tx;
  26.       VBOPointer^.T:=Vertices[Triangles[i].v3].ty;
  27.       VBOPointer^.X:=Vertices[Triangles[i].v3].p[0];
  28.       VBOPointer^.Y:=Vertices[Triangles[i].v3].p[1];
  29.       VBOPointer^.Z:=Vertices[Triangles[i].v3].p[2];
  30.       inc(Integer(VBOPointer), SizeOf(TVBO_Skydome_Vertex));
  31.     end;
  32.  
  33.     glUnMapBufferARB(GL_ARRAY_BUFFER_ARB);
  34.  


...und dann so gezeichnet:
Code:
  1.  
  2.       glBindBufferARB(GL_ARRAY_BUFFER_ARB, VertexBufferObject);
  3.       glInterleavedArrays(GL_T2F_V3F, SizeOf(TVBO_Skydome_Vertex), nil);
  4.       glDrawArrays(GL_TRIANGLES, 0, VBOSize);
  5.  


Im Immediate Modus wird alles so gezeichnet:
Code:
  1.  
  2.       glBegin(GL_TRIANGLES);
  3.       for i:=0 to length(Triangles)-1 do
  4.       begin
  5.         glMultiTexCoord2f(GL_TEXTURE0,Vertices[Triangles[i].v1].tx,Vertices[Triangles[i].v1].ty);
  6.         glNormal3f(Vertices[Triangles[i].v1].n[0],
  7.                    Vertices[Triangles[i].v1].n[1],
  8.                    Vertices[Triangles[i].v1].n[2]);
  9.         glVertex3f(Vertices[Triangles[i].v1].p[0],
  10.                    Vertices[Triangles[i].v1].p[1],
  11.                    Vertices[Triangles[i].v1].p[2]);
  12.         glMultiTexCoord2f(GL_TEXTURE0,Vertices[Triangles[i].v2].tx,Vertices[Triangles[i].v2].ty);
  13.         glNormal3f(Vertices[Triangles[i].v2].n[0],
  14.                    Vertices[Triangles[i].v2].n[1],
  15.                    Vertices[Triangles[i].v2].n[2]);
  16.         glVertex3f(Vertices[Triangles[i].v2].p[0],
  17.                    Vertices[Triangles[i].v2].p[1],
  18.                    Vertices[Triangles[i].v2].p[2]);
  19.         glMultiTexCoord2f(GL_TEXTURE0,Vertices[Triangles[i].v3].tx,Vertices[Triangles[i].v3].ty);
  20.         glNormal3f(Vertices[Triangles[i].v3].n[0],
  21.                    Vertices[Triangles[i].v3].n[1],
  22.                    Vertices[Triangles[i].v3].n[2]);
  23.         glVertex3f(Vertices[Triangles[i].v3].p[0],
  24.                    Vertices[Triangles[i].v3].p[1],
  25.                    Vertices[Triangles[i].v3].p[2]);
  26.       end;
  27.       glEnd;
  28.  


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Okt 13, 2008 09:12 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Du erstellst das VBO aber schon nach dem Initialisieren und zeichnest es wärend dem Rendern nur noch, oder? Ein dauerhaftes Erstellen wärend dem Zeichnen wäre vermutlich nicht so wirklich schnell. Bzw habe ich bei einigen Karten gesehen, dass MapBuffer unverhältnismäßig langsam ist.

VBOs haben einen gewissen Mehraufwand in der Verwaltung. Entsprechend kann es schon passieren, dass die Geschwindigkeit sogar drastisch sinkt, wenn sie klein genug sind. Also ein VBO für 2-4 Quads lohnt wirklich nicht. Eher im Gegenteil. Aber deines sieht so eigentlich ganz okay. 3800 Vertices sind jetzt nicht so wahnsinnig viele Vertices damit sich die Karte daran austoben könnte. Allerdings sollte die Menge schon ausreichen damit eine leichte Steigerung feststellbar sein könnte. Muss aber auch nicht zwingend. Je nachdem wo und wie die Treiber optimiert wurden. Aber alleine schon bei den Aufrufen von glVertex fällt einiges an Aufwand weg. Im Immediate Modus greifst du bei jedem Aufruf auf ein Indexarray und auf ein Vertexarray zu und dort dann auf eine Stelle des Vertex. Bei einem VBO liegt das normal alles im Speicher der Grafikkarte und dann fällt das alles weg. Wobei die VBO Erweiterung kein Garant dafür ist, dass die VBOs auch wirklich unterstützt werden müssen. Der Treiber darf sie auch emulieren. Dann werden aber VertexArrays benutzt und selbst dann fällt der ganze Aufwand mit dem eigenen Iterieren über die Arrays weg. Besonders (auch aktuelle) Karten mit SharedMemory (leider ein Trend um Karten günstiger zu machen) haben keinen Speicher für Vertexdaten also auch keine echten VBOs. Entsprechend ist die Geschwindigkeit dürftig obwohl der Grafikchip eigentlich anständig Leistung hat.

Wobei ich auch nicht weiß wie deine Daten aufgebaut sind. Evtl wäre es da sogar möglich, dass du sowohl Speicher sparen kannst als auch ein günstiges Zeichendesign verwendest. Und zwar hast du ein Vertexarray und ein Indexarray. Wenn die Einträge im Vertexarray keine doppelten Vertices enthalten, dann kannst du das auch genau so benutzen. Also neben dem GL_ARRAY_BUFFER kannst du auch noch einen GL_ELEMENT_ARRAY_BUFFER erstellen. Der kann entweder im selben Buffer sein oder in einem Seperaten. In diesen kopierst du einfach nur die Indizes deines Triangles arrays und die Vertexdaten überträgst du auch einfach so ohne sie aufzulösen.

Zum Zeichnen benötigst du dann glDrawElements. Benutzen GL_ARRAY_BUFFER und GL_ELEMENT_ARRAY_BUFFER den selben Buffer, dann musst du bei glDrawElements als letzten Parameter den Anfang deiner Indexdaten übergeben.

Sonst wüsste ich so spontan nicht was man an dem VBO noch verändern sollte. Da kommt es dann vermutlich auf die Hardware bzw auch auf die Treiber an.


Für den Imediate Mode hätte ich aber noch was. Wenn du folgendes machst (ungetestet), dann kannst du deinen Daten den Umweg über den Stack ersparen. Denn damit übergibst du nur dein Pointer auf die Daten und OpenGL ließt an dieser 3 Singles. Du hast so weniger Arrayzugriffe und musst weniger Speicher transportieren.
Code:
  1. glVertex3fv(@(Vertices[Triangles[i].v2].p[0]));


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mo Okt 13, 2008 14:39 
Offline
DGL Member

Registriert: Fr Okt 03, 2008 13:32
Beiträge: 367
Ja, das VBO wird nur einmal erstellt.
Mit noch mehr Vertices ändert sich nicht wirklich etwas.
Die Vertices mit einem Pointer im Immediate Modus zu übergeben habe ich mal gemacht, außerdem habe ich gemerkt das ich da noch Normalen drin habe, die ich garnicht brauche. Allerdings macht das das VBO natürlich auch nicht schneller.

Ich versuche mal die Daten fürs VBO umzuorganisieren, wie du das beschrieben hast.

Und wie lässt es sich erklären, das ohne Shader das VBO schneller als der Immediate Modus ist (das war in meinem Anfangspost wohl nicht so gut formuliert)?


Edit:

Ich hab das mit dem Index mal implementiert und das VBO ist nun schneller, so wie es sein sollte.
Und um meine Frage mit dem Shader selbst zu beantworten: Das liegt denke ich daran, dass der Shader der Flaschenhals ist und die Performance beim VBO dementsprechend stärker beschnitten wird.

Edit2:

Jetzt hab ich endlich meinen eigentlichen Fehler gefunden. Weil im Tutorial "glDrawArrays(GL_QUADS, 0, VBOSize);" stand, hab' ich gedacht VBOSize ist die Größe in Bytes. Dabei soll das die Anzahl der Indizes sein.
Da ist es ja kein Wunder, dass es langsamer geht, wenn 20 mal soviel Primitive zu zeichnen versucht werden. :roll:


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 3 Beiträge ] 
Foren-Übersicht » Programmierung » OpenGL


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 4 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.007s | 14 Queries | GZIP : On ]