GLES vertex buffer object (VBO), glesvbo
You may often hear about VBO in other people's mouths. I don't know what it means, but I think it's very tall. But if you know the Chinese name, you should be able to understand it.
VBO, that is, the vertex buffer object.
When using a vertex array, the specified vertex data is stored in the system memory. When performing glDrawArrays or glDrawElements, You need to copy the vertex data to the graphics card memory.
Very troublesome. As a matter of fact, we can directly store the vertex data in the graphics card memory, so that we do not need to copy this step. This method can improve rendering performance and reduce memory bandwidth consumption.
Before using VBO, we need to apply for allocating buffer objects and upload vertex data and element indexes to corresponding buffer objects.
The following example describes the usage:
// Create and bind vertex buffer objects (VBO); void InitVertexBufferObjects (float * vertexBuffer, GLushort * indices, GLuint numVertices, GLuint numIndices, GLuint * vboIds) {glGenBuffers (2, vboIds); // apply for two buffers. One is used to save the actual vertex data, and the other is used to store the element index of the elements. glBindBuffer (GL_ARRAY_BUFFER, vboIds [0]); // specify the Current Buffer object; glBufferData (GL_ARRAY_BUFFER, numVertices * sizeof (float), vertexBuffer, GL_STATIC_DRAW); // create and initialize data storage; glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, vboIds [1]); glBufferData (GL_ELEMENT_ARRAY_BUFFER, numIndices * sizeof (float), indices, GL_STATIC_DRAW );}
Let's take a look at the different operations of drawing elements without using VBO or using VBO:
// Use vertex array-structure array instead of VBO to draw elements; void stride (GLfloat * vertices, GLint vtxStride, GLint numIndices, GLushort * indices) {GLfloat * vertexBuffer = vertices; glBindBuffer (GL_ARRAY_BUFFER, 0); glBindBuffer (vertex, 0); vertex (vertex); // vertex array; vertex (vertex); vertex (vertex, VERTEX_POS_SIZE, GL_FLOAT, GL_FALSE, vtxStride, vertexBuffer); // vertex array; vertexBuffer = vertexBuffer + vertex; // offset; vertex (vertex, VERTEX_COLOR_SIZE, GL_FLOAT, GL_FALSE, vtxStride, vertexBuffer); vertex (GL_TRIANGLES, numIndices, counts, indices); counts (VERTEX_POS_INDX); counts (VERTEX_COLOR_INDX);} // use VBO to draw elements; void counts (ESContext * esContext, GLint numVertices, GLfloat * vertexBuffer, GLint vtxStride, GLint numIndices, GLushort * indices) {UserData * userData = (UserData *) esContext-> userData; GLuint offset = 0; if (userData-> vboIds [0] = 0 & userData-> vboIds [1] = 0) {glGenBuffers (2, userData-> vboIds); glBindBuffer (GL_ARRAY_BUFFER, userData-> vboIds [0]); glBufferData (GL_ARRAY_BUFFER, vtxStride * numVertices, vertexBuffer, buffers); glBindBuffer (bytes, userData-> vboIds [1]); glBufferData (bytes, sizeof (GLushort) * numIndices, vertexBuffer, buffers);} glBindBuffer (GL_ARRAY_BUFFER, userData-> vboIds [0]); glBindBuffer glEnableVertexAttribArray (random); glablevertexattribarray (random); // note that VBO is used. The final parameter is not vertexBuffer, but data in VBO; struct (random, VERTEX_POS_SIZE, GL_FLOAT, GL_FALSE, vtxStride, (const void *) offset); offset = offset + VERTEX_POS_SIZE * sizeof (float); // offset; glVertexAttribPointer (vertex, VERTEX_COLOR_SIZE, GL_FLOAT, GL_FALSE, vtxStride, (const void *) offset); reverse (VERTEX_POS_INDX); reverse (VERTEX_COLOR_INDX); // Restore Default VBO binding; glBindBuffer (GL_ARRAY_BUFFER, 0); glBindBuffer (limit, 0 );} void Draw (ESContext * esContext) {UserData * userData = (UserData *) esContext-> userData; GLfloat vertices [3 * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE)] = {-0.5f, 0.5f, 0.0f, // v01.0f, 0.0f, 0.0f, 1.0f, // c0-1.0f,-0.5f, 0.0f, // v10.0f, 1.0f, 0.0f, 1.0f, // c10.0f,-0.5f, 0.0f, // v20366f, 0.0f, 1.0f, 1.0f, // c2}; GLushort indices [3] = {, 2}; glViewport (, esContext-> width, esContext-> height); glClear (GL_COLOR_BUFFER_BIT); glUseProgram (userData-> programObject); glUniform1f (userData-> offsetLoc, 0.0f); vertex (vertices, sizeof (GLfloat) * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE), 3, indices); glUniform1f (userData-> offsetLoc, 1.0f); fig (esContext, 3, vertices, sizeof (GLfloat) * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE), 3, indices );}
Entire code
# Include "esUtil. h "# define VERTEX_POS_SIZE 3 # define VERTEX_COLOR_SIZE 4 # define limit 0 # define limit 1 typedef struct {GLuint programObject; // save GLProgram; GLuint vboIds [2]; // vbo object; GLuint offsetLoc;} UserData; // load Shader; GLuint LoadShader (GLenum type, const char * shaderSrc) {GLuint shader; GLint compiled; shader = glCreateShader (type ); if (shader = 0) {return 0;} glShaderSource (shader, 1, & sha DerSrc, NULL); glCompileShader (shader); glGetShaderiv (shader, GL_COMPILE_STATUS, & compiled); if (! Compiled) {GLint infoLen = 0; glGetShaderiv (shader, GL_INFO_LOG_LENGTH, & infoLen); if (infoLen> 1) {char * infoLog = (char *) malloc (sizeof (char) * infoLen); glGetShaderInfoLog (shader, infoLen, NULL, infoLog); esLogMessage ("Error Compiling Shader: % s", infoLog); free (infoLog);} glDeleteShader (shader ); return 0;} return shader;} // initialize Shader and GLProgram; int Init (ESContext * esContext) {UserData * userData = (UserData *) esContext-> u SerData; char vShaderStr [] = "# version 300 es \ n" "layout (location = 0) in vec4 a_Position;" // specifies the index of the vertex attribute. Optional, if no program is set, it will be automatically allocated; "layout (location = 1) in vec4 a_Color;" "uniform float u_offset;" "out vec4 v_Color;" // output value to Fragment Shader; flat coloring; "void main ()" {"" v_Color = a_Color; "" gl_Position = a_Position; "" gl_Position.x + = u_offset ;""}"; char fShaderStr [] = "# version 300 es \ n" "precision mediump float;" // default precision qualifier; highp, l Owp, mediump; "in vec4 v_Color;" // Vertex Shader value; "out vec4 o_fragColor;" "void main () "" {"" o_fragColor = vec4 (v_Color); ""} "; GLuint vertexShader; GLuint fragmentShader; GLuint programObject; GLint linked; vertexShader = LoadShader (delimiter, vShaderStr ); fragmentShader = LoadShader (GL_FRAGMENT_SHADER, fShaderStr); programObject = glCreateProgram (); if (programObject = 0) {return 0;} glAttachShader (programObject, VertexShader); glAttachShader (programObject, fragmentShader); glLinkProgram (programObject); glGetProgramiv (programObject, GL_LINK_STATUS, & linked); if (! Linked) {GLint infoLen = 0; glGetProgramiv (programObject, GL_INFO_LOG_LENGTH, & infoLen); if (infoLen> 1) {char * infoLog = (char *) malloc (sizeof (char) * infoLen); glGetProgramInfoLog (programObject, infoLen, NULL, infoLog); esLogMessage ("Error linking program: % s \ n", infoLog); free (infoLog );} glDeleteProgram (programObject); return 0;} userData-> programObject = programObject; userData-> offsetLoc = glGetUniformLocation (programObj Ect, "u_offset"); userData-> vboIds [0] = 0; userData-> vboIds [1] = 0; glClearColor (1.0f, 1.0f, 1.0f, 1.0f ); return 1;} // create and bind a vertex buffer object (VBO); void InitVertexBufferObjects (float * vertexBuffer, GLushort * indices, GLuint numVertices, GLuint numIndices, GLuint * vboIds) {glGenBuffers (2, vboIds); // apply for two buffers. One is used to save the actual vertex data, and the other is used to save the element index that makes up the elements. glBindBuffer (GL_ARRAY_BUFFER, vboIds [0]); // specifies the Current Buffer object; glBufferData (GL_ARRAY_BUFFER, numVertices * Sizeof (float), vertexBuffer, GL_STATIC_DRAW); // create and initialize data storage; glBindBuffer (batch, vboIds [1]); glBufferData (batch, numIndices * sizeof (float ), indices, GL_STATIC_DRAW);} // use vertex array-structure array instead of VBO to draw elements; void Merge (GLfloat * vertices, GLint vtxStride, GLint numIndices, GLushort * indices) {GLfloat * vertexBuffer = vertices; glBindBuffer (GL_ARRAY_BUFFER, 0); glBindBuffer (GL_ELEM ENT_ARRAY_BUFFER, 0); glEnableVertexAttribArray (vertex); // allowed vertex array; glablevertexattribarray (vertex); vertex (vertex, VERTEX_POS_SIZE, GL_FLOAT, GL_FALSE, vtxStride, vertexBuffer ); // vertex array; vertexBuffer = vertexBuffer + VERTEX_POS_SIZE; // offset; vertex (vertex, VERTEX_COLOR_SIZE, GL_FLOAT, GL_FALSE, vtxStride, vertexBuffer); glDrawElements (GL_TRIANGLES, numI Ndices, numbers, indices); numbers (VERTEX_POS_INDX); numbers (VERTEX_COLOR_INDX);} // use VBO to draw elements; void aggregate (ESContext * esContext, GLint numVertices, GLfloat * vertexBuffer, GLint vtxStride, GLint numIndices, GLushort * indices) {UserData * userData = (UserData *) esContext-> userData; GLuint offset = 0; if (userData-> vboIds [0] = 0 & userData-> vboIds [1] = 0) {glG EnBuffers (2, userData-> vboIds); buffers (GL_ARRAY_BUFFER, userData-> vboIds [0]); glBufferData (GL_ARRAY_BUFFER, vtxStride * numVertices, vertexBuffer, buffers); counts (buffers, userData-> vboIds [1]); glBufferData (bytes, sizeof (GLushort) * numIndices, indices, buffers);} glBindBuffer (GL_ARRAY_BUFFER, userData-> vboIds [0]); glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, userD Ata-> vboIds [1]); glEnableVertexAttribArray (VERTEX_POS_INDX); glablevertexattribarray (VERTEX_COLOR_INDX); // note that VBO is used, and the final parameter is not vertexBuffer, but data in VBO; glVertexAttribPointer (iterator, VERTEX_POS_SIZE, GL_FLOAT, GL_FALSE, vtxStride, (const void *) offset); offset = offset + VERTEX_POS_SIZE * sizeof (float); // offset; iterator (iterator, VERTEX_COLOR_SIZE, GL_FLOAT, GL_FALSE, vtxStride, (const void *) Offset); glDrawElements (GL_TRIANGLES, numIndices, numbers, 0); reset (numbers); reset (VERTEX_COLOR_INDX); // restore the default bound VBO; glBindBuffer (GL_ARRAY_BUFFER, 0 ); glBindBuffer (latency, 0);} void Draw (ESContext * esContext) {UserData * userData = (UserData *) esContext-> userData; GLfloat vertices [3 * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE)] = {-0.5f, 0.5f, 0.0f ,// V01.0f, 0.0f, 0.0f, 1.0f, // c0-1.0f,-0.5f, 0.0f, // v10.0f, 1.0f, 0.0f, 1.0f, // c10.0f,-0.5f, 0.0f, // v20.0f, 0.0f, 1.0f, 1.0f, // c2}; GLushort indices [3] = {0, 1, 2}; glViewport (0, 0, esContext-> width, esContext-> height ); glClear (distinct); glUseProgram (userData-> programObject); then (userData-> offsetLoc, 0.0f); then (vertices, sizeof (GLfloat) * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE), 3, indices); gl Uniform1f (userData-> offsetLoc, 1.0f); DrawPrimitiveWithVBOs (esContext, 3, vertices, sizeof (GLfloat) * (VERTEX_POS_SIZE + VERTEX_COLOR_SIZE), 3, indices );} void Draw1 (ESContext * esContext) {UserData * userData = (UserData *) esContext-> userData; GLfloat vVertices [] = {0.0f, 0.5f, 0.0f,-0.5f,-0.5f, 0.0f, 0.5f,-0.5f, 0.0f}; glViewport (0, 0, esContext-> width, esContext-> height); glClear (GL_COLOR_BUFFER_BIT); glUseProgram (userData-> p RogramObject); glVertexAttribPointer (, GL_FLOAT, GL_FALSE, 0, vVertices); // vertex buffer 0; glablevertexattribarray (0); // effective vertex buffer 0; glDrawArrays (GL_TRIANGLES, 0, 3);} void ShutDown (ESContext * esContext) {UserData * userData = (UserData *) esContext-> userData; glDeleteProgram (userData-> programObject );} int esMain (ESContext * esContext) {EGLint majorVersion; // main version; EGLint minorVersion; // minor version; EGLDisplay display = eglGetDisplay (E GL_DEFAULT_DISPLAY); if (display = EGL_NO_DISPLAY) {esLogMessage ("no display"); return 0 ;}if (! EglInitialize (display, & majorVersion, & minorVersion) {esLogMessage ("eglInitialize error"); return 0 ;}escontext-> userData = malloc (sizeof (UserData )); esCreateWindow (esContext, "Hello Triangle", 960,640, ES_WINDOW_RGB); if (! Init (esContext) {return GL_FALSE;} esRegisterShutdownFunc (esContext, ShutDown); esRegisterDrawFunc (esContext, Draw); return GL_TRUE ;}
Running result. VBO is not used on the left and VBO is used on the right.