如何在 OpenGL ES 2 中创建和使用 VBO
Posted
技术标签:
【中文标题】如何在 OpenGL ES 2 中创建和使用 VBO【英文标题】:How to create and use VBOs in OpenGL ES 2 【发布时间】:2018-02-04 00:53:26 【问题描述】:我正在寻求有关理解 VBO 的帮助。我已经进行了大量研究并找到了有关该主题的教程,但它们对我来说仍然含糊不清。我有几个问题:
应该在哪里创建 VBO,我应该如何创建?
我目前正在使用下面的代码来初始化我的顶点和索引缓冲区:
vertices = new float[]
p[0].x, p[0].y, 0.0f,
p[1].x, p[1].y, 0.0f,
p[2].x, p[2].y, 0.0f,
p[3].x, p[3].y, 0.0f,
;
// The order of vertex rendering for a quad
indices = new short[] 0, 1, 2, 0, 2, 3;
ByteBuffer bb = ByteBuffer.allocateDirect(vertices.length * 4);
bb.order(ByteOrder.nativeOrder());
vertexBuffer = bb.asFloatBuffer();
vertexBuffer.put(vertices);
vertexBuffer.position(0);
ByteBuffer dlb = ByteBuffer.allocateDirect(indices.length * 2);
dlb.order(ByteOrder.nativeOrder());
drawListBuffer = dlb.asShortBuffer();
drawListBuffer.put(indices);
drawListBuffer.position(0);
如果我是正确的,这不是创建 VBO。那么,如果我想制作 VBO,创建 VBO 的代码会紧跟上面列出的代码吗?如果有,如何创建?
另外,如何将 VBO 渲染和绘制到屏幕上?
它的渲染和绘制方式是否与仅使用顶点和索引数组相同?如果不是,流程是什么?目前,我渲染和绘制我的对象,如下面的代码所示:
GLES20.glUseProgram(GraphicTools.sp_SolidColor);
mPositionHandle =
GLES20.glGetAttribLocation(GraphicTools.sp_SolidColor, "vPosition");
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glVertexAttribPointer(mPositionHandle, 3,
GLES20.GL_FLOAT, false,
0, vertexBuffer);
mtrxHandle = GLES20.glGetUniformLocation(GraphicTools.sp_SolidColor,
"uMVPMatrix");
GLES20.glUniformMatrix4fv(mtrxHandle, 1, false, m, 0);
GLES20.glDrawElements(GLES20.GL_TRIANGLES, indices.length,
GLES20.GL_UNSIGNED_SHORT, drawListBuffer);
GLES20.glDisableVertexAttribArray(mPositionHandle);
如果您有任何问题,请告诉我。提前致谢。
【问题讨论】:
【参考方案1】:Vertex Buffer Object 是一个可以存储顶点数组数据的缓冲区。数据一次性上传到图形内存(GPU),可以重复使用绘制网格。
首先您必须创建 2 个缓冲区对象,一个用于顶点,一个用于索引:
int buffers[] = new int[2];
GLES20.glGenBuffers(2, buffers, 0);
int vbo = buffers[0];
int ibo = buffers[1];
然后你必须绑定缓冲区并传输数据
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo);
GLES20.glBufferData(
GLES20.GL_ARRAY_BUFFER,
vertexBuffer.capacity() * 4, // 4 = bytes per float
vertexBuffer,
GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo);
GLES20.glBufferData(
GLES20.GL_ELEMENT_ARRAY_BUFFER,
drawListBuffer.capacity() * 2, // 2 = bytes per short
drawListBuffer,
GLES20.GL_STATIC_DRAW);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
如果要绘制网格,则必须定义通用顶点属性数据数组并绑定索引缓冲区,但不必将任何数据传输到 GPU:
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo);
GLES20.glVertexAttribPointer(
mPositionHandle, 3,
GLES20.GL_FLOAT, false,
0, 0); // <----- 0, because "vbo" is bound
GLES20.glEnableVertexAttribArray(mPositionHandle);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo);
GLES20.glDrawElements(
GLES20.GL_TRIANGLES, indices.length,
GLES20.GL_UNSIGNED_SHORT, 0); // <----- 0, because "ibo" is bound
GLES20.glDisableVertexAttribArray(mPositionHandle);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
另见An Introduction to Vertex Buffer Objects (VBOs)
【讨论】:
以上是关于如何在 OpenGL ES 2 中创建和使用 VBO的主要内容,如果未能解决你的问题,请参考以下文章