[OGL] Vertex Array Objects
[OGL] Vertex Array Objects
Moin,
bevor ich versuche, Instancing zu implementieren, wollte ich mir zunächst nocheinaml angucken, wie das jetzt unter OpenGL mit den VertexBuffern in den neueren Versionen aussieht. Und siehe da, da gibt es tatsächlich etwas, was ich bisher nie benutzt habe, dessen Sinn ich aber auch noch nicht so ganz verstehe. Meine Lektüre:
http://www.opengl.org/wiki/Vertex_Specification
Gut, da steht jetzt, dass VertexArrayObjects auf irgendeine Art VertexBuffer zusammen fassen. Und dann wird noch viel darüber geredet, was jetzt genau zum VAO-State gehört und was nicht. Aber so ganz konkret, wofür das eigentlich da ist, und wie man es jetzt korrekt benutzen würde, werden die irgendwie nicht. Und auf weitere 3000 schlechte OpenGL-Tutorials habe ich eigentlich keine Lust mehr.
Die Details zu den einzelnen Funktionen kann ich ja überall nachlesen, aber ich hätte gerne gewusst, was ich wie zusammen benutzen sollte. Beispielsweise hab ich in meinem Projekt noch im Rendercode zig "glVertexAttribPointer" Aufrufe (ohne je ein VAO erstellt zu haben, wieso kann man eigentlich alles für 5 verschiedene Sachen benutzen?) und wüsste gerne, ob ich die wirklich brauche - das VAO hört sich eigentlich so an, als könnte ich das am Anfang einmal initialisieren und ab dann benutzen, aber wirklich konkret werden die in die Richtung nicht.
bevor ich versuche, Instancing zu implementieren, wollte ich mir zunächst nocheinaml angucken, wie das jetzt unter OpenGL mit den VertexBuffern in den neueren Versionen aussieht. Und siehe da, da gibt es tatsächlich etwas, was ich bisher nie benutzt habe, dessen Sinn ich aber auch noch nicht so ganz verstehe. Meine Lektüre:
http://www.opengl.org/wiki/Vertex_Specification
Gut, da steht jetzt, dass VertexArrayObjects auf irgendeine Art VertexBuffer zusammen fassen. Und dann wird noch viel darüber geredet, was jetzt genau zum VAO-State gehört und was nicht. Aber so ganz konkret, wofür das eigentlich da ist, und wie man es jetzt korrekt benutzen würde, werden die irgendwie nicht. Und auf weitere 3000 schlechte OpenGL-Tutorials habe ich eigentlich keine Lust mehr.
Die Details zu den einzelnen Funktionen kann ich ja überall nachlesen, aber ich hätte gerne gewusst, was ich wie zusammen benutzen sollte. Beispielsweise hab ich in meinem Projekt noch im Rendercode zig "glVertexAttribPointer" Aufrufe (ohne je ein VAO erstellt zu haben, wieso kann man eigentlich alles für 5 verschiedene Sachen benutzen?) und wüsste gerne, ob ich die wirklich brauche - das VAO hört sich eigentlich so an, als könnte ich das am Anfang einmal initialisieren und ab dann benutzen, aber wirklich konkret werden die in die Richtung nicht.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
https://jonathank.de/games/
- dot
- Establishment
- Beiträge: 1745
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: [OGL] Vertex Array Objects
Ein VAO ist im Prinzip einfach ein Objekt, das den gesamten State der Input Stage repräsentiert, also die Gesamtheit der gebudnenen Buffer und Vertex Attribute Pointer und aktivierten Vertex Attribute etc. Anstatt also jedes mal aufs Neue alle Buffer zu binden und alle Attribute zu setzen und zu enablen, merkst du dir das alles in einem VAO und bindest dann nur noch das jeweilige VAO und fertig. Ab OpenGL 3.1 Core (iirc) geht ohne VAOs gar nix mehr, da es dort kein Default VAO mehr gibt...
-
- Beiträge: 11
- Registriert: 03.12.2012, 20:56
- Echter Name: Christian
Re: [OGL] Vertex Array Objects
Es ist zu erwarten, dass es performanter ist ein VAO zu binden, als die Zustände einzeln zu setzen.
Zum Beispiel verringert sich die Anzahl von Funktionsaufrufen an den Grafikkartentreiber.
Zum Beispiel verringert sich die Anzahl von Funktionsaufrufen an den Grafikkartentreiber.
Re: [OGL] Vertex Array Objects
Die Zeit die in den Aufrufen an den Treiber verbraten wird ist riesig.
Du musst nur mal die Zeit messen die die das beschreiben einer 4GB große Datei einmal byte für byte verbraucht und einmal in 512Byte Blöcken.
Die Differenz die sich da ergibt ist in erster Linie den Aufrufen an das OS geschuldet, denn das OS buffered die Daten eh in einer Blockgröße das es für angemessen befindet, bevor die Daten auf das Medium gebracht werden.
So ziemlich jede Optimierung, die massenhafte OS calls vermeidet ist deutlich bemerkbar.
Du musst nur mal die Zeit messen die die das beschreiben einer 4GB große Datei einmal byte für byte verbraucht und einmal in 512Byte Blöcken.
Die Differenz die sich da ergibt ist in erster Linie den Aufrufen an das OS geschuldet, denn das OS buffered die Daten eh in einer Blockgröße das es für angemessen befindet, bevor die Daten auf das Medium gebracht werden.
So ziemlich jede Optimierung, die massenhafte OS calls vermeidet ist deutlich bemerkbar.
Re: [OGL] Vertex Array Objects
Ja ok, aber 4GB Byte für Byte schreiben und 3 Vertexbuffer binden ist nochmal ein Unterschied..
Das VAO speichert aber nur alle Buffer, oder? Ich muss zum Rendern dann also den Shader, alle Texturen, alle Uniforms und eben mein VAO (statt 2-3 Vertexbuffer + Indexbuffer + Setup was was heißen soll) setzen, ja?
Ich probiere das jetzt mal so aus, und poste Bilder, sobald ich Ergebnisse habe :)
Das VAO speichert aber nur alle Buffer, oder? Ich muss zum Rendern dann also den Shader, alle Texturen, alle Uniforms und eben mein VAO (statt 2-3 Vertexbuffer + Indexbuffer + Setup was was heißen soll) setzen, ja?
Ich probiere das jetzt mal so aus, und poste Bilder, sobald ich Ergebnisse habe :)
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
https://jonathank.de/games/
- Schrompf
- Moderator
- Beiträge: 5044
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: [OGL] Vertex Array Objects
Der Trick an VAOs ist doch meines Wissens, dass das Setup mit drin ist? Damit kann der GPU-Treiber eine Menge Verifikation und Zuordnung bei Erstellung machen, anstatt vor jedem DrawCall.
Wenn es wirklich nur die Buffer wären, wäre das ja nicht viel mehr als das Bündeln einiger Zeiger-Zuweisungen. Da hätte man wirklich nicht viel rausholen können.
Wenn es wirklich nur die Buffer wären, wäre das ja nicht viel mehr als das Bündeln einiger Zeiger-Zuweisungen. Da hätte man wirklich nicht viel rausholen können.
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
Re: [OGL] Vertex Array Objects
Es hört sich so an, als wären es wirklich nur die Buffer:
http://stackoverflow.com/questions/1182 ... ay-objects
Allerdings: Ich lege ja die Eingabe mit glVertexAttribPointer fest, und muss dem die Position des Attributes im Shader geben - es hängt also schon irgendwie vom Shader ab, ich sollte zumindest nur andere Shader mit der selben Attributreihenfolge benutzen. So richtig überzeugt bin ich von dem ganzen Konzept noch nicht, mal sehen, in wie weit sich das noch ändert.
http://stackoverflow.com/questions/1182 ... ay-objects
Allerdings: Ich lege ja die Eingabe mit glVertexAttribPointer fest, und muss dem die Position des Attributes im Shader geben - es hängt also schon irgendwie vom Shader ab, ich sollte zumindest nur andere Shader mit der selben Attributreihenfolge benutzen. So richtig überzeugt bin ich von dem ganzen Konzept noch nicht, mal sehen, in wie weit sich das noch ändert.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
https://jonathank.de/games/
-
- Beiträge: 11
- Registriert: 03.12.2012, 20:56
- Echter Name: Christian
Re: [OGL] Vertex Array Objects
Wegen der Reihenfolge der Attribute:
Ich mache das so, dass ich in jedem Shader mit
feste Positionen für die Attribute vergebe und somit für jeden Mesh
nur einen VBO brauche.
Ich mache das so, dass ich in jedem Shader mit
Code: Alles auswählen
layout(location = 0) in vec4 aPosition;
layout(location = 1) in vec3 aNormal;
...
nur einen VBO brauche.
Re: [OGL] Vertex Array Objects
Nein. Weil es um die Frage der Menge der Aufrufe geht. Bei 4GB Daten kannste den Geschwindigkeitsunterschied mit der Bahnhofsuhr messen. Grundsätzlich ergibt sich immer das gleiche Problem. Wenn du Daten aus deinem User-Space-Prozess an das OS, und der GraKa-Treiber ist Bestandteil des OS, übergeben musst, geht viel Zeit beim Übergang in den Sicherheitsbereich des OS drauf. Früher hat man das per Soft-Interrupt gemacht. Dann müssen die Daten oft nochmal umkopiert werden, die Treiberfunktionen aufgerufen und noch vieles mehr.Jonathan hat geschrieben:Ja ok, aber 4GB Byte für Byte schreiben und 3 Vertexbuffer binden ist nochmal ein Unterschied..
Das VAO speichert aber nur alle Buffer, oder?
Wenn ich diesen Aufwand, anstelle tausendfach zu wiederholen, einmal machen, habe ich einen Geschwindigkeitsgewinn von 1000 erreicht. Und genau darum ging es bei meinen Vergleich mit der Datei.
- dot
- Establishment
- Beiträge: 1745
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: [OGL] Vertex Array Objects
In Zeiten von Use Mode Drivern sollten die Kernel Mode Switches eher kaum zum Problem werden. Im konkreten Fall liegt der Overhead einzig und allein in der kaputten API begründet, Details gibt's z.B. hier: http://developer.download.nvidia.com/op ... aphics.pdf
Re: [OGL] Vertex Array Objects
Das Papier wiederspricht meiner Aussage nicht.
Denn unterm Strich führt auch hier die Masse der Kommunikation zum Engpass. Um das zu umgehen, geht man dazu über der Anwendung eine Addresse mitzuteilen, in die die Anwendung ihre Daten hineinschreibt und die eigentlich schon auf der GraKa liegt. Damit kopiert das Programm die Daten direkt dahin wo sie hinsollen. Aber was passiert, wenn die Software einfach mal über die Grenzen schreibt?
Wie wird sichergestellt, dass die Anwendung nicht vitale Bereich der GraKa erwischt und wenn sie es doch tut, nicht gleich den Computer mit ins Nirvana befördert. Solange Hardware und Anwendung getrennt sind, ist das schlimmste das mein Prozess stirbt. Ist das immer noch so?
Kann sichergestellt werden, das die GraKa immer in ihren Grundzustand zurückfindet? Und ist der Window-Manager auch in der Lage einen solchen Crash direkt auf der Karte entsprechend abzuhandeln?
Denn unterm Strich führt auch hier die Masse der Kommunikation zum Engpass. Um das zu umgehen, geht man dazu über der Anwendung eine Addresse mitzuteilen, in die die Anwendung ihre Daten hineinschreibt und die eigentlich schon auf der GraKa liegt. Damit kopiert das Programm die Daten direkt dahin wo sie hinsollen. Aber was passiert, wenn die Software einfach mal über die Grenzen schreibt?
Wie wird sichergestellt, dass die Anwendung nicht vitale Bereich der GraKa erwischt und wenn sie es doch tut, nicht gleich den Computer mit ins Nirvana befördert. Solange Hardware und Anwendung getrennt sind, ist das schlimmste das mein Prozess stirbt. Ist das immer noch so?
Kann sichergestellt werden, das die GraKa immer in ihren Grundzustand zurückfindet? Und ist der Window-Manager auch in der Lage einen solchen Crash direkt auf der Karte entsprechend abzuhandeln?
- dot
- Establishment
- Beiträge: 1745
- Registriert: 06.03.2004, 18:10
- Echter Name: Michael Kenzel
- Kontaktdaten:
Re: [OGL] Vertex Array Objects
Klar, ich wollte nur feststellen, dass, aufgrund der Art und Weise wie Grafiktreiber in einem modernen OS funktionieren, die Kernel Mode Switches nicht unbedingt zum direkten Bottleneck werden, sondern dass der Overhead im konkreten Fall hier eher durch das kaputte Objektmodell der API bedingt ist. VAOs sollten es dem Treiber ermöglichen, diesen Overhead weitestgehend zu vermeiden.simbad hat geschrieben:Das Papier wiederspricht meiner Aussage nicht.
Denn unterm Strich führt auch hier die Masse der Kommunikation zum Engpass.
Ich glaub du hast da was falsch verstanden. Aber das ist auch egal, die NVIDIA Extension um die es in der Präsentation oben geht ist für das Thema hier irrelevant, mir ging es nur um die Beschreibung der Natur des Overhead.simbad hat geschrieben:Um das zu umgehen, geht man dazu über der Anwendung eine Addresse mitzuteilen, in die die Anwendung ihre Daten hineinschreibt und die eigentlich schon auf der GraKa liegt. Damit kopiert das Programm die Daten direkt dahin wo sie hinsollen. Aber was passiert, wenn die Software einfach mal über die Grenzen schreibt?
Wie wird sichergestellt, dass die Anwendung nicht vitale Bereich der GraKa erwischt und wenn sie es doch tut, nicht gleich den Computer mit ins Nirvana befördert. Solange Hardware und Anwendung getrennt sind, ist das schlimmste das mein Prozess stirbt. Ist das immer noch so?
Kann sichergestellt werden, das die GraKa immer in ihren Grundzustand zurückfindet? Und ist der Window-Manager auch in der Lage einen solchen Crash direkt auf der Karte entsprechend abzuhandeln?
Re: [OGL] Vertex Array Objects
War aber trotzdem interessant.
-
- Beiträge: 11
- Registriert: 03.12.2012, 20:56
- Echter Name: Christian
Re: [OGL] Vertex Array Objects
Zu den Folien. Ich habe das so verstanden:
Für die Zuordnung buffer Name -> buffer Eigenschaften (insbesondere Addr. im GPU Speicher) muss im Hauptspeicher der CPU gelesen werden,
was Cache-Misses zur Folge hat.
War das die Aussage zur OpenGL 3.x Performance?
Für die Zuordnung buffer Name -> buffer Eigenschaften (insbesondere Addr. im GPU Speicher) muss im Hauptspeicher der CPU gelesen werden,
was Cache-Misses zur Folge hat.
War das die Aussage zur OpenGL 3.x Performance?
Re: [OGL] Vertex Array Objects
Ok, kennt jemand ein aktuelles OpenGL Tutorial (ab Version 4 oder so?). Ich bin es langsam leid, dass jede Funktion für sich zwar dokumentiert ist, aber die ganzen Zusammenhänge nicht so wirklich gut. Und wer weiß wie oft wenn ich was suche stoße ich auf Seiten, die einfach alt sind und wo ich selbst mit meinem Halbwissen merke, dass die Informationen die da stehen, lange nicht mehr aktuell sind und ignoriert werden sollten (immerhin, sonst hätte ich heute schon echt viel Blödsinn gecodet). Im Grunde genommen würde mir ein Beispielprogramm zu Instancing in Open GL mit Vertex- und Index Buffer und VAOs und was sonst noch alles dazugehört schon reichen.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
https://jonathank.de/games/
-
- Establishment
- Beiträge: 488
- Registriert: 01.03.2009, 19:09
Re: [OGL] Vertex Array Objects
Vieleicht hilft dir das etwas, bezüglich Tutorial
http://www.daveshreiner.com/SIGGRAPH/s11/
Beinhaltet zwar viele absoulte Grundlagen die dir wahrscheinlich schon bekannt sind aber ein anderes das sich bereits mit OGL 4 beschäftigt fällt mir grad nicht ein.
http://www.daveshreiner.com/SIGGRAPH/s11/
Beinhaltet zwar viele absoulte Grundlagen die dir wahrscheinlich schon bekannt sind aber ein anderes das sich bereits mit OGL 4 beschäftigt fällt mir grad nicht ein.
Bevor man den Kopf schüttelt, sollte man sich vergewissern einen zu haben
Re: [OGL] Vertex Array Objects
Bezieht sich das auf die alphabetisch geordnete Online-Auflistung aller Funktionen des API, oder auf die Spezifikation? Letztere bietet über die einzelnen Komponenten der API einen jeweils vollständigen Überblick, anstatt dass man sich wie in ersterem Fall auf gut Glück einzelne Funktionen herauspickt und dabei Gefahr läuft, irgendetwas wichtiges zu übersehen.Jonathan hat geschrieben:Ok, kennt jemand ein aktuelles OpenGL Tutorial (ab Version 4 oder so?). Ich bin es langsam leid, dass jede Funktion für sich zwar dokumentiert ist, aber die ganzen Zusammenhänge nicht so wirklich gut.
Re: [OGL] Vertex Array Objects
Hi allerseits,
http://www.swiftless.com/opengltuts/opengl4tuts.html
Das ist eines der verständlichsten Tutorials was ich damals gefunden hatte, wenn man den alten Kram bei OGL weglassen will.
http://www.swiftless.com/opengltuts/opengl4tuts.html
Das ist eines der verständlichsten Tutorials was ich damals gefunden hatte, wenn man den alten Kram bei OGL weglassen will.
Re: [OGL] Vertex Array Objects
Ich finde http://www.opengl-tutorial.org/ noch recht gut.
Re: [OGL] Vertex Array Objects
Nun, es scheint zu gehen :)
Ich glaube, ich benutzte VAOs jetzt so, wie sie gedacht sind, falls jemand drüber gucken möchte und mich auf Fehler hinweisen möchte, nun, das darf er sehr gerne machen :D
(Das ist wieder eines der Bilder, bei denen ein Nicht-Informatiker absolut nicht verstehen kann, wie man sich über so was hässliches freuen kann... :D)
Ich glaube, ich benutzte VAOs jetzt so, wie sie gedacht sind, falls jemand drüber gucken möchte und mich auf Fehler hinweisen möchte, nun, das darf er sehr gerne machen :D
Code: Alles auswählen
#include "InstancedModel.hpp"
#include <assimp/Importer.hpp>
#include <assimp/PostProcess.h>
#include <assimp/scene.h>
#include <GL/glew.h>
using namespace std;
using namespace glm;
InstancedModel::InstancedModel(string ModelFile, string VertexFile, string FragmentFile)
{
Assimp::Importer Importer;
const aiScene* Scene=Importer.ReadFile(ModelFile,
aiProcess_Triangulate | aiProcess_CalcTangentSpace | aiProcess_RemoveRedundantMaterials |
aiProcess_OptimizeGraph | aiProcess_OptimizeMeshes | aiProcess_LimitBoneWeights);
auto Mesh=Scene->mMeshes[0];
//Positions
m_PositionData.resize(Mesh->mNumVertices);
memcpy(m_PositionData.data(), Mesh->mVertices, m_PositionData.size()*sizeof(vec3));
//Uvs
m_UvData.resize(Mesh->mNumVertices);
memcpy(m_UvData.data(), Mesh->mTextureCoords[0], m_UvData.size()*sizeof(vec2));
//Indices
m_IndexData.resize(Mesh->mNumFaces*3);
for(unsigned int i=0; i<Mesh->mNumFaces; ++i)
{
if(Mesh->mFaces[i].mNumIndices<3)
continue; //skip points and lines
//copy the indices of 1 triangle
m_IndexData[i*3+0]=Mesh->mFaces[i].mIndices[0];
m_IndexData[i*3+1]=Mesh->mFaces[i].mIndices[1];
m_IndexData[i*3+2]=Mesh->mFaces[i].mIndices[2];
}
//and some fancy positions:
for(auto i=0u; i<10; ++i)
{
m_InstancedPositionData.push_back(vec3(0, 0, i*10));
}
//Position Buffer:
unsigned int PositionBuffer;
glGenBuffers(1, &PositionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, PositionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vec3)*m_PositionData.size(), m_PositionData.data(), GL_STATIC_DRAW);
//Uv Buffer:
unsigned int UvBuffer;
glGenBuffers(1, &UvBuffer);
glBindBuffer(GL_ARRAY_BUFFER, UvBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vec2)*m_UvData.size(), m_UvData.data(), GL_STATIC_DRAW);
//Index Buffer
unsigned int IndexBuffer;
glGenBuffers(1, &IndexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, IndexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(unsigned int)*m_IndexData.size(), m_IndexData.data(), GL_STATIC_DRAW);
//Instanced Positions:
unsigned int InstancedPositionBuffer;
glGenBuffers(1, &InstancedPositionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, InstancedPositionBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vec3)*m_InstancedPositionData.size(), m_InstancedPositionData.data(), GL_STATIC_DRAW);
//The Shader
m_Shader.Load(VertexFile, FragmentFile);
auto PositionLocation=glGetAttribLocation(m_Shader.GetProgram(), "attPosition");
auto UvLocation=glGetAttribLocation(m_Shader.GetProgram(), "attUv");
auto InstPosLocation=glGetAttribLocation(m_Shader.GetProgram(), "instPosition");
//The Vertex Array Object
glGenVertexArrays(1, &m_VertexArrayObject);
glBindVertexArray(m_VertexArrayObject);
//Positions
glBindBuffer(GL_ARRAY_BUFFER, PositionBuffer);
glVertexAttribPointer(PositionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(PositionLocation);
//Uv
glBindBuffer(GL_ARRAY_BUFFER, UvBuffer);
glVertexAttribPointer(UvLocation, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(UvLocation);
//Instanced Positions
glBindBuffer(GL_ARRAY_BUFFER, InstancedPositionBuffer);
glVertexAttribPointer(InstPosLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glEnableVertexAttribArray(InstPosLocation);
glVertexAttribDivisor(InstPosLocation, 1);
//Indicies
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IndexBuffer);
glBindVertexArray(0);
}
InstancedModel::~InstancedModel()
{
glDeleteVertexArrays(1, &m_VertexArrayObject);
//well, delete buffers
}
void InstancedModel::Render()
{
m_Shader.Set();
glBindVertexArray(m_VertexArrayObject);
//glDrawArrays(GL_TRIANGLES, 0, m_IndexData.size()/3);
//glDrawElements(GL_TRIANGLES, m_IndexData.size()/3, GL_UNSIGNED_INT, nullptr);
glDrawElementsInstanced(GL_TRIANGLES, m_IndexData.size()/3, GL_UNSIGNED_INT, nullptr, 10);
glBindVertexArray(0);
m_Shader.Unset();
}
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
https://jonathank.de/games/