如何恢复GL_RENDERBUFFER?

时间:2016-09-11 03:22:07

标签: ios opengl-es framebuffer opengl-es-3.0

我正在努力存储和恢复基于OpenGL ES的应用程序状态。

我有一个函数来保存GL_RENDERBUFFER以使用以下代码转储数据:

glBindFramebuffer(GL_FRAMEBUFFER, fboTextureBufferData.framebuffer);
glBindRenderbuffer(GL_RENDERBUFFER, fboTextureBufferData.colorbuffer);

GLint x = 0, y = 0, width2 = backingWidth, height2 = backingHeight;
NSInteger dataLength = width * height * 4;
GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte));

// Read pixel data from the framebuffer
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);

我没有看到glWritePixels函数。使用上面填充的GLubyte数据重新填充GL_RENDERBUFFER的最佳方法是什么?一个例子将不胜感激。

编辑3:

以下是我尝试配置纹理渲染缓冲区以及用于绘制它的函数。如代码中所述,如果我为glFramebufferTexture2D参数指定GL_COLOR_ATTACHMENT1,则存储的像素数据将被恢复,但我无法获取任何更新。但是如果我使用GL_COLOR_ATTACHMENT0,我会得到绘图更新但没有恢复像素数据。

我尝试了各种组合(例如也使用GL_COLOR_ATTACHMENT1作为glFramebufferRenderbuffer参数)但是在尝试渲染时我得到了无效的帧缓冲区错误。我似乎非常接近,但无法弄清楚如何让它们恢复和渲染一起工作。

- (bool)configureRenderTextureBuffer {

    [EAGLContext setCurrentContext:context];

    glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];

    glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);
    [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];

    glGenFramebuffers(1, &fboTextureBufferData.framebuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, fboTextureBufferData.framebuffer);

    glGenRenderbuffers(1, &fboTextureBufferData.colorbuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, fboTextureBufferData.colorbuffer);

    glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, backingWidth, backingHeight);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboTextureBufferData.colorbuffer);

    // Generate texture name, stores in .textureID
    glGenTextures(1, &fboTextureBufferData.textureID);

    glBindTexture(GL_TEXTURE_2D, fboTextureBufferData.textureID);

    ////////////////// Read Existing texture data //////////////////
    NSString *dataPath = [TDTDeviceUtilitesLegacy documentDirectory]; //This just returns the app's document directory
    NSData *data = [NSData dataWithContentsOfFile:[NSString stringWithFormat:@"%@/buffer.data", dataPath]];
    GLubyte *pixelData = (GLubyte*)[data bytes];

    // If I use GL_COLOR_ATTACHMENT1 here, my existing pixel data is restored
    // but no drawing occurs. If I use GL_COLOR_ATTACHMENT0, then data isn't
    // restored but drawing updates work
    glFramebufferTexture2D ( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, fboTextureBufferData.textureID, 0 );

    // Populate with existing data
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, backingWidth, backingHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, &pixelData[0]); //&image[0]

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER) ;
    if(status != GL_FRAMEBUFFER_COMPLETE) {
        NSLog(@"failed to make complete render texture framebuffer object %x", status);
        return false;
    }

    return true;
}

这是渲染的代码。 viewFramebuffer附加到GL_COLOR_ATTACHMENT0并使用,因此纹理框架缓冲区可以缩放并定位在视图内。

- (void)renderTextureBuffer {

    //Bind the texture frame buffer, if I don't use this, I can't get it to draw
    //glBindFramebuffer(GL_FRAMEBUFFER, fboTextureBufferData.framebuffer);

    //If I use this instead of binding the framebuffer above, I get no drawing and black background
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTextureBufferData.textureID, 0);

    renderParticlesToTextureBuffer();

    //Bind the view frame buffer.
    glBindFramebuffer(GL_FRAMEBUFFER, viewFramebuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, viewRenderbuffer);

    drawFboTexture();

    [context presentRenderbuffer:GL_RENDERBUFFER];
}

1 个答案:

答案 0 :(得分:3)

如果需要将数据直接写入渲染目标,则使用渲染缓冲区不是一个好选择。在这种情况下,使用纹理要好得多。

将纹理用作FBO附件与使用渲染缓冲区非常相似。您当前使用glRenderbufferStorage()分配所需维度的渲染缓冲区的位置,而是创建纹理,并使用以下内容分配其存储:

GLuint texId = 0;
glGenTextures(1, &texId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
    GL_RGBA, GL_UNSIGNED_SHORT_5_6_5, 0);

然后用:

将它附加到帧缓冲区
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);

现在,如果您以后想要使用数据填充渲染目标,则只需再次调用glTexImage2D(),如果尺寸不变,则可以更好地调用glTexSubImage2D()