10

当我在 OpenGL 2.0 中更新 iOS 上的顶点数组时,原始顶点数据保留在屏幕上——即第一次刷新是持久的(我发送到 GPU 的初始点集每帧都被渲染),但第二次刷新,第 3 次,第 4 次,.. 第 n 次刷新似乎都覆盖了相同的内存。

所以我在做:

vector<VertexType> 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 中的动态 vbo:

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

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

  3. 我知道使用“客户端内存”指针,您可以在 OpenGL ES 2.0 中执行此操作(以避免 memcpy)还是不推荐使用,应该专门使用顶点缓冲区?

4

2 回答 2

6

失火#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());  

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

于 2012-09-22T10:56:23.363 回答
1

对于那里的 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);
于 2013-07-24T03:28:05.523 回答