在iOS上使用OpenGL ES 2.0创建FBO的最小示例

7
我创建FBO并在我的iOS应用程序中将其用作纹理时遇到了问题。我已经在GitHub上上传了一个简化版本的应用程序,展示了这个问题。屏幕只显示一个空白屏幕和一种奇怪的颜色,而我从未设置过。检查状态显示FBO已成功创建。

https://github.com/glman74/simpleFBO

我已经查看了相关的stackoverflow问题,特别是来自datenwolf的以下链接,展示了如何使用GLUT设置FBO,但没有使用着色器。我仍然不确定我做错了什么。

https://github.com/datenwolf/codesamples/blob/master/samples/OpenGL/minimalfbo/

我还在这里附上代码的相关部分。在renderFBO方法中,我只是进行了清除操作。我本来期望在主渲染中渲染多边形时会使用这个纯色(绿色)的纹理。
FBO设置:
// intialize FBO
- (void)setupFBO
{
    fbo_width = 512;
    fbo_height = 512;

    glGenFramebuffers(1, &fboHandle);
    glGenTextures(1, &fboTex);
    glGenRenderbuffers(1, &depthBuffer);

    glBindFramebuffer(GL_FRAMEBUFFER, fboHandle);

    glBindTexture(GL_TEXTURE_2D, fboTex);
    glTexImage2D( GL_TEXTURE_2D,
                 0,
                 GL_RGBA,
                 fbo_width, fbo_height,
                 0,
                 GL_RGBA,
                 GL_UNSIGNED_BYTE,
                 NULL);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_APPLE, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0);

    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, fbo_width, fbo_height);
    glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER_APPLE, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);

    // FBO status check
    GLenum status;
    status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    switch(status) {
        case GL_FRAMEBUFFER_COMPLETE:
            NSLog(@"fbo complete");
            break;

        case GL_FRAMEBUFFER_UNSUPPORTED:
            NSLog(@"fbo unsupported");
            break;

        default:
            /* programming error; will fail on all hardware */
            NSLog(@"Framebuffer Error");
            break;
    }

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

FBO渲染:
// render FBO 
- (void)renderFBO
{
    glBindTexture(GL_TEXTURE_2D, 0);
    glEnable(GL_TEXTURE_2D);
    glBindFramebuffer(GL_FRAMEBUFFER, fboHandle);

    glViewport(0,0, fbo_width, fbo_height);
    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

主渲染:
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    // render FBO tex
    [self renderFBO];

    glViewport(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
    // render main
    glClearColor(0.65f, 0.65f, 0.65f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnable(GL_TEXTURE_2D);
    glActiveTexture(GL_TEXTURE0);

    glUniform1i(uSamplerLoc, 0);     
    // Render 
    glUseProgram(_program);

    glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
    glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

    glDisable(GL_TEXTURE_2D);
}

我可能做错了什么?
编辑#1:
我在github上对代码进行了一些小改动。尝试使用GL_FRAMEBUFFER而不是上面的GL_DRAW_FRAMEBUFFER_APPLE。还添加了一个绑定纹理调用,这是缺少的。仍然无法工作。
编辑#2:
我找到了解决方法。我需要在主渲染中调用:
// reset to main framebuffer
[((GLKView *) self.view) bindDrawable];    
1个回答

9

我找到了一个解决方案,并且已经更新了以下代码,以便对某些人有用。

https://github.com/glman74/simpleFBO/

主要问题是我需要在主渲染中调用:

// reset to main framebuffer
[((GLKView *) self.view) bindDrawable];   

这是因为我使用的是GLKView。这种情况与CAEAGLLayer示例不同。

1
谢谢,你的例子真的帮了我很多。如果有人在编译GL_DEPTH_COMPONENT24_OES时出现错误,请将其替换为GL_DEPTH_COMPONENT16。 - LightMan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接