【发布时间】:2016-11-08 04:26:52
【问题描述】:
每帧更新 VBO 数据的最佳方法是什么?目前我正在使用 glBufferSubData 在每帧调用 glBufferData 后使用 null ,并且我不能达到超过 25fps 而不会出现奇怪的口吃。
我的主要目标是以 50fps 的速度在两张图像之间翻转。
这是一些代码:
public void onDrawFrame(GL10 glUnused) {
endTime = System.currentTimeMillis();
dt = endTime - startTime;
if (dt < 20)
try {
Thread.sleep(20 - dt);
} catch (InterruptedException e) {
e.printStackTrace();
}
startTime = System.currentTimeMillis();
...some matrix operations
render();
}
void render() {
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, vbo[0]);
GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, floatbuffer.capacity() * BYTES_PER_FLOAT,
null, GLES20.GL_STREAM_DRAW);
...a bunch of if statements
if(side==1) {
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, floatbuffer.capacity() * BYTES_PER_FLOAT,floatbuffer);
side = 0;
} else {
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, floatbuffer2.capacity() * BYTES_PER_FLOAT, floatbuffer2);
side = 1;
}
GLES20.glVertexAttribPointer(positionAttribute, POSITION_DATA_SIZE_IN_ELEMENTS, GLES20.GL_FLOAT, false, STRIDE, 0);
GLES20.glEnableVertexAttribArray(positionAttribute);
GLES20.glVertexAttribPointer(colorAttribute, COLOR_DATA_SIZE_IN_ELEMENTS, GLES20.GL_FLOAT, false, STRIDE, (POSITION_DATA_SIZE_IN_ELEMENTS) * BYTES_PER_FLOAT);
GLES20.glEnableVertexAttribArray(colorAttribute);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, ibo[0]);
GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, indexCount, GLES20.GL_UNSIGNED_SHORT, 0);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0);
}
我还尝试设置多个 vbo,每个 vbo 都有自己不变的数据,并在我要显示的 vbo 上调用 glBindBuffer,但我仍然注意到卡顿。
我对 OpenGL 有点陌生,所以我不清楚最好的方法。我了解将数据从 CPU 传输到 GPU 可能存在瓶颈。有没有更有效的方法来解决这个问题?
【问题讨论】:
-
鉴于使用没有任何数据传输的静态 VBO 仍然卡顿,您为什么认为这是您的问题?
-
你完全正确。我查看了代码的其他部分,如果我删除了 onDrawFrame 中的 Thread.sleep() 调用,则应用程序呈现时不会卡顿(除了偶尔的失误)。您对如何正确获得恒定帧速率有任何想法吗?如果 Thread.sleep() 在如此低的毫秒数下不准确,还有什么其他方法?是否可以使用 RENDERMODE_WHEN_DIRTY 并设置另一个在正确的时间调用 requestRender() 的线程?
-
添加并回答了一些尝试的想法。