使用 OpengGLES2(角度)从帧缓冲区对象中读取

Reading from frame buffer object with OpengGLES2 (Angle)

使用 Angle 将 UWP 应用程序编程为 运行 OpenGL ES,我遇到了使用 glReadPixels 从帧缓冲区对象读取的基本操作的问题。 从 Visual Studio 模板 "OpenglES2 Application (Android,iOS,Windows Universal)" 开始,我可以将默认场景渲染检索到内存缓冲区中。

初始化:

void SimpleRenderer::InitFbo()
{
    int buf_size = tex_height*tex_width * 4;
    mReadBuf = new char[buf_size];
    memset(mReadBuf, 123, buf_size); // arbitrary value to detect changes
}

绘图函数:

void SimpleRenderer::Draw()
{

    // drawing calls here
    // (...)

    glReadPixels(0, 0, tex_width, tex_height, GL_RGBA, GL_UNSIGNED_BYTE, mReadBuf);
    // success : mReadBuf is updated with pixel values
}

但是如果我只是创建一个帧缓冲区对象,尝试在其中绘制并检索结果,glReadPixels 不会 return 任何值,并且 glError returns INVALID_FRAMEBUFFER_OPERATION.

初始化:

void SimpleRenderer::InitFbo()
{
    glGenFramebuffers(1, &mRenderFbo);
    glGenTextures(1, &mRenderTexture);
    int buf_size = tex_height*tex_width * 4;
    char*buf = new char[buf_size];
    memset(buf, 255, buf_size);

    glBindTexture(GL_TEXTURE_2D, mRenderTexture);
    glTexImage2D(GL_TEXTURE_2D, 0, 4,
            tex_width,
            tex_height,
            0, GL_RGBA, GL_UNSIGNED_BYTE,
            buf);

    glBindFramebuffer(GL_FRAMEBUFFER, mRenderFbo);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
            mRenderTexture, 0);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    delete[] buf;

    mReadBuf = new char[buf_size];
    memset(mReadBuf, 123, buf_size);
}

绘图函数:

void SimpleRenderer::Draw()
{
    glBindFramebuffer(GL_FRAMEBUFFER, mRenderFbo);

    // drawing calls here
    // (...)

    glReadPixels(0, 0, tex_width, tex_height, GL_RGBA, GL_UNSIGNED_BYTE, mReadBuf);

    // failure : mReadBuf is unchanged

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

*edit - 由于下面的评论解决了。纹理的正确初始化是

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
    tex_width,
    tex_height,
    0, GL_RGBA, GL_UNSIGNED_BYTE,
    buf);

郑重声明,在它得到解决之前,我正在使用 glCheckFramebufferStatus 检查帧缓冲区状态,returned GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT

OpenGL函数的第三个参数glTexImage2D指定纹理缓冲区的内部格式。

在方法 SimpleRenderer::InitFbo 中,您将 4 传递给内部格式,这不是有效参数。使用 GL_RGBA 代替:

glTexImage2D(GL_TEXTURE_2D, 0, 
        GL_RGBA,   // <-----------------------
        tex_width,
        tex_height,
        0, GL_RGBA, GL_UNSIGNED_BYTE,
        buf);

请注意,内部格式(在 OpenGL ES 2.0 中)的有效参数为 GL_ALPHAGL_LUMINANCEGL_LUMINANCE_ALPHAGL_RGBGL_RGBA

如果您在调用 glTexImage2D 之后使用 glGetError,您将得到 GL_INVALID_VALUE,如果内部格式不是可接受的格式,则会生成该代码。此外,如果纹理附加到帧缓冲区并且 glReadPixels 导致 INVALID_FRAMEBUFFER_OPERATION 错误,这会导致 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 错误(使用 glCheckFramebufferStatus 检查时)。