Android OpenGL ES 2.0——glReadPixels() 和 glTexImage2D() 绘制黑色纹理?

标签 android opengl-es opengl-es-2.0 glreadpixels glteximage2d

我正在编写一些 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() 构建一个四边形并将其绘制到当前绑定(bind)的帧缓冲区。该代码已在我项目的其他部分进行了充分测试——这不应该是这里的问题。

最佳答案

对于那些在家里一起玩的人来说,这个代码实际上是完全有效的。还记得当我盲目地发誓说 gfx.drawTexture() 已经过良好测试并且不应该成为这里的问题吗?是的,这完全是那里的问题。我正在缓冲要绘制的顶点而实际上没有通过 glDrawElements() 调用刷新它们。糟糕。

关于Android OpenGL ES 2.0——glReadPixels() 和 glTexImage2D() 绘制黑色纹理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7208255/

相关文章:

android - PeriodicSync 不适用于 android kitkat 和 lollipop

java - [Android]如何在Android中加载swf文件(API 23)

android - 使用GLES20的Vertex Buffer Objects(VBO)在Android 2.3.3上不起作用

libgdx - GLSL ES - 使用重复将纹理从直角坐标映射到极坐标

java - 如何检查首选项是否存在

安卓 ICS : JNI error attempt to use stale local reference 0x1

ios - Unity3D 4.1 导致 Everyplay 损坏 - "iPhone_GlesSupport.h"丢失

android - 我怎样才能得到更有帮助的 GLSL 编译错误?

android - 相机 View 上的 opengl 叠加

android - CircleCI:在 .yml 文件中为同一存储库中的多个项目设置工作目录