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

Aktuelle Zeit: Mo Nov 20, 2017 00:56

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



Ein neues Thema erstellen Auf das Thema antworten  [ 8 Beiträge ] 
Autor Nachricht
BeitragVerfasst: Mo Nov 06, 2017 12:16 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Jan 04, 2008 21:29
Beiträge: 419
Wohnort: Lübeck
Hallo Leute!

Zu meinen Specs: Ich arbeite derzeit mit OpenGl 4.5+

Mein Ziel ist es mehrere winzige zusammengehörige Meshes in ein VAO zusammen zulegen und je nach Bedarf nur Teilmengen zu rendern.
Prinzipiell setze ich Bausteine aus Einzelteilen zusammen, zu denen es jeweils mehrere Alternativen gibt.
Da diese Einzelteile teilweise nur aus 4-6 Triangles bestehen wollte ich dafür nicht jedesmal ein eigene Vao, Vbo und Ibo anlegen.
Zusätzlich treten diese beliebig zusammengesetzten Bauteile wahrscheinlich sehr oft auf (so ca. 10^4 bis 10^5)

Gibt es sowas?
Falls ja: wie heißt die Funktion dann korrekt?
Falls nein: wie würdet ihr das am besten nachstellen?

Wie verhält es sich Performance technisch für jedes Bauteil ein Indexarray anzulegen und das an glDrawElementsInstance als letzten Parameter zu übergeben? müssen hierbei die Indexdaten mit jedem Drawcall an die GPU neu übermittelt werden, oder kann man das geschickter lösen?

Letzte Idee wäre es den Indexbuffer am Vao ständig beim rendern durchzuswitchen mittels
Code:
  1. glVertexArrayElementBuffer(vaoId, iboId[x]);
Macht das Sinn? In dem Fall müsste ich ja für jede Einzelteilalternative ein eigenes Ibo erzeugen, oder nicht?


Freundliche Grüße
Sellmann

_________________
Klar Soweit?


Zuletzt geändert von Sellmann am Mi Nov 08, 2017 01:35, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glDrawRangeElementsInstanced
BeitragVerfasst: Mo Nov 06, 2017 15:58 
Offline
DGL Member
Benutzeravatar

Registriert: So Aug 08, 2010 08:37
Beiträge: 429
Programmiersprache: C / C++ / Lua
Gibt mehrere Techniken die dir helfen koennen, gds. ist es jedoch performance technisch gesehen sehr hilfreich, nur ein VBO und ein IBO zu besitzen.

Ich vermute, du suchst das Stichwort "Primitive Restart".

Damit kannst du in deinem IBO einen speziellen Index definieren, der das Processing der Vertices neuanfangen laesst. (quasi als haettest du glDrawElements mit entsprechendem offset neuaufgerufen)

