FBO blit depth buffer


#1

Hey folks,

I’m trying to copy the depth buffer from one FBO to another using glBlitFramebuffer();

My code appears to be working, but I’m noticing a few artifacts:

  1. MSAA doesn’t appear to be working
  2. Every time I bind the camera after copying, the perspective is flipped

Here’s what’s going on

ofFbo first;
ofFbo second;

//--------------------------------------------------------------
void ofApp::setup(){

   ofFbo::Settings settings;
   settings.width = ofGetWidth();
   settings.height = ofGetHeight();
   settings.internalformat = GL_RGBA;
   settings.useDepth = true;
   //settings.depthStencilAsTexture = true;
   //settings.depthStencilInternalFormat = GL_DEPTH_COMPONENT16_ARB;
   settings.numSamples = 8;

   first.allocate( settings );
   second.allocate( settings );
}

//--------------------------------------------------------------
void ofApp::draw(){
    
    ofBackground(50);
    ofEnableDepthTest();
    
    ofVec3f camPosition;
    camPosition.set(0, ofMap(ofGetMouseY(), 0, ofGetHeight(), -50, 50, true), 80);
    
    // -------------------------- draw into first FBO --------------------------
    
    first.begin();
    
    ofClear(50);
    
    ofCamera cam;
    cam.setPosition(camPosition);
    cam.lookAt(ofVec3f(0, 0, 0), ofVec3f(0, 1, 0));
    cam.begin();
    
    ofSetColor(127);
    ofDrawBox(0, 0, 0, 30, 30, 30);
    
    cam.end();
    
    first.end();
    
    // -------------------------- draw into second FBO --------------------------
    
    second.begin();
    
    ofClear(50);
    
    // copy depth buffer using glBlitFramebuffer()
    
    int w = first.getWidth();
    int h = first.getHeight();
    
    glBindFramebuffer(GL_READ_FRAMEBUFFER, first.getId());
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_DEPTH_BUFFER_BIT, GL_NEAREST);

    cam.setPosition(camPosition);
    cam.lookAt(ofVec3f(0, 0, 0), ofVec3f(0, 1, 0));
    cam.begin();
    
    for(int i=-100; i<=100; i+=5){
        ofDrawLine(i, -100, i, 100);
    }
    
    cam.end();
    
    // not sure if this does anything :|
    
    glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    
    second.end();
    
    GLenum err = glGetError();
    if(err!=GL_NO_ERROR)
    {
        ofLogNotice("Error while blitting") << err;
    }
   
    // -------------------------- draw second FBO (occluded) --------------------------
    
    ofSetColor(255);
    second.draw(0, 0);
    
    if( ofGetKeyPressed('d')){
        
      // draw occluded lines normally (this is how it should look)
        
        ofSetupScreen();
        
        ofBackground(50);
    
        ofCamera debugCam;
        debugCam.setPosition(camPosition);
        debugCam.lookAt(ofVec3f(0, 0, 0), ofVec3f(0, 1, 0));
        debugCam.begin();
    
        ofSetColor(127);
        ofDrawBox(0, 0, 0, 30, 30, 30);
        
        ofSetColor(255);
        for(int i=-100; i<=100; i+=5){
            ofDrawLine(i, -100, i, 100);
        }
        
        debugCam.end();
    }
}

What’s strange is that when I blit and use second.getId(), it doesn’t work, but when I use 0 as the argument, it does.

If anybody has any thoughts or tip, I’d be super grateful.

Jeremy


#2

For the record, it looks like the copying of the depth buffer needs to happen before i bind and draw into the second fbo. Still not 100% sure about the MSAA

// -------------------------- blit depth into second FBO --------------------------

// copy depth buffer using glBlitFramebuffer()

int w = first.getWidth();
int h = first.getHeight();

glBindFramebuffer(GL_READ_FRAMEBUFFER, first.getId());
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, second.getIdDrawBuffer());
glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_DEPTH_BUFFER_BIT, GL_NEAREST);

// not sure if this does anything :|

glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

 // -------------------------- draw into second FBO --------------------------

second.begin();

//ofClear(50);

// just clear the color buffer
glClearColor(0.2f, 0.2f, 0.2f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
//glDisable(GL_DEPTH_TEST);

cam.setPosition(camPosition);
cam.lookAt(ofVec3f(0, 0, 0), ofVec3f(0, 1, 0));
cam.begin();

for(int i=-100; i<=100; i+=5){
    ofDrawLine(i, -100, i, 100);
}

cam.end();
second.end();