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

Aktuelle Zeit: So Mai 19, 2024 10:36

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



Ein neues Thema erstellen Auf das Thema antworten  [ 6 Beiträge ] 
Autor Nachricht
 Betreff des Beitrags: TriangleStride effektiv zeichnen
BeitragVerfasst: Sa Dez 14, 2013 16:53 
Offline
DGL Member

Registriert: Mo Feb 15, 2010 18:09
Beiträge: 21
Programmiersprache: C++, Java
Guten Abend,
ich setze mich jetzt schon etwas mit openGL auseinander. Nun bin ich an einem Punkt, andem ich externe Modelle aus einer Datei einlesen möchte. Da ich meine Modelle mit Milkshape3D erstelle, habe ich mich als Übung einfach dafür entschieden, das hauseigene Format ms3d zu benutzen um meine Modelle zu laden. Die Implementierung ist kein Problem, die Datei wird korrekt gelesen, Vertexzahl, Dreiecke, Gruppennamen und Texturen stimmen alle überein.

Das eigentlich Problem: wie zeichne ich den ganzen Spaß jetzt? Ich möchte vermeiden mit glVertex, glColor usw. zu arbeiten und würde Arrays bevorzugen, VBOs außen vor gelassen, wobei da die Problematik ähnlich ist.
Das Problem ist jetzt, dass in dieser Datei die Vertices für ein Dreieck per Index angegeben werden, allerdings alle Normalen und Texturekoordinaten für jedes der 3 Vertices pro Dreieck gespeichert werden.
Wenn ich also nun glInterleavedArrays nutzen wollen würde, müsste ich mir das Array erst zusammen bauen und dadurch sehr viel Redundanz erzeugen. Dazu kommt noch, dass ich das ganze dann mit GL_TRIANGLES zeichen müsste.

Frage: Gibt es dafür eine bessere Möglichkeit? Kann ich aus zwei Arrays mit verschiedenen Indices zeichnen? Gibt es einen wirklichen (performance) Unterschied ob ich mit Arrays arbeite oder das ganze manuell mit glVertex, glNormal usw übergebe? Und zu guter letzt: wie kann ich jetzt sinnvoll GL_TRIANGLE_STRIDE einsetzen? Modell vorher durchmustern und zusammenhänge erzeugen? Oder ist dieses Verfahren nur bei großen regelmäßigen Netzen wie Landschaften sinnvoll?

Mit freundlichen Grüßen
Desmu


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: TriangleStride effektiv zeichnen
BeitragVerfasst: Sa Dez 14, 2013 18:00 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 588
Programmiersprache: C++
Desmulator hat geschrieben:
Das Problem ist jetzt, dass in dieser Datei die Vertices für ein Dreieck per Index angegeben werden, allerdings alle Normalen und Texturekoordinaten für jedes der 3 Vertices pro Dreieck gespeichert werden.
Wenn ich also nun glInterleavedArrays nutzen wollen würde, müsste ich mir das Array erst zusammen bauen und dadurch sehr viel Redundanz erzeugen.
Das mit dem Zusammenbauen des eigenen Arrays ist eigentlich nicht so das Problem. Dabei entsteht i.d.R. auch nicht viel Redundanz, denn wenn man sich die meisten Meshes ansieht, wird man eines feststellen: Hat ein Vertex die selbe Position wie ein anderer, so sind in 90% der Fälle auch Texturkoordinaten und Normalen gleich (außer an harten Kanten). Ich verwende aus diesem Grund nur ein Array aus Vertices (Vertex = Position + Normale + TexCoord) als VBO und ein Index-Array.

