Hello everyone, this is my OpenGL ES advanced advanced series of articles, there is a corresponding project on my Github, welcome to follow, link: github.com/kenneycode/…

Vertex Buffer Object (IBO) Vertex Buffer Object (IBO) Vertex Buffer Object (IBO)

// Put the triangle vertex data into buffer
// Put the triangle vertex data into the vertexDataBuffer
vertexDataBuffer = ByteBuffer.allocateDirect(vertexData.size * java.lang.Float.SIZE / 8)
    .order(ByteOrder.nativeOrder())
    .asFloatBuffer()
vertexDataBuffer.put(vertexData)
vertexDataBuffer.position(0)

// Start the parameters for the location, using LOCATION_ATTRIBUTE_POSITION instead of the location as OpenGL 2.0 does
// Enable the parameter of the location. Here we can simply use LOCATION_ATTRIBUTE_POSITION, while in OpenGL 2.0 we have to query the location of the parameter
GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)

// Specify the vertex data used by a_position
// Specify the data of a_position
GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, VERTEX_COMPONENT_COUNT, GLES30.GL_FLOAT, false.0, vertexDataBuffer)
Copy the code

GlVertexAttribPointer () specifies the vertex data to the attribute variable in the Vertex shader. However, it does not store the vertex data in video memory all the time, and when we render, all the data to be accessed must be in video memory. Therefore, OpenGL has an operation to copy the vertex data from memory to video memory every time we render. This causes some problems:

  • One is that every rendering is copied, so the vertex data is kept in memory, otherwise there will be no data to copy.

  • The other is that if you have a lot of vertices, and you do this copy every time you render, you have a performance problem. In our example, there are very few vertices, so when do you have a lot of vertices? For example, when doing some deformation effects, mesh is often divided. Generally speaking, the more the mesh is divided, the more delicate the effect will be, and there will be many vertices. In addition, when doing 3D rendering, there are usually many vertices, and a single 3D model can even have tens of thousands of vertices.

So what can we do to avoid duplication? In this case, you need to use VBO, which can be bound with vertex data. The vertex data after binding is always stored in video memory. When you need to use these vertex data, you can directly bind this VBO, without copying process.

So what is IBO? It is similar to VBO, which prevents vertex data from being copied, and IBO, which prevents vertex index data from being copied. What is a vertex index? Let’s start with vertex data:

// Triangle vertex data
// The vertex data of a triangle
private val vertexData = floatArrayOf(
                            -1f, -1f./ / the bottom left corner
                            -1f.1f./ / the top left corner
                            1f.1f./ / the top right corner
                            -1f, -1f./ / the bottom left corner
                            1f.1f./ / the top right corner
                            1f, -1f     / / the bottom right hand corner
                        )                       
// Vertex index data
// The vertex data of triangles
private val indexData = intArrayOf(0.1.2.0.2.3)
Copy the code

This is a very generic piece of vertex data, which we’ve used many times in this tutorial, using two triangles to form a rectangle, using the drawing mode using GL_TRIANGLES. (See my article, Android OpenGL ES 2.0, Drawing Mode.) We can easily see that these six vertices are duplicated, that a rectangle only needs four vertices, and that some points are shared between different triangles, so how do we make them shared between different triangles? This is where we use the vertex index, which allows us to tell OpenGL our vertices by index rather than by coordinates, so we can reduce the amount of vertex data, which is useful when the number of facets is large.

So let’s see how to use VBO and IBO in detail, starting with vertex data and vertex index data:

// Triangle vertex, texture data
// The vertex data and texture coordinate data of triangles
private val vertexData = floatArrayOf(
                            -1f, -1f.0f.1f.// x, y, u, v
                            -1f.1f.0f.0f.1f.1f.1f.0f.1f, -1f.1f.1f
                        )
Copy the code

Here we combine vertices and texture coordinates, which is also a general optimization used with VBO and IBO. Its benefits make vertices and texture coordinates close to each other in storage, which facilitates OpenGL to fetch data and improve performance, especially in 3D rendering, data is generally organized in this way.

Next create VBO and IBO with glGenBuffers:

// Create VBO and IBO
// Create VBO and IBO
val buffers = IntArray(2)
GLES30.glGenBuffers(buffers.size, buffers, 0)
vbo = buffers[0]
ibo = buffers[1]
Copy the code

As we can see, there is no difference between VBO and IBO when creating them. They are called buffers and can only be shown when they are actually used.

Load the vertex texture data into VBO:

// Load vertex data into VBO
// Load vertex data into VBO
val vertexDataBuffer = ByteBuffer.allocateDirect(vertexData.size * java.lang.Float.SIZE / 8)
                                    .order(ByteOrder.nativeOrder())
                                    .asFloatBuffer()
vertexDataBuffer.put(vertexData)
vertexDataBuffer.position(0)
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo)
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, vertexDataBuffer.capacity() * java.lang.Float.SIZE / 8, vertexDataBuffer, GLES30.GL_STATIC_DRAW)
GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_POSITION)
GLES30.glEnableVertexAttribArray(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE)
GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_POSITION, 2, GLES30.GL_FLOAT, false.16.0)
GLES30.glVertexAttribPointer(LOCATION_ATTRIBUTE_TEXTURE_COORDINATE, 2, GLES30.GL_FLOAT, false.16.8)

Copy the code

The main point is to bind the buffer we are working on first with glBindBuffer. This is similar to the texture and frame buffer. And then we feed it data with glBufferData, and the last parameter here is to tell OpenGL to do some optimizations, so for example here we passed GL_STATIC_DRAW, which means our data is not going to change, and a few other things we can set, GL_DYNAMIC_DRAW tells OpenGL that the data in the buffer will change.

When glVertexAttribPointer specifies the vertex and texture data, we do not pass the data directly as before, because our data is already in the VBO, we do not need to pass the data, we focus on the last two parameters, the penlast parameter is to specify the stride, That’s how long It takes OpenGL to fetch a piece of data, because we’re combining vertex and texture data together, so a piece of data is 2 vertices and 2 texture coordinates, 4 floats, 16 bytes. The reciprocal first parameter specifies the starting position of the data in a piece of data, since we place vertices before texture coordinates in a piece of data, so the starting position is 0 for vertices and 8 bytes for texture coordinates.

Now that we have VBO and IBO set up, we can bind VBO and IBO to use the corresponding vertex and texture data when rendering:

override fun onDrawFrame(gl: GL10?). {

    // Set the clear color
    // Set the color which the screen will be cleared to
    GLES30.glClearColor(0.9 f.0.9 f.0.9 f.1f)

    / / clear screen
    // Clear the screen
    GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)

    // Set the viewport to the entire GLSurfaceView area
    // Set the viewport to the full GLSurfaceView
    GLES30.glViewport(0.0, glSurfaceViewWidth, glSurfaceViewHeight)

    // Set up the state, ready to render
    // Set the status before rendering
    GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo)
    GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, ibo)
    GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
    GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, imageTexture)

    // Call the draw method, using TRIANGLES, with three vertices
    // Call the draw method with GL_TRIANGLES to render 3 vertices
    GLES30.glDrawElements(GLES30.GL_TRIANGLES, indexData.size, GLES30.GL_UNSIGNED_INT, 0)}Copy the code

To see the effect, it is to render a picture, from the effect can not see the difference:

The code is in my Github OpenGLESPro project, the corresponding article is SampleVBOAndIBO, project link: github.com/kenneycode/…

Thanks for reading!