opengl
Använda VAO: er
Sök…
Introduktion
Vertex Array Object lagrar hur opengl ska tolka en uppsättning VBO: er.
I huvudsak låter det dig undvika att ringa glVertexAttribPointer varje gång du vill göra ett nytt nät.
Om du inte vill ta itu med VAO: er kan du helt enkelt skapa en och binda den under programinitieringen och låtsas att de inte finns.
Syntax
void glEnableVertexAttribArray (GLuint attribIndex);
void glDisableVertexAttribArray (GLuint attribIndex);
void glVertexAttribPointer (GLuint attribIndex, GLint storlek, GLenum typ, GLboolean normaliserad, GLsizei steg, const GLvoid * pointer);
void glVertexAttribFormat (GLuint attribIndex, GLint storlek, GLenum typ, GLboolean normaliserad, GLuint relative offset);
void glVertexAttribbindning (GLuint attribIndex, GLuint bindingIndex);
void glBindVertexBuffer (GLuint bindingIndex, GLuint buffert, GLintptr offset, GLintptr steg);
parametrar
parameter | detaljer |
---|---|
attribIndex | platsen för vertexattributet till vilket vertexfältet matar data |
storlek | antalet komponenter som ska dras från attributet |
typ | C ++ -typen för attributdata i bufferten |
normaliserad | huruvida man ska kartlägga heltalstyper till flytpunktsområdet [0, 1] (för osignerad) eller [-1, 1] (för signerad) |
pekare | byteförskjutningen i bufferten till den första byten av attributets data (kastas till void* av äldre skäl) |
offset | basbyteförskjutningen från början av bufferten till där matrisdata startar |
relativeOffset | förskjutningen till ett visst attribut, relativt basförskjutningen för bufferten |
kliva | antalet byte från en toppunkt till nästa |
buffert | buffertobjektet där vertexmatriserna lagras |
bindingIndex | det index som källbuffertobjektet kommer att vara bundet till |
Anmärkningar
Den separata attributformatet VAO-inställningen kan samverka med glVertexAttribPointer
(det senare definieras i termer av det förra). Men du måste vara försiktig när du gör det.
Den separata attributformatversionen har ekvivalenter med direkttillstånd (DSA) i 4.5. Dessa kommer att ha samma parametrar men istället för att använda den bundna VAO, skickas VAO som modifieras uttryckligen. När du använder DSA de glDrawElements
för glDrawElements
kan ställas in med glVertexArrayElementBuffer(vao, ebo);
Version 3.0
Varje attribut är associerat med ett komponentantal, typ, normaliserat, offset, steg och VBO. VBO passeras inte uttryckligen som en parameter utan är istället bufferten bunden till GL_ARRAY_BUFFER vid samtalet.
void prepareMeshForRender(Mesh mesh){
glBindVertexArray(mesh.vao);
glBindBuffer(GL_ARRAY_BUFFER, mesh.vbo);
glVertexAttribPointer (posAttrLoc, 3, GL_FLOAT, false, sizeof(Vertex), mesh.vboOffset + offsetof(Vertex, pos));//will associate mesh.vbo with the posAttrLoc
glEnableVertexAttribArray(posAttrLoc);
glVertexAttribPointer (normalAttrLoc, 3, GL_FLOAT, false, sizeof(Vertex), mesh.vboOffset + offsetof(Vertex, normal));
glEnableVertexAttribArray(normalAttrLoc);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ebo); //this binding is also saved.
glBindVertexArray(0);
}
void drawMesh(Mesh[] meshes){
foreach(mesh in meshes){
glBindVertexArray(mesh.vao);
glDrawElements(GL_TRIANGLES, mesh.vertexCount, GL_UNSIGNED_INT, mesh.indexOffset);
}
}
Version 4.3
OpenGL 4.3 (eller ARB_separate_attrib_format) lägger till ett alternativt sätt att specificera vertexdata, vilket skapar en åtskillnad mellan formatet för data som är bundet för ett attribut och buffertobjektkällan som tillhandahåller data. Så istället för att ha en VAO per nät, kan du ha ett VAO per vertexformat.
Varje attribut är associerat med ett toppunktformat och en bindningspunkt. Vertexformatet består av typen, komponenträkningen, oavsett om den är normaliserad, och den relativa förskjutningen från början av data till det specifika toppunktet. Bindningspunkten anger vilken buffert ett attribut tar sina data från. Genom att separera de två kan du binda buffertar utan att respektera några toppformat. Du kan också ändra bufferten som tillhandahåller data till flera attribut med ett enda bindande samtal.
//accessible constant declarations
constexpr int vertexBindingPoint = 0;
constexpr int texBindingPoint = 1;// free to choose, must be less than the GL_MAX_VERTEX_ATTRIB_BINDINGS limit
//during initialization
glBindVertexArray(vao);
glVertexAttribFormat(posAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, pos));
// set the details of a single attribute
glVertexAttribBinding(posAttrLoc, vertexBindingPoint);
// which buffer binding point it is attached to
glEnableVertexAttribArray(posAttrLoc);
glVertexAttribFormat(normalAttrLoc, 3, GL_FLOAT, false, offsetof(Vertex, normal));
glVertexAttribBinding(normalAttrLoc, vertexBindingPoint);
glEnableVertexAttribArray(normalAttrLoc);
glVertexAttribFormat(texAttrLoc, 2, GL_FLOAT, false, offsetof(Texture, tex));
glVertexAttribBinding(texAttrLoc, texBindingPoint);
glEnableVertexAttribArray(texAttrLoc);
Sedan under dragningen håller du vao bunden och ändrar bara buffertbindningarna.
void drawMesh(Mesh[] mesh){
glBindVertexArray(vao);
foreach(mesh in meshes){
glBindVertexBuffer(vertexBindingPoint, mesh.vbo, mesh.vboOffset, sizeof(Vertex));
glBindVertexBuffer(texBindingPoint, mesh.texVbo, mesh.texVboOffset, sizeof(Texture));
// bind the buffers to the binding point
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.ebo);
glDrawElements(GL_TRIANGLES, mesh.vertexCount, GL_UNSIGNED_INT, mesh.indexOffset);
//draw
}
}