Die MS3D-Daten kannst du ganz leicht solche Arrays umwandeln. Dafür gehst du jedes Dreieck durch und rufst für jeden Eckpunkt des Dreiecks diese Funktion auf:
Code:
  1. // C3D_Mesh::Vertices ist vom Typ std::vector<Vertex>
  2. // p: position,  n: normal,  t: texCoord
  3. uint16 C3D_Mesh::AddVertex(const vec3& p, const vec3& n, const vec2& t)
  4. {
  5.   const uint16 vmax = Vertices.size();
  6.   uint16 i;
  7.   for(i=0; i<vmax; ++i) // iterating backwards would be faster in most cases
  8.     if(Vertices[i].p == p && Vertices[i].n == n && Vertices[i].t == t)
  9.       return i;
  10.   Vertices.push_back(Vertex(p, n, t));
  11.   return vmax;
  12. }
Als Rückgabewert erhältst du dann den Index, den du an deinen Indexpuffer anhängst (push_back()). Nur wenn der Vertex nicht schon vorhanden ist, wird er neu hinzugefügt.

Desmulator hat geschrieben:
Dazu kommt noch, dass ich das ganze dann mit GL_TRIANGLES zeichen müsste.
Wenn du sowieso einen Indexpuffer verwendest, ist das nicht weiter schlimm. Ich habe mal versucht, trotzdem noch in GL_TRIANGLE_STRIP (ich denke, das meintest du) umzuwandeln. Mein Algorithmus hat aber nicht auf die Schnelle funktioniert, und dann habe ich es erstmal sein gelassen, weil soo groß wird der Vorteil nicht sein und es gibt viele andere Sachen, die wichtiger sind. Wenn du aber einen guten Algorithmus dazu finden solltest, nur her damit!

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Zuletzt geändert von glAwesome am Sa Dez 14, 2013 18:49, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: TriangleStride effektiv zeichnen
BeitragVerfasst: Sa Dez 14, 2013 18:06 
Offline
DGL Member

Registriert: Mo Feb 15, 2010 18:09
Beiträge: 21
Programmiersprache: C++, Java
:) super, danke, du hast alle meine Fragen beantwortet.
Ich merke gerade, jetzt wo ich deine Funktion sehe, dass die Konvertierung wirklich simpel ist. Habe mir das wesentlich komplizierter vorgestellt und versucht zu lösen.

Danke nochmal!


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: TriangleStride effektiv zeichnen
BeitragVerfasst: Sa Dez 14, 2013 22:45 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Dein Beispielcode ist nicht ganz richtig.
Ohne es zu wissen, nehme ich aus dem Kontext an, dass "vec3" ein Gleitkommavektor ist. Einen Gleitkommavektor mit "==" zu vergleichen ist eine schlechte Idee, weil es unter vielen Bedingungen leicht passieren kann, dass sie entweder durch vorherige "Berechnungen"(kann auch bloß Einlesen von Text sein) nicht die gleiche Binärrepresentation haben, obwohl sich ihr Wert mathematisch nicht unterscheiden sollte. Deshalb sollte man Gleitkommazahlen niemals mit "==" oder "!=" vergleichen. Siehe auf Wikipedia "Wikipedia - Gleitkommazahl - Prüfung auf Gleichheit" oder "Prüfe Fließkommazahlen nie auf Gleichheit!".
Am Besten definierst du einfach verschiedene Toleranzen für die Zahlen. Das heißt du bildest den absoluten Wert der Differenz um den Unterschied zu erhalten und prüfst ob dieser eine gewisse tolerierbare Größe überschreitet.

TriangleStrips können die Datenmenge im Indexbuffer, falls man einen verwendet, sonst sogar noch viel mehr im Vertex Buffer selber, weiter reduzieren. Das Finden von zusammenhängenden Strips erfordert jedoch einige Rechenarbeit die eigentlich nur im Vorraus sinnvoll möglich ist, außer bei speziellen Netzen wie beispielsweise das eines Terrains. Damit allerdings nicht soviele Drawcalls für jeden einzelne Strip entstehen, möchte ich auch mal auf Primitve Restart hinweisen, falls du den noch nicht kanntest.

Die meisten Formate sind leider nicht optimal für die Echtzeitdarstellung in OpenGL/DirectX. Ich habe noch kein Format gefunden, dass mich für mich wirklich zufriedenstellend war. Deshalb würde ich empfehlen, ein einiges einfaches binär Format zu entwerfen, das optimal auf deine "Engine" zugeschnitten und erweiterbar ist. Darin könnte man dann auch einfach Strips oder passende Indices speichern. Eine naive Implementierung um doppelte Vertices zusammenzulegen hat schon quadratische Komplexität, von Strips finden ganz zu schweigen. Das würde ich das keinen Nutzer zur Laufzeit zumuten wollen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: TriangleStride effektiv zeichnen
BeitragVerfasst: Sa Dez 14, 2013 23:47 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 14, 2013 21:17
Beiträge: 588
Programmiersprache: C++
OpenglerF hat geschrieben:
Dein Beispielcode ist nicht ganz richtig.
Ohne es zu wissen, nehme ich aus dem Kontext an, dass "vec3" ein Gleitkommavektor ist. Einen Gleitkommavektor mit "==" zu vergleichen ist eine schlechte Idee, weil es unter vielen Bedingungen leicht passieren kann, dass sie entweder durch vorherige "Berechnungen"(kann auch bloß Einlesen von Text sein) nicht die gleiche Binärrepresentation haben, obwohl sich ihr Wert mathematisch nicht unterscheiden sollte.

Danke für den Hinweis. Mir war gar nicht bekannt, dass dieser Effekt selbst bei Bit-Gleichheit auftreten kann. Ich habe gerade mal den Praxistest gemacht. Mein Model hat 13506 Indices und 10668 mal bricht die Funktion bereits in Zeile 9 aufgrund des positiven Vergleichs ab (d.h. 2838 mal schlägt der Vergleich fehl). Wenn ich den Vergleich abschwäche, bricht die Funktion genau 1 Mal öfter ab. :mrgreen: Also in diesem Fall harmlos, aber messbar.

_________________
So aktivierst du Syntaxhighlighting im Forum: [code=pascal ][/code], [code=cpp ][/code], [code=java ][/code] oder [code=glsl ][/code] (ohne die Leerzeichen)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: TriangleStride effektiv zeichnen
BeitragVerfasst: So Dez 15, 2013 13:45 
Offline
DGL Member

Registriert: Do Dez 29, 2011 19:40
Beiträge: 421
Wohnort: Deutschland, Bayern
Programmiersprache: C++, C, D, C# VB.Net
Es ist halt auch platformabhänig. Eine Gradwanderung die in einigen Fällen gut geht aber jederzeit schiefgehen kann. Bei Normalen zum Beispiel macht es sowieso Sinn: Wer kann schon (1,0,0) von einer (1,0,0.001) Normale unterscheiden?

Was ich gestern noch vergessen hatte:
Ob der Immediate Mode wirklich soviel langsamer ist als VBOs ist, lässt sich allgemein nicht beantworten. Fakt ist, dass er auf Treiberseite sehr viel Overhead hervorruft und für jeden Vertex mehrere API Aufrufe notwendig sind. Nicht um sonst gibt es immer mehr OpenGL Features die mehr oder weniger darauf abzielen, die Anzahl OpenGL Aufrufe zu reduzieren. Außerdem wurde er in OpenGL 3.1 aus dem Core entfernt und ist nicht mehr zukunftssicher, schon das sollte Grund genug sein auf ihn zu verzichten. Wenn man bloß ein paar Dreiecke rendert die sich nochdazu jedes Frame ändern, dann wird der Unterschied wohl noch nicht so groß ausfallen. Den großen Triumpf spielt ein VBO dann aus, wenn er nicht jedes Frame geändert wird. Die GPU - CPU Verbindung ist ein totaler Flaschenhals und VBOs können auf der Grafikkarte bleiben. Ein weiterer Grund: Wenn du mal erweiterte Effekte realisieren willst, wirst du zusätzliche Daten an den Shader übergeben wollen und die lassen sich nicht effizient und flexibel mit dem Immediate Mode übergeben. Bei einen VBO kann man die enthaltenen Datentypen komplett selber anpassen.


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


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.017s | 14 Queries | GZIP : On ]