Objekt vrcholového bufferu - Vertex buffer object

Objekt vrcholového bufferu ( VBO ) je funkce OpenGL , která poskytuje metody pro nahrávání vertexových dat ( pozice , normální vektor , barva atd.) Do videozařízení pro vykreslení v jiném než okamžitém režimu. VBO nabízejí podstatné zvýšení výkonu oproti okamžitému vykreslování, protože data jsou uložena spíše v paměti videozařízení než v systémové paměti, a proto je lze vykreslovat přímo videozařízením. Jedná se o ekvivalent vertexových vyrovnávacích pamětí v Direct3D .

Specifikace objektu vrcholového bufferu byla standardizována komisí OpenGL Architecture Review Board od verze OpenGL verze 1.5 (v roce 2003). Podobné funkce byly k dispozici před standardizací VBO prostřednictvím rozšíření „vertex array range“ vytvořeného Nvidia nebo rozšíření „object vertex array“ od ATI .

Základní funkce VBO

Následující funkce tvoří jádro přístupu a manipulace VBO:

V OpenGL 1.4 :
glGenBuffersARB (velikost, uint * vyrovnávací paměti)
Generuje nové VBO a vrátí jeho ID číslo jako celé číslo bez znaménka. Id 0 je rezervováno.
glBindBufferARB (cíl enum, vyrovnávací paměť uint)
Jako aktivní VBO použijte dříve vytvořenou vyrovnávací paměť.
glBufferDataARB (cíl enum, velikost sizeiptrARB, const void * data, využití enum)
Nahrajte data do aktivního VBO.
glDeleteBuffersARB (velikost, konstu * vyrovnávací paměti)
Odstraní zadaný počet VBO z dodaného pole nebo ID VBO.
V OpenGL 2.1 , OpenGL 3.xa OpenGL 4.x :
glGenBuffers (velikost, n * vyrovnávací paměti)
Generuje nové VBO a vrátí jeho ID číslo jako celé číslo bez znaménka. Id 0 je rezervováno.
glBindBuffer (cíl enum, uint buffer)
Jako aktivní VBO použijte dříve vytvořenou vyrovnávací paměť.
glBufferData (cíl enum, velikost sizeiptrARB, const void * data, využití enum)
Nahrajte data do aktivního VBO.
glDeleteBuffers (velikost, konstu * vyrovnávací paměti)
Odstraní zadaný počet VBO z dodaného pole nebo ID VBO.

Příklad použití

V jazyce C pomocí 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();

V jazyce C pomocí OpenGL 3.xa 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);
}
/*--------------------------------------------------------------*/


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


Hlavní program OpenGL:

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

Reference

externí odkazy