顶点缓冲区没有很好地更新

Vertex Buffer Is not updated well

大家好,我用 opengles 绘制了一个立方体。 每次我调用重绘函数时,我都会使用此代码

更新 coordinates_buffer
floatBuffer.position(0);

floatBuffer.put(coordinates);
floatBuffer.position(0);

问题是在不同的设备上(大多数设备有 api 版本 22 或更高版本)第一个元素没有更新,所以我可以看到其余的顶点移动,而第一个保留在最开始位置。 另一个问题是,当我放置坐标时,有时会发生 java.nio.BufferOverflowException。我认为这些错误仍然存​​在于每秒调用 60 次的代码行上。

感谢大家。

1) 确保您提供的绘图调用 (glDrawArrays/glDrawElements) 具有正确的偏移量。
2) Buffer.put() 和 .get() 方法根据传输的元素数量增加位置。 Buffer.put() 方法 returns BufferOverflowException 如果这样的传输超过限制。 确保你没有传递一个对于这个缓冲区来说太大的数组。 此外,如果您只想在 3D 中移动整个对象 space,请使用矩阵计算顶点着色器中的最终顶点位置。

好吧,除了 java.nio.BufferOverflowException,我遇到了类似的问题。我正在使用这个 OpenGL library,它非常易于使用,并且有很多预制形状,例如:圆形、矩形、图像、三角形等等。

我在 OnTouch 事件中使用 Images class 为多个图像生成新坐标,但我在 [= =37=] *updateBuffers() 方法。

fun updateBuffers() {

    // init buffer for vertices
    var byteBuffer: ByteBuffer = ByteBuffer.allocateDirect(coordinatesOpenGL.size * 4)
    byteBuffer.order(ByteOrder.nativeOrder())
    vertexBuffer = byteBuffer.asFloatBuffer()
    vertexBuffer.put(coordinatesOpenGL)
    vertexBuffer.position(0)
     
    ...
}

明显的原因是,当我们使用数组[=33]ByteBuffer.allocateDirect()方法分配字节缓冲区的大小时=]coordinatesOpenGL.size 数组大小发生一些变化。在单线程环境下不太可能发生,所以我当时的结论是,OpenGL表面线程之外还有另一个线程在调用该方法。

为了查明是否是这种情况,我在方法中记录了当前线程的 ID 和名称,因此在调用它时我会收到一条消息。这是记录当前线程的 ID 和名称的代码:

Log.i("msg", "${Thread.currentThread().id}  ${Thread.currentThread().name}")

然后在Log中看到主线程也在调用这个方法,当多个线程同时调用并且都对ByteBuffer进行修改时出现溢出错误

2020-12-16 05:54:12.461 26477-26516/com.slaviboy.test I/msg: 3074  GLThread 3074
2020-12-16 05:54:13.383 26477-26516/com.slaviboy.test I/msg: 3074  GLThread 3074
2020-12-16 05:54:13.401 26477-26516/com.slaviboy.test I/msg: 3074  GLThread 3074
2020-12-16 05:54:14.080 26477-26516/com.slaviboy.test I/msg: 3074  GLThread 3074
2020-12-16 05:54:14.097 26477-26477/com.slaviboy.test I/msg: 2  main
2020-12-16 05:54:14.098 26477-26516/com.slaviboy.test I/msg: 3074  GLThread 3074
2020-12-16 05:54:14.116 26477-26516/com.slaviboy.test I/msg: 3074  GLThread 3074

然后我意识到,由于我在 OnTouch 事件中设置了图像的坐标,代码 运行ning 在主线程上,所以我不得不包装代码并在 OpenGL 表面执行它线程。

这是我用来 运行 OpenGL 表面线程中的代码,而不是主线程中的代码:

override fun onTouch(surfaceView: View, event: MotionEvent): Boolean {

    if (surfaceView is GLSurfaceView) {

       // run the code in the OpenGL surface thread
       surfaceView.queueEvent(Runnable {
           touch(event)
       })
    }

    return consumedTouchEvent
}

所以如果有类似的问题我想你首先检查是否有另一个线程进行相同的调用。