如何在OpenGL Es 2.0中正确更新顶点数组?

当我在OpenGL 2.0中更新iOS上的顶点数组时,原始顶点数据停留在屏幕上 – 即第一次刷新是持久的(我向下发送到GPU的初始点集每帧渲染),但第二次,第3,第4,…第n次冲洗似乎都覆盖了相同的记忆。

所以我在做:

vector rawDynamicData ; glGenVertexArraysOES( 1, &va ) ; CHECK_GL ; glBindVertexArrayOES( va ) ; CHECK_GL ; glGenBuffers( 1, &vb ) ; CHECK_GL ; glBindBuffer( GL_ARRAY_BUFFER, vb ) ; CHECK_GL ; glBufferData( glBufferData( GL_ARRAY_BUFFER, //Specifies the target buffer object. rawDynamicData.size() * sizeof( VertexType ), &rawDynamicData[0], GL_DYNAMIC_DRAW // I plan to update the data every frame ) ; CHECK_GL ; 

在随后的帧中,我只是再次打电话:

 // update the data glBufferData( glBufferData( GL_ARRAY_BUFFER, //Specifies the target buffer object. rawDynamicData.size() * sizeof( VertexType ), &rawDynamicData[0], GL_DYNAMIC_DRAW // I plan to update the data every frame ) ; CHECK_GL ; 

我也试过了

 //update the data GLvoid* vbo_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES); memcpy(vbo_buffer, &rawDynamicData[0], rawDynamicData.size()*sizeof(VertexType) ); glUnmapBufferOES(GL_ARRAY_BUFFER); 

但是通过这两种方式,我得到了这个:

在此处输入图像描述

白点是初始数据,红点是后续调用glBufferData的结果

所以这个问题在OpenGL ES 2.0中有关于动态vbos的几个部分:

  1. 创建动态顶点缓冲区的正确命令顺序是什么,其元素将在每个帧上 完全更新?

  2. 顶点缓冲区可以在帧之间增长吗? 或者我必须冲洗完全相同的尺寸?

  3. 我知道使用“客户端内存”指针,你能在OpenGL ES 2.0中做到这一点(避免使用memcpy)还是不赞成使用顶点缓冲区?

失火#1

我在这里找到了一个答案,它指出我使用glSubBufferData在数组中停放数据,并仅使用glBufferData进行初始分配。 最终这不起作用(如果vb太大,只会更新前3个元素),

所以,

 glBufferData( glBufferData( GL_ARRAY_BUFFER, //Specifies the target buffer object. rawDynamicData.size() * sizeof( VertexType ), 0, // NO INITIAL DATA GL_DYNAMIC_DRAW // I plan to update the data every frame ) ; CHECK_GL ; 

然后是第一次后续更新:

 // Update the whole buffer glBufferSubData(GL_ARRAY_BUFFER, 0, rawDynamicData.size()*sizeof(VertexType), &rawDynamicData[0]) ; 

这似乎有效。

看起来。 但事实并非如此。

我唯一能做到的就是使用顶点缓冲区退出并使用客户端内存顶点数组

这看起来如下:

 // do all your vertex attrib/glVertexAttrib enable commands: glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(VertexPC), &debugPoints->data[0].pos.x) ; CHECK_GL ; glEnableVertexAttribArray(0); CHECK_GL ; // ..do glVertexAttrib* for all attributes you have.. // then just flush your draw command glDrawArrays(GL_POINTS, 0, debugPoints->data.size()); 

简而言之,我发现将顶点缓冲区用于动态数据要么具有挑战性, 要么不受支持。

对于那里的Android用户,我刚刚确认可以在Android上的OpenGL ES 2.0中使用顶点属性数组进行可变形几何体测试。 令人讨厌的是你不能将指针传递给你自己的数组,而是你必须使用FloatBuffer(或类似的类型)。 示例代码:

初始化:

  // initialize vertex byte buffer for shape coordinates ByteBuffer bb = ByteBuffer.allocateDirect( // (number of coordinate values * 4 bytes per float) coords.length * 4); // use the device hardware's native byte order bb.order(ByteOrder.nativeOrder()); // create a floating point buffer from the ByteBuffer vertexBuffer = bb.asFloatBuffer(); // add the coordinates to the FloatBuffer vertexBuffer.put(coords); // set the buffer to read the first coordinate vertexBuffer.position(0); 

绘图代码:

  // get handle to vertex shader's vPosition member mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); checkGlError("glGetAttribLocation"); // Enable a handle to the triangle vertices GLES20.glEnableVertexAttribArray(mPositionHandle); checkGlError("glEnableVertexAttribArray"); float newValue = (float) Math.sin((float) (frame++) / 1000) + 1; System.out.println(newValue); vertexBuffer.put(0, newValue); // Prepare the triangle coordinate data GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, VERTEX_STRIDE, vertexBuffer);