我正在开发一些 Android 代码,用于在 EGL 上下文的丢失和重新创建之间缓存和重绘帧缓冲区对象的颜色缓冲区。开发主要发生在运行 Honeycomb 的 Xoom 平板电脑上。无论如何,我要做的是将在 FBO 上调用 glReadPixels() 的结果存储在直接的 ByteBuffer 中,然后将该缓冲区与 glTexImage2D() 一起使用并将其绘制回(现已清除)帧缓冲区。所有这一切似乎工作正常——ByteBuffer 包含正确的值([-1, 0, 0, -1] 等像素,根据 Java 无法理解无符号字节),似乎没有抛出 GlErrors,并且四边形被绘制到屏幕的右侧(当前为测试目的的帧缓冲区的左上角四分之一)。
但是,无论我尝试什么, glTexImage2D() 总是输出纯黑色纹理。我之前遇到过一些问题——在显示位图时,我最终放弃了尝试将基本的 GLES20.glTexImage2D() 与缓冲区一起使用,而是转而使用 GLUtils.glTexImage2D(),它会为您处理位图。不幸的是,这不是一个选项(我确实尝试将 ByteBuffer 转换为位图,以便我可以使用 GLUtils,但没有取得多大成功),所以我真的没有什么想法了。
谁能想到任何可能导致 glTexImage2D() 无法正确处理完美的 ByteBuffer 的事情?欢迎任何和所有建议。
ByteBuffer pixelBuffer;
void storePixels() {
try {
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbuf);
pixelBuffer = ByteBuffer.allocateDirect(width * height * 4).order(ByteOrder.nativeOrder());
GLES20.glReadPixels(0, 0, width, height, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, pixelBuffer);
GLES20.glBindFrameBuffer(GLES20.GL_FRAMEBUFFER, 0);
gfx.checkGlError("store Pixels");
}catch (OutOfMemoryError e) {
pixelBuffer = null;
}
}
void redrawPixels() {
GLES20.glBindFramebuffer(GL20.GL_FRAMEBUFFER, fbuf);
int[] texId = new int[1];
GLES20.glGenTextures(1, texId, 0);
int bufferTex = texId[0];
GLES20.glBindTexture(GL20.GL_TEXTURE_2D, bufferTex);
GLES20.glTexParameterf(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MAG_FILTER, GL20.GL_LINEAR);
GLES20.glTexParameterf(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_MIN_FILTER, GL20.GL_LINEAR);
GLES20.glTexParameterf(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_S, repeatX ? GL20.GL_REPEAT
: GL20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameterf(GL20.GL_TEXTURE_2D, GL20.GL_TEXTURE_WRAP_T, repeatY ? GL20.GL_REPEAT
: GL20.GL_CLAMP_TO_EDGE);
GLES20.glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_RGBA, width, height, 0, GL20.GL_RGBA, GL20.GL_UNSIGNED_BYTE, pixelBuffer);
gfx.drawTexture(bufferTex, width, height, Transform.IDENTITY, width/2, height/2, false, false, 1);
GLES20.glDeleteTextures(1, IntBuffer.wrap(new int[] {bufferTex}));
pixelBuffer = null;
GLES20.glBindFrameBuffer(GLES20.GL_FRAMEBUFFER, 0);
}
顺便说一下,gfx.drawTexture() 构建一个四边形并将其绘制到当前绑定的帧缓冲区。该代码已经在我项目的其他部分经过了很好的测试——这不应该是这里的问题。