Fuer das Instancing kannst du einfach mehrere VAOs erstellen und dort Offsets verteilen. Die sind nicht so teuer (da du ja nicht die VBOs/IBOs ummappen musst. Musst dann aber evtl. etwas schlau deine Daten im VBO/IBO sortieren // sie einfach mehrfach reinkopieren.

_________________
Never run a changing system! (oder so)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glDrawRangeElementsInstanced
BeitragVerfasst: Mo Nov 06, 2017 19:19 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Jan 04, 2008 21:29
Beiträge: 419
Wohnort: Lübeck
Also Primitive Restart kenne ich, aber das ist nicht das was ich suche, da ich ja nicht LineStrips, TriangleFans oder TriangleStrips trennen möchte. In meiner Situation habe ich mehrere Meshes in einem Vbo untergebracht und muss diese unabhängig voneinander mit Instancing zeichnen können. Da es sich um sehr kleine Meshes handelt, möchte ich diese nur ungerne in mehrere (wahrscheinlich über 100) Vaos / Vbos aufteilen. Das macht für mich deshalb Sinn, weil viele der Vertexdaten über die unterschiedlichen Meshes wiederholt werden und ich so deutlich Daten und bind-Aufrufe sparen könnte.

Edit: Jedes der Meshes kann beliebig oft und an verschiedenen Orten auftauchen, es werden also nicht immer alle Meshes in gleicher Anzahl gezeichnet

Im Etwa so:
Mesh1 (Index0-12) x 112
Mesh2 (Index13-25) x 63
...
MeshN (Index150-161) x 98

_________________
Klar Soweit?


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glDrawRangeElementsInstanced
BeitragVerfasst: Di Nov 07, 2017 17:12 
Offline
DGL Member
Benutzeravatar

Registriert: So Aug 08, 2010 08:37
Beiträge: 429
Programmiersprache: C / C++ / Lua
Hau einfach alles in ein VBO und IBO und render mit glDrawElementsInstanced.

https://www.khronos.org/registry/OpenGL ... nced.xhtml

Der Parameter indices gibt das Offset im IBO in Bytes an.

(4 da vmtl. 4x Triangle)
Mesh 1 renderst du also z.B. glDrawElementsInstanced(GL_TRIANGLES, 4, GL_FLOAT, 0, 112)
Mesh 2 renderst du mit glDrawElementsInstanced(GL_TRIANGLES, 4, GL_FLOAT, 12*sizeof(GLfloat), 63)

usw.

_________________
Never run a changing system! (oder so)


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glDrawRangeElementsInstanced
BeitragVerfasst: Di Nov 07, 2017 23:04 
Offline
DGL Member
Benutzeravatar

Registriert: Di Dez 03, 2002 22:12
Beiträge: 2074
Wohnort: Vancouver
Programmiersprache: C++
Schau dir mal glDrawElementsInstancedBaseVertex an, das koennte helfen - je nachdem wie du deinen Index Buffer fuer die einzelnen sub-meshes aufgebaut hast. Ansonsten ist das was End sagt das was du brauchst.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glDrawRangeElementsInstanced
BeitragVerfasst: Mi Nov 08, 2017 00:59 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Jan 04, 2008 21:29
Beiträge: 419
Wohnort: Lübeck
Vielen Dank für eure Antworten!

Code:
  1. glDrawElementsInstanced(GL_TRIANGLES, 4, GL_FLOAT, 0, 112);
  2. glDrawElementsInstanced(GL_TRIANGLES, 4, GL_FLOAT, 12*sizeof(GLfloat), 63);

12*sizeof(GLfloat) geht leider nicht, weil an dieser Stelle ein const void * als Argument erwartet wird, der auf ein Array mit den Indizes zeigen soll. Hab auch ausprobiert den Parameter so zu verwenden und da tut sich dann gar nichts auf dem Bildschirm. Was aber geht ist, wenn man das IndexArray übergibt und dann die Adresse des StartIndex ermittelt:
Code:
  1. glDrawElementsInstanced(GL_TRIANGLES, 4, GL_FLOAT, &indices[12], 63);

Blöd nur, dass das IndexArray dann jedes mal neu auf die Gpu geschoben werden muss (Vermutung)

Die Variante mit dem BaseVertex hilft mir leider auch nicht weiter. Das BaseVertex verschiebt lediglich den Bezug der Indize auf die Vertices. Dafür müssten also die Vertexdaten der einzelnen Meshes voneinander unabhängig sein und die Meshes selbst hintereinander weg in den Vbos liegen. In meinem Fall wäre das mit umsortieren und Datendopplung möglich. Die Krux an der Sache ist aber, dass ich trotzdem nicht um die Indexbuffer rumkomme. Auch hier kann ich nur entweder einen Indexbuffer an das Vao koppeln und diesen komplett zeichnen (also ALLE enthaltenen Meshes pro Instanz 1x zeichnen), oder keinen Indexbuffer binden und dann, wie in Variante 1, für jedes Mesh einzeln übergeben.

Jetzt das große ABER!
Ich bin ja nicht blöd und suche parallel natürlich auch nach einer Lösung! Dabei habe ich folgende Seite entdeckt:
https://www.khronos.org/opengl/wiki/Vertex_Rendering#Indirect_rendering
Hier werden die unterschiedlichen Methoden dargestellt, mit denen Vertexdaten gezeichnet werden können. Unter anderem findet man weiter unten eine Beschreibung für eine Funktion mit Namen *trommelwirbel*

glDrawElementsIndirect

Dieses Ungetüm erhält ein struct in dem quasi alle Drawcall Eigenschaften auf einmal übergeben werden können. Sie fasst also BaseVertex, FirstIndex und BaseInstance zusammen und bezieht sich bequemerweise auf ein Vao mit Indexbuffer -> genau was ich gesucht habe. Auch wenn ich BaseVertex und BaseInstance eigentlich nicht brauche, missbrauchen kann ich diese Funktion für meinen Zweck sicherlich schon!

Hier vollständigkeitshalber ein Link zur Funktionsbeschreibung:
https://www.khronos.org/opengl/wiki/GLAPI/glDrawElementsIndirect

Ich habe heute leider keine Zeit mehr das auszuprobieren, aber werde mich schnellst möglich dran setzen 8)

Vielen herzlichen Dank für eure investierte Mühe und Zeit!

PS: wenn der Test positiv ausfällt, setze ich auch das [solved] Tag in den Titel

_________________
Klar Soweit?


Zuletzt geändert von Sellmann am Mi Nov 08, 2017 01:34, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags: Re: glDrawRangeElementsInstanced
BeitragVerfasst: Mi Nov 08, 2017 01:27 
Offline
DGL Member
Benutzeravatar

Registriert: Fr Jan 04, 2008 21:29
Beiträge: 419
Wohnort: Lübeck
Kann ja nicht wahr sein: Ich hab nochmal die Spezifikationen etwas genauer gelesen und hab dann folgendes gesehen:

Zitat:
glDrawElementsIndirect is equivalent to:

Code:
  1.     void glDrawElementsIndirect(GLenum mode, GLenum type, const void * indirect)
  2.     {
  3.         const DrawElementsIndirectCommand *cmd  = (const DrawElementsIndirectCommand *)indirect;
  4.         glDrawElementsInstancedBaseVertexBaseInstance(mode,
  5.                                                       cmd->count,
  6.                                                       type,
  7.                                                       cmd->firstIndex * size-of-type,
  8.                                                       cmd->primCount,
  9.                                                       cmd->baseVertex,
  10.                                                       cmd->baseInstance);
  11.     }


Interessant war für mich die Stelle, an der der viertletzte Parameter mit firstIndex besetzt wird. Laut Spezifikation von glDrawElementsInstancedBaseVertexBaseInstance befindet sich an dieser Stelle aber wiederum ein const void * indices... Also müsste die Variante von end ja doch klappen!

Jetzt fragt mich nicht, was bei mir im ersten Versuch schief gelaufen ist, aber end hatte tatsächlich Recht! Es geht genau so. Man muss lediglich noch den Typecast auf (void *) durchführen :D

Sry, für die Kritik und vielen Dank für die Hilfe :oops:

Edit: Sieht jetzt bei mir so aus:
Code:
  1. glDrawElementsInstanced(GL_TRIANGLES, 4, GL_FLOAT, (void *)(12*sizeof(GLfloat)), 63);

_________________
Klar Soweit?


Nach oben
 Profil  
Mit Zitat antworten  
BeitragVerfasst: Mi Nov 08, 2017 12:43 
Offline
DGL Member
Benutzeravatar

Registriert: So Aug 08, 2010 08:37
Beiträge: 429
Programmiersprache: C / C++ / Lua
Ja, den cast hab ich vergessen, sorry.

_________________
Never run a changing system! (oder so)


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


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast


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.033s | 17 Queries | GZIP : On ]