Ein Vertex Buffer Object (VBO) ist eine OpenGL-Funktionalität, die Methoden zum Hochladen von Vertexdaten (Position, Normalenvektor, Farbe usw.) auf das Videogerät für das Rendern im Retained Mode bereitstellt. VBOs bieten erhebliche Leistungssteigerungen gegenüber dem Rendern im Immediate Mode – vor allem deshalb, weil sich die Daten im Speicher des Videogeräts und nicht im Systemspeicher befinden und daher direkt vom Videogerät gerendert werden können. Die VBOs sind äquivalent zu Vertexpuffern in Direct3D.

Die Spezifikation des Vertex-Puffer-Objekts wurde für OpenGL Version 1.5 (im Jahr 2003) vom OpenGL Architecture Review Board standardisiert. Eine ähnliche Funktionalität war vor der Standardisierung von VBOs über die von Nvidia erstellte Erweiterung „vertex array range“[1] oder ATIs „vertex array object“[2] Erweiterungen verfügbar.

Grundlegende VBO-Funktionen

Bearbeiten

Die folgenden Funktionen bilden den Kern des VBO-Zugriffs und der VBO-Manipulation:

In OpenGL 1.4:
glGenBuffersARB(sizei n, uint *buffers)
Erzeugt ein neues VBO und gibt seine ID-Nummer als vorzeichenlose Ganzzahl zurück. ID 0 ist reserviert.
glBindBufferARB(enum target, uint buffer)
Verwendet einen zuvor erstellten Puffer als aktiven VBO.
glBufferDataARB(enum target, sizeiptrARB size, const void *data, enum usage)
Daten in den aktiven VBO hochladen.
glDeleteBuffersARB(sizei n, const uint *buffers)
Löscht die angegebene Anzahl von VBOs aus dem übergebenen Array oder der VBO-IDs.
In OpenGL 2.1,[3] OpenGL 3.x[4] und OpenGL 4.x:[5]
glGenBuffers(sizei n, uint *buffers)
Erzeugt ein neues VBO und gibt seine ID-Nummer als vorzeichenlose Ganzzahl zurück. ID 0 ist reserviert.
glBindBuffer(enum target, uint buffer)
Verwendet einen zuvor erstellten Puffer als aktiven VBO.
glBufferData(enum target, sizeiptrARB size, const void *data, enum usage)
Daten in den aktiven VBO hochladen.
glDeleteBuffers(sizei n, const uint *buffers)
Löscht die angegebene Anzahl von VBOs aus dem übergebenen Array oder der VBO-IDs.

Beispiel für die Verwendung

Bearbeiten

In C, für OpenGL 2.1

Bearbeiten
//Initialise VBO - do only once, at start of program
//Create a variable to hold the VBO identifier
GLuint triangleVBO;

//Vertices of a triangle (counter-clockwise winding)
float data[] = {1.0, 0.0, 1.0, 0.0, 0.0, -1.0, -1.0, 0.0, 1.0};
//try float data[] = {0.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0}; if the above doesn't work.

//Create a new VBO and use the variable id to store the VBO id
glGenBuffers(1, &triangleVBO);

//Make the new VBO active
glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);

//Upload vertex data to the video device
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);

//Make the new VBO active. Repeat here incase changed since initialisation
glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);

//Draw Triangle from VBO - do each time window, view point or data changes
//Establish its 3 coordinates per vertex with zero stride in this array; necessary here
glVertexPointer(3, GL_FLOAT, 0, NULL);

//Establish array contains vertices (not normals, colours, texture coords etc)
glEnableClientState(GL_VERTEX_ARRAY);

//Actually draw the triangle, giving the number of vertices provided
glDrawArrays(GL_TRIANGLES, 0, sizeof(data) / sizeof(float) / 3);

//Force display to be drawn now
glFlush();

In C, für OpenGL 3.x und OpenGL 4.x

Bearbeiten

Vertex Shader:

/*----------------- "exampleVertexShader.vert" -----------------*/

#version 150 // Specify which version of GLSL we are using.

// in_Position was bound to attribute index 0("shaderAttribute")
in  vec3 in_Position;

void main()
{
    gl_Position = vec4(in_Position.x, in_Position.y, in_Position.z, 1.0);
}
/*--------------------------------------------------------------*/


Fragment Shader:

/*---------------- "exampleFragmentShader.frag" ----------------*/

#version 150 // Specify which version of GLSL we are using.

precision highp float; // Video card drivers require this line to function properly

out vec4 fragColor;

void main()
{
    fragColor = vec4(1.0,1.0,1.0,1.0); //Set colour of each fragment to WHITE
}
/*--------------------------------------------------------------*/


Main OpenGL Program:

/*--------------------- Main OpenGL Program ---------------------*/

/* Create a variable to hold the VBO identifier */
GLuint triangleVBO;

/* This is a handle to the shader program */
GLuint shaderProgram;

/* These pointers will receive the contents of our shader source code files */
GLchar *vertexSource, *fragmentSource;

/* These are handles used to reference the shaders */
GLuint vertexShader, fragmentShader;

const unsigned int shaderAttribute = 0;

/* Vertices of a triangle (counter-clockwise winding) */
float data[3][3] = {
                       {  0.0, 1.0, 0.0   },
                       { -1.0, -1.0, 0.0  },
                       {  1.0, -1.0, 0.0  }
                   };

/*---------------------- Initialise VBO - (Note: do only once, at start of program) ---------------------*/
/* Create a new VBO and use the variable "triangleVBO" to store the VBO id */
glGenBuffers(1, &triangleVBO);

/* Make the new VBO active */
glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);

/* Upload vertex data to the video device */
glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);

/* Specify that our coordinate data is going into attribute index 0(shaderAttribute), and contains three floats per vertex */
glVertexAttribPointer(shaderAttribute, 3, GL_FLOAT, GL_FALSE, 0, 0);

/* Enable attribute index 0(shaderAttribute) as being used */
glEnableVertexAttribArray(shaderAttribute);

/* Make the new VBO active. */
glBindBuffer(GL_ARRAY_BUFFER, triangleVBO);
/*-------------------------------------------------------------------------------------------------------*/

/*--------------------- Load Vertex and Fragment shaders from files and compile them --------------------*/
/* Read our shaders into the appropriate buffers */
vertexSource = filetobuf("exampleVertexShader.vert");
fragmentSource = filetobuf("exampleFragmentShader.frag");

/* Assign our handles a "name" to new shader objects */
vertexShader = glCreateShader(GL_VERTEX_SHADER);
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);

/* Associate the source code buffers with each handle */
glShaderSource(vertexShader, 1, (const GLchar**)&vertexSource, 0);
glShaderSource(fragmentShader, 1, (const GLchar**)&fragmentSource, 0);

/* Free the temporary allocated memory */
free(vertexSource);
free(fragmentSource);

/* Compile our shader objects */
glCompileShader(vertexShader);
glCompileShader(fragmentShader);
/*-------------------------------------------------------------------------------------------------------*/

/*-------------------- Create shader program, attach shaders to it and then link it ---------------------*/
/* Assign our program handle a "name" */
shaderProgram = glCreateProgram();

/* Attach our shaders to our program */
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);

/* Bind attribute index 0 (shaderAttribute) to in_Position*/
/* "in_Position" will represent "data" array's contents in the vertex shader */
glBindAttribLocation(shaderProgram, shaderAttribute, "in_Position");

/* Link shader program*/
glLinkProgram(shaderProgram);
/*-------------------------------------------------------------------------------------------------------*/

/* Set shader program as being actively used */
glUseProgram(shaderProgram);

/* Set background colour to BLACK */
glClearColor(0.0, 0.0, 0.0, 1.0);

/* Clear background with BLACK colour */
glClear(GL_COLOR_BUFFER_BIT);

/* Actually draw the triangle, giving the number of vertices provided by invoke glDrawArrays
   while telling that our data is a triangle and we want to draw 0-3 vertexes
*/
glDrawArrays(GL_TRIANGLES, 0, (sizeof(data) / 3) / sizeof(GLfloat));
/*---------------------------------------------------------------*/
Bearbeiten

Einzelnachweise

Bearbeiten
  1. GL_NV_vertex_array_range. Abgerufen am 10. Mai 2020.
  2. ATI_vertex_array_object. Abgerufen am 10. Mai 2020.
  3. OpenGL 2.1 reference pages. Abgerufen am 10. Mai 2020.
  4. OpenGL 3.2 quick reference. (PDF) Abgerufen am 10. Mai 2020.
  5. OpenGL 4.x reference pages. Abgerufen am 10. Mai 2020.