【问题标题】:GL_INVALID_FRAMEBUFFER_OPERATION Android NDK GL FrameBuffer and glReadPixels returns 0 0 0 0GL_INVALID_FRAMEBUFFER_OPERATION Android NDK GL FrameBuffer 和 glReadPixels 返回 0 0 0 0
【发布时间】:2013-04-02 15:27:39
【问题描述】:

我的 C++ 代码是为 iOS 设计的,现在我将其移植到 NDK 中,只做很少的修改。

我绑定帧缓冲区并调用

glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);

然后我像这样绑定主帧缓冲区

glBindFramebuffer(GL_FRAMEBUFFER, 0);

glGetError() 返回GL_INVALID_FRAMEBUFFER_OPERATION

我可以在我的帧缓冲区中绘制并使用它的纹理在主帧缓冲区中绘制它。但是当我打电话给glReadPixels 时,我得到了零

该代码在 iOS 中运行,大多数在 Android 中运行,除了 glReadPixels

glCheckFramebufferStatus(GL_FRAMEBUFFER) 返回 GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7

--

我会考虑一些示例代码,它会为我提供来自帧缓冲区或纹理的像素数据,我可以将其保存为文件作为answer

现在我可以使用附加纹理绘制到缓冲区,并且可以使用该纹理在主缓冲区上绘制。但我无法从帧缓冲区/纹理中获取像素以保存到文件或发布到 facebook。

【问题讨论】:

  • 分别绑定framebuffer和glReadPixels之后glGetError()的结果是什么?
  • 0 和 1268 (0x506) GL_INVALID_FRAMEBUFFER_OPERATION 我现在要查询glCheckFramebufferStatus
  • 您确定您没有无意中利用了 Android 上不存在的 iOs 扩展(例如,两个纹理的非幂或颜色/深度缓冲区的某些不受支持的格式)?创建每个纹理后 glGetError 是否返回任何特殊内容?我不是一个 OpenGL 专家,但是在最意想不到的地方用 assert(glGetError() == 0) 喷洒我的代码总是会给我带来有趣的结果...... :)
  • 我使用的是 NPOT 纹理并且它有效。我能够在屏幕上绘制帧缓冲区 NPOT 纹理。但是现在我有 512x512 teture 并且让glReadPixels 工作没有帮助。现在我在这里和那里添加glGetError()
  • 当我创建缓冲区时,我得到 GL_FRAMEBUFFER_COMPLETE

标签: android glreadpixels


【解决方案1】:

我已经能够从修改 NDK 示例“GL2JNIActivity”的帧缓冲区执行 glReadPixels。

我刚刚改了gl_code.cpp,在里面添加了一个初始化函数:

char *pixel = NULL;
GLuint fbuffer, rbuffers[2];
int width, height;
bool setupMyStuff(int w, int h) {
     // Allocate the memory
     if(pixel != NULL) free(pixel);
     pixel = (char *) calloc(w * h * 4, sizeof(char)); //4 components
     if(pixel == NULL)  {
                  LOGE("memory not allocated!");
                       return false;
                       }

                       // Create and bind the framebuffer
    glGenFramebuffers(1, &fbuffer);
    checkGlError("glGenFramebuffer");

    glBindFramebuffer(GL_FRAMEBUFFER, fbuffer);
    checkGlError("glBindFramebuffer");

    glGenRenderbuffers(2, rbuffers);
    checkGlError("glGenRenderbuffers");

    glBindRenderbuffer(GL_RENDERBUFFER, rbuffers[0]);
    checkGlError("glGenFramebuffer[color]");

    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB565, w, h);
    checkGlError("glGenFramebuffer[color]");

    glBindRenderbuffer(GL_RENDERBUFFER, rbuffers[1]);
    checkGlError("glGenFramebuffer[depth]");

    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, w, h);
    checkGlError("glGenFramebuffer[depth]");

    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbuffers[0]);
    checkGlError("glGenFramebuffer[color]");
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,  GL_RENDERBUFFER, rbuffers[1]);
    checkGlError("glGenFramebuffer[depth]");

    if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
                                                    LOGE("Framebuffer not complete");
                                                    return false;
    }

    // Turn this on to confront the results in pixels when the fb is active with the ones obtained from the screen
    if(false) {
                  glBindFramebuffer(GL_FRAMEBUFFER, 0);
        checkGlError("glBindFramebuffer");
    }

    width = w;
    height = h;

    return true;
}

它只是初始化帧缓冲区并为输出分配空间,我在结束时调用它

bool setupGraphics(int w, int h);

和一个块将输出保存在我的像素数组中(我显然在

    checkGlError("glDrawArrays");

renderFrame() 中的语句:

{ 
// save the output of glReadPixels somewhere... I'm a noob about JNI however, so I leave this part as an exercise for the reader ;-)
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
checkGlError("glReadPixel(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixel)");
int end = width * height * 4 - 1;
// This function returns the same results regardless of where the data comes from (screen or fbo)
LOGI("glReadPixel => (%hhu,%hhu,%hhu,%hhu),(%hhu,%hhu,%hhu,%hhu),(%hhu,%hhu,%hhu,%hhu),..., (%hhu, %hhu, %hhu, %hhu)",
      pixel[0], pixel[1], pixel[2], pixel[3],
      pixel[4], pixel[5], pixel[6], pixel[7],
      pixel[8], pixel[9], pixel[10], pixel[11],
      pixel[end - 3], pixel[end - 2], pixel[end - 1], pixel[end]);
}

无论是在帧缓冲区还是屏幕上绘制,logcat 中的结果都是相同的:

I/libgl2jni( 5246): glReadPixel => (0,4,0,255),(8,4,8,255),(0,4,0,255),..., (0, 4, 0, 255)
I/libgl2jni( 5246): glReadPixel => (8,4,8,255),(8,8,8,255),(0,4,0,255),..., (8, 8, 8, 255)
I/libgl2jni( 5246): glReadPixel => (8,8,8,255),(8,12,8,255),(8,8,8,255),..., (8, 8, 8, 255)
I/libgl2jni( 5246): glReadPixel => (8,12,8,255),(16,12,16,255),(8,12,8,255),..., (8, 12, 8, 255)
I/libgl2jni( 5246): glReadPixel => (16,12,16,255),(16,16,16,255),(8,12,8,255),..., (16, 16, 16, 255)
[...]

在 Froyo(手机)和 4.0.3 平板电脑上测试。

您可以在原始 NDK 示例 (GL2JNIActivity) 中找到所有其他详细信息。

希望对你有帮助

编辑:还要确保检查:

Android NDK glReadPixels() from offscreen buffer

张贴者似乎有与您相同的症状(并解决了从正确线程调用 glReadPixels 的问题)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    • 2020-10-28
    • 2015-06-15
    • 1970-01-01
    相关资源
    最近更新 更多