大家好我有一个用opengles绘制的立方体。 每次我调用重绘功能时,我都会使用此代码更新coordinate_buffer
floatBuffer.position(0);
floatBuffer.put(coordinates);
floatBuffer.position(0);
问题在于,在不同的设备上(大多数设备都有api版本22或更高版本),第一个元素没有更新,因此我可以看到在第一个元素停留在第一个位置时移动的其余顶点。 另一个问题是,当我放置坐标时,有时会发生java.nio.BufferOverflowException。我认为错误仍然存在于这些被称为60次的代码行中。
非常感谢。
答案 0 :(得分:0)
1)确保您提供正确偏移的绘制调用(glDrawArrays / glDrawElements)。
2)Buffer.put()和.get()方法根据传输的元素数量来增加位置。如果此类传输超出限制,Buffer.put()方法将返回BufferOverflowException。
确保您没有传递对于此缓冲区而言太大的数组。
此外,如果您只想在3D空间中移动整个对象,则使用矩阵计算顶点着色器中的最终顶点位置。
答案 1 :(得分:0)
嗯,除了 java.nio.BufferOverflowException 以外,我也遇到了类似的问题。我使用的OpenGL library非常易于使用,并具有许多预制的形状,例如:圆形,矩形,图像,三角形等。
我正在使用 Images 类在OnTouch事件中为多个图像生成新坐标,并且在
处出现了异常错误,看起来像是随机的
* 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)
...
}
一个明显的原因是,当我们使用数组 coordinatesOpenGL.size 的大小使用方法 ByteBuffer.allocateDirect()分配字节缓冲区的大小时,数组大小发生一些变化。在单线程环境中,这种情况不太可能发生,因此我当时的结论是,OpenGL表面线程之外还有另一个线程正在对该方法进行调用。
要确定是否是这种情况,我在方法中记录了当前线程的ID和名称,因此在调用它时会收到一条消息。这是记录当前线程的ID和名称的代码:
Log.i("msg", "${Thread.currentThread().id} ${Thread.currentThread().name}")
然后在日志中,我看到主线程也在调用此方法,当多个线程同时调用它并且都对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事件中设置了图像的坐标,因此代码在主线程上运行,因此我不得不将代码包装并在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
}
因此,如果遇到类似问题的问题,我想您首先检查是否有另一个线程进行相同的调用。