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

Aktuelle Zeit: Fr Jul 18, 2025 12:41

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



Ein neues Thema erstellen Auf das Thema antworten  [ 7 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Mi Aug 29, 2007 17:23 
Offline
DGL Member

Registriert: Mi Mär 31, 2004 15:24
Beiträge: 114
Hallo zusammen!

Ich lade die Vertexdaten(+Texturkoordinaten) eines Terrains in ein VBO im VRAM. Nun hab ich das Octree-Verfahren so implementiert, dass es ein Indexarray mit den Indizes der sichtbaren Vertices des Vertexarrays berechnet. Diese Indizes zeichne ich dann mit glDrawElements. Hier der Code:

Code:
  1.  
  2.   glPushMatrix;
  3.  
  4.   TerrainVBO.BindBuffer;
  5.     // Die sichtbaren Vertices werden in Indexlist geschrieben
  6.     TerrainTree.CalculateOctree;
  7.  
  8.     // VexCount - Anzahl sichtbarer Vertices
  9.     glDrawElements(GL_Triangles, VexCount, GL_UNSIGNED_INT, @IndexList[0]);
  10.  
  11.   glPopMatrix;
  12.  


Komisch ist nur, dass folgender Code (bedeutend) schneller ist, obwohl deutlich mehr Vertices gezeichnet werden:

Code:
  1.  
  2.   glPushMatrix;
  3.  
  4.   TerrainVBO.BindBuffer;
  5.     // Die sichtbaren Vertices werden in Indexlist geschrieben
  6.     TerrainTree.CalculateOctree;
  7.  
  8.     // TerrainVBO.VertexCount - Anzahl der Vertices im VBO
  9.     glDrawArrays(GL_Triangles,0,TerrainVBO.VertexCount);
  10.  
  11.   glPopMatrix;
  12.  


Die Geschwindigkeitseinbuße liegt also nicht beim Octree, sondern bei glDrawElements.

Sollte ich lieber glDrawArrays verwenden und den Octree jedesmal das Vertexarray mit den sichtbaren Vertices schreiben lassen? Ich dachte mir, dass glDrawElements, vor allem was LOD angeht, viel flexibler ist und wollte es deshalb so implementieren.
Naja, vielleicht kann mir ja jemand helfen :)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Aug 29, 2007 18:19 
Offline
DGL Member
Benutzeravatar

Registriert: So Jun 04, 2006 12:54
Beiträge: 263
DIe batches sollten nicht zu klein sein, 10000 vertices pro Octreezelle sind kein problem. Eigendlich macht es nur noch Sinn große Bereiche zu entfernen...


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Aug 29, 2007 18:37 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Das Problem liegt wohl eher darin, dass glDrawElements einen clientseitigen Speicherbereich benutzt wärend glDrawArrays einen Speicherbereich auf der Grafikkarte benutzen kann.

Dabei entstehen 2 Probleme.
1. Der Clientspeicher ist wesentlich langsamer, da der komplette Speicher erst einmal über den Bus geschickt werden muss. Und der Speicher auf der Grafikkarte hat einen wesentlich kürzeren und schnelleren weg.
2. OpenGL arbeitet asynchron. Das bedeutet, dass der Aufruf von glDrawArrays schon wieder zurückkehren kann wärend die Grafikkarte noch die Dreiecke zeichnet. Bei glDrawElements ist es aber so, dass du einen clientseitigen Speicherbereich hast und auf den kann OpenGL nur so lange zugreifen wie die Fuktion noch ausgeführt wird. Mit anderen Worten OpenGL muss an dieser zwingend synchron arbeiten. (warten)

Und evtl kann es auch noch problematisch sein, wenn man veraltete VertexArrays (VA) mit VertexBufferObjects (VBO) mischt. Ich weiß nicht ob das unbedingt so reibungslos klappt.

Aber wie oc2k1 schon sagte. Ich denke es ist besser, wenn du einzelne Bereiche in VBOs verpackst und dann nur die sichtbaren Bereiche. So wie bei einem Schachbrett. Die einzelnen Quadrate wären dann Teilstücke der Landschaft.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Aug 29, 2007 19:25 
Offline
DGL Member

Registriert: Mi Mär 31, 2004 15:24
Beiträge: 114
Danke schonmal für die Antworten!

@oc2k1: Wenn sich die Zellengröße in gewissen Grenzen bewegt(Ich glaube etwa zwischen 5000-100000) macht das kaum was an der Renderperformance, aber natürlich ändert sich die Erstellungszeit am Anfang sehr stark :)

@Lossy:
Zitat:
Und evtl kann es auch noch problematisch sein, wenn man veraltete VertexArrays (VA) mit VertexBufferObjects (VBO) mischt. Ich weiß nicht ob das unbedingt so reibungslos klappt.

Also im Moment mach ich das so, dass ich ein Vertexarray gegeben habe, dieses ins VBO packe und dann später nur noch binde und glDrawElements aufrufe. Ich guck mal, ob ich das irgendwie so umgestellt bekomme, dass ich glDrawArrays anwenden kann. Aber sind VA's veraltet? Im VBO-Tutorial werden ja auch VA's benutzt, oder? Wie könnte ich sonst das VBO "füllen? Hab ich da was falsch verstanden?[/quote]


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Aug 30, 2007 08:51 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Ja okay. Das stimmt. Das sieht wirklich etwas verwirrend aus. Denn das ganze hat einen geschichtlichen Hintergrund. Früher waren die Karten noch nicht in der Lage Vertexdaten im Speicher halten zu können. Und da waren VAs das flexible Gegenstück zu den Displaylisten. Und mit Einführung der VBOs können die Karten aber VertexDaten im ihrem Speicher halten. Die Daten haben sich nicht verändert. Es hat sich mehr oder weniger nur die Position davon verändert. Und zwar vom Client (Anwendung) auf den Server (Grafikkarte).

Da VAs und VBOs sich sehr sehr ähnlich sind hat man einfach die bereits bestehenden Methoden der VAs für die VBOs benutzt. Es muss halt ein Buffer gebunden werden damit OpenGL weiß, dass essich um ein VBO handelt. Sonst ist es ziemlich gleich. Bzw bei den Methoden wird bei bei einem VA ein Pointer auf die Daten übergeben und bei einem VBO handelt es sich dabei um ein Offset innerhalb der Daten.

Im Übrigen kannst du glDrawElements auch mit einem VBO benutzen. Du musst halt nur die Daten für den IndexBuffer auch hochladen. (glIndexPointer) Also du musst nicht zwingend mit glDrawArrays arbeiten, da die beiden Funktionen ja schon ihre Daseinsberechtigung haben, denn mit Indexbuffern kannst du sich überlappende Vertices auch mehrfach benutzen. Wärend glDrawArrays für jedes Primitiv entsprechend viele Einzelpunkte erwartet.

PS: Ich muss aber gestehen, dass ich schon länger nichts mehr mit VBOs gemacht habe. Deswegen weiß ich gerade aus dem Kopf nicht so 100%tig wie das mit dem IndexBuffer auf der Grafikkarte funktioniert. ;)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Do Aug 30, 2007 14:57 
Offline
DGL Member

Registriert: Mi Mär 31, 2004 15:24
Beiträge: 114
Ich glaube, dass ich jetzt die Fehlerquelle gefunden habe, die das ganze so verlangsamt. Naja, eigentlich habe ich sie noch nicht gefunden, aber ich weiß jetzt in etwa, woran es liegt.

Mein VBO scheint irgendwie im Hauptspeicher zu sein. Die Benutzung von glDrawArrays bringt bei der gesamten Szene schon die doppelte Framerate im Vergleich zu glDrawElements. Die Geschwindigkeit bleibt aber bei beiden gleich, wenn ich

glBufferData(GL_ARRAY_BUFFER, VertexCount*SizeOf(TVertex), @Vertices[0], GL_STATIC_DRAW);

benutze, also in den Hauptspeicher schreibe, oder wenn ich "versuche" in den VRAM zu schreiben :)
Vielleicht könnt ihr ja mal über meinen Code gucken:

Code:
  1.  
  2.   glGenBuffers(1,@Number);
  3.   glBindBuffer(GL_ARRAY_BUFFER, Number);
  4.  
  5.   VertexCount := Length(Vertices);
  6.   glBufferData(GL_ARRAY_BUFFER, VertexCount*SizeOf(TVertex), nil, GL_STATIC_DRAW);
  7.  
  8.   VBOPointer := glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
  9.  
  10.   For i := 0 to VertexCount-1 do
  11.   begin
  12.     VertexPointer    := VBOPointer;
  13.  
  14.     VertexPointer^.S := Vertices[i].S;
  15.     VertexPointer^.T := Vertices[i].T;
  16.     VertexPointer^.NormX := Vertices[i].NormX;
  17.     VertexPointer^.NormY := Vertices[i].NormY;
  18.     VertexPointer^.NormZ := Vertices[i].NormZ;
  19.     VertexPointer^.X := Vertices[i].X;
  20.     VertexPointer^.Y := Vertices[i].Y;
  21.     VertexPointer^.Z := Vertices[i].Z;
  22.  
  23.     Inc(Integer(VBOPointer), SizeOf(TVertex));
  24.   end;
  25.  
  26.   glUnMapBuffer(GL_ARRAY_BUFFER);
  27.  
  28.   glInterleavedArrays(GL_T2F_N3F_V3F,Sizeof(TVertex), nil);
  29.  
  30.  


Wie ihr vielleicht seht, benutze ich als Vorlage das VBO-Tutorial aus dem Wiki. glEnableClientState(GL_Vertex_Array) usw. brauche ich komischerweise nicht. Ob ich das setze oder nicht, hat keinen Einfluss. Ich kann jetzt auch die ganze Pointergeschichte einfach weglassen Und
glBufferData(GL_ARRAY_BUFFER, VertexCount*SizeOf(TVertex), @Vertices[0], GL_STATIC_DRAW); benutzen. Ist genauso schnell :/

Rendern tue ich so (Ich schreibe hier jetzt mal nur die VBO betreffenden Befehle hin und lasse Octree etc. weg) :
Code:
  1.  
  2.  
  3.     glBindBuffer(GL_ARRAY_BUFFER, Number);
  4.  
  5.     // IndexList enthält die Indizes des Arrays im VBO, die gerendert werden sollen
  6.  
  7.     glDrawElements(GL_Triangles, VexCount, GL_UNSIGNED_INT, @IndexList[0]);
  8.  
  9.  


Seht ihr meinen Fehler?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Di Sep 04, 2007 16:08 
Offline
DGL Member
Benutzeravatar

Registriert: Di Nov 07, 2006 13:37
Beiträge: 83
Wohnort: Partenheim
Hi,

wie erzeugst du deine IndexList? Ist sie ein statisches Array, oder setzt du bei jedem Renderdurchlauf die Größe neu? Das nämlich kann 'ne Menge Performance kosten.
Soll nicht außerdem glDrawRangeElements schneller sein als glDrawElements? Irgendwie soll da der Treiber den Speicherbedarf besser planen und regulieren können ...

Conan

_________________
THE TRUTH IS NOT OUT THERE!


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


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 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:  
cron
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.008s | 14 Queries | GZIP : On ]