Oggetto buffer vertice - Vertex buffer object

Un oggetto vertex buffer ( VBO ) è una funzionalità OpenGL che fornisce metodi per caricare i dati dei vertici ( posizione , vettore normale , colore, ecc.) Sul dispositivo video per il rendering in modalità non immediata. I VBO offrono notevoli vantaggi in termini di prestazioni rispetto al rendering in modalità immediata principalmente perché i dati risiedono nella memoria del dispositivo video piuttosto che nella memoria di sistema e quindi possono essere renderizzati direttamente dal dispositivo video. Questi sono equivalenti ai buffer dei vertici in Direct3D .

La specifica dell'oggetto del buffer dei vertici è stata standardizzata dall'OpenGL Architecture Review Board a partire da OpenGL versione 1.5 (nel 2003). Funzionalità simili erano disponibili prima della standardizzazione dei VBO tramite l' estensione "vertex array range" creata da Nvidia o l'estensione "vertex array object" di ATI .

Funzioni VBO di base

Le seguenti funzioni costituiscono il nucleo dell'accesso e della manipolazione di VBO:

In OpenGL 1.4 :
glGenBuffersARB (sizei n, uint * buffer)
Genera un nuovo VBO e restituisce il suo numero ID come numero intero senza segno. L'ID 0 è riservato.
glBindBufferARB (enum target, uint buffer)
Usa un buffer creato in precedenza come VBO attivo.
glBufferDataARB (enum target, sizeiptrARB size, const void * data, enum usage)
Carica i dati sul VBO attivo.
glDeleteBuffersARB (sizei n, const uint * buffer)
Elimina il numero specificato di VBO dall'array o dall'id VBO fornito.
In OpenGL 2.1 , OpenGL 3.x e OpenGL 4.x :
glGenBuffers (sizei n, uint * buffer)
Genera un nuovo VBO e restituisce il suo numero ID come numero intero senza segno. L'ID 0 è riservato.
glBindBuffer (enum target, uint buffer)
Usa un buffer creato in precedenza come VBO attivo.
glBufferData (enum target, sizeiptrARB size, const void * data, enum usage)
Carica i dati sul VBO attivo.
glDeleteBuffers (sizei n, const uint * buffer)
Elimina il numero specificato di VBO dall'array o dall'id VBO fornito.

Utilizzo di esempio

In C, utilizzando OpenGL 2.1

//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, utilizzando OpenGL 3.xe OpenGL 4.x

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);
}
/*--------------------------------------------------------------*/


Shader frammento:

/*---------------- "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
}
/*--------------------------------------------------------------*/


Programma OpenGL principale:

/*--------------------- 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));
/*---------------------------------------------------------------*/

Riferimenti

link esterno