ofFBO and Core Image Filters Fix Sought


#1

I had a working OF project a few years back that implemented video feedback by drawing to an ofFBO for offscreen rendering. I would draw mix new frame over the old, including processing that FBO with Core Image Filters for blur and mixing. The Core Image gaussian blur is lovely and fast and can have a very wide radius.

This code broke after OS 10.9 – the Core Image Filters no longer functioned on the FBO – and I have not been able to find a solution.

Ahbi found a solution for his ofxCoreImageFilters package, getting it to work with ofImage on newer OS’s. He noted ‘If i remember correctly, the core image fillers only work with a gl 2.0 context(Dont know if apple updated it). but open frame works uses 3.2+. So what I did was create a framebuffer within a 2.0 context and drew the image in there.’

  • Presumably, I could use Ahbi’s package – if I could figure out how to use ofImage as an offscreen FBO. But I’m scratching my head here: it is not obvious to me if one can, and if so, how it is done.

  • Or I need to figure out how to make my own FBO within a GL 2.0 context. I have the code to make my own FBO without ofFBO, but that is not obvious to me how to force that to use an OpenGL 2.0 context , and it does it become clear to me looking at Abhi’s code… (?)

Much thanks for any clues…


#2

Hey bbattey,

I’m not sure how you can do what you want but you can set the version of openGL you wan to use in your main.cpp :


int main(){
	
	ofGLWindowSettings settings;
	settings.setGLVersion(3,2);
    float w = 1920;
    float h = 1080;
    settings.setSize(w, h);
	ofCreateWindow(settings);
	ofRunApp(new ofApp());
}

hope it helps to compile with your FBO.


#3

Ah, excellent! There is hope! Although my OF (0.9.8. OSX) does not seem to be recognizing the setSize method for ofGLWindowSettings… (?)


#4

But

settings.width = 1920;
settings.height = 1080;

is recognized…


#5

** Ah yeah I’ve got it**


#6

OK, just forcing OpenGL 2.0 with the the original code is not in itself solving the problem…


#7

OK, let’s try this with some code. The following works in OF 0.9.8 on OSX 10.9, but does not work on any later Max OS’s, though no errors show up in the traps I have here.

When it works correctly, we get a lovely gauss blur extending out around the circle.

Forcing OpenGL 2.0 as per the above does not fix the situation.

Revelant items in header

    // GL
    GLint   width;
    GLint   height;
    ofFbo   sourceFbo;
    
    // Core Image
    CGLContextObj   CGLContext;
    NSOpenGLPixelFormatAttribute*   attr;
    NSOpenGLPixelFormat*    pf;
    CGColorSpaceRef genericRGB;
    CIContext*  glCIcontext;
    CIImage*    inputCIImage;
    CIFilter*   clampFilter;
    CIFilter*   blurFilter;
    CIFilter*   colorShiftFilter;
    CGSize      texSize;
    GLint       tex;
    CGRect      outRect;
    CGRect      inRect;

Setup

    // just in case -- haven't confirmed this is necessary
    ofDisableArbTex();

    width  = ofGetViewportWidth();
    height = ofGetViewportHeight();
    
    ofBackground(0);
    ofClear(0);
    glEnable(GL_POINT_SMOOTH);
    
    sourceFbo.allocate(width, height, GL_RGBA32F_ARB); //32-bit framebuffer for smoothness
    
    sourceFbo.begin();
    ofClear(0,0,0);
    sourceFbo.end();
    
    // Groundwork for Core Image
    
    genericRGB = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
    
    NSOpenGLPixelFormatAttribute attr[] = {
        NSOpenGLPFAAccelerated,
        NSOpenGLPFANoRecovery,
        NSOpenGLPFAColorSize, 32,
        0
    };
    
    pf=[[NSOpenGLPixelFormat alloc] initWithAttributes:attr];
    
    if (!pf) {
        NSLog(@"ofBDW could not create NS Open GL Pixel Format");
    }

    glCIcontext = [CIContext contextWithCGLContext: CGLGetCurrentContext()
                                       pixelFormat: CGLPixelFormatObj(pf)
                                        colorSpace: genericRGB
                                           options: nil];
    if (!glCIcontext)
    {
        NSLog(@"ofBDW could not create the CI context");
    }

    texSize = CGSizeMake(width,height);
    clampFilter = [CIFilter filterWithName:@"CIAffineClamp"] ;  // for ensuring blur goes fully to edge
    blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"] ;
    colorShiftFilter  = [CIFilter filterWithName:@"CIColorControls"] ;

    
    if (!blurFilter) {
        NSLog(@"ofBDW could not create CI Blur Filter");
    }
    if (!clampFilter) {
        NSLog(@"ofBDW could not create CI Clamp Filter");
    }
    if (!colorShiftFilter) {
        NSLog(@"ofBDW could not create CI Color Shift Filter");
    }
    
    inRect = CGRectMake(0,0,width,height);
    outRect = CGRectMake(0,0,width,height);

Update

    sourceFbo.begin();
    
    ofColor(255,255,255);
    ofDrawCircle(width/2.0, height/2.0, 40);
    
    //  do we have to re-initialise the inputCIImage each time? I am assuming yes...
    GLint   tex = sourceFbo.getTexture().texData.textureID;
    CGSize   texSize = CGSizeMake(width, height);
    
    //NSLog(@"FBO Texture ID = %d", tex);
    
    inputCIImage = [CIImage imageWithTexture:tex
                                        size:texSize
                                     flipped:NO
                                  colorSpace:genericRGB];
    
    if (!inputCIImage)
    {
        NSLog(@"ofBDW could not create CIImage from texture");
    }
    
    // Draw something
    ofColor(255,255,255);
    ofDrawCircle(width/2.0, height/2.0, 40);
    
    
    // Filter it
    float blurRadius = 20.0;
    float saturation = 1.0;
    float brightness = 1.0;
    float contrast = 1.0;

    
    CGAffineTransform xform = CGAffineTransformIdentity;
    [clampFilter setValue:[NSValue valueWithBytes:&xform objCType:@encode(CGAffineTransform)] forKey:@"inputTransform"];
    [clampFilter setValue:inputCIImage forKey:kCIInputImageKey];
    
    // blur filter
    [blurFilter setValue:clampFilter.outputImage forKey:kCIInputImageKey];
    [blurFilter setValue:[NSNumber numberWithFloat: blurRadius] forKey:@"inputRadius"];
    
    
    // color shift filter
    [colorShiftFilter setValue:[NSNumber numberWithFloat: saturation] forKey:@"inputSaturation"];
    [colorShiftFilter setValue:[NSNumber numberWithFloat: brightness] forKey:@"inputBrightness"];
    [colorShiftFilter setValue:[NSNumber numberWithFloat: contrast] forKey:@"inputContrast"];
    [colorShiftFilter setValue:inputCIImage forKey:kCIInputImageKey];
    
    ofSetColor(255,255,255,255);
    
    [glCIcontext drawImage:blurFilter.outputImage
                    inRect:outRect
                  fromRect:inRect];  // this also serves to crop the affine clamped blur image
    
    // alpha blend the color shifted copy onto the blurred copy
    
    ofSetColor(255,255,255,127); //127
    
    sourceFbo.end();

Draw

    ofSetColor(255,255,255,255);
    sourceFbo.draw(0,0);