Search code examples
iosxcodeopengl-esgpuimage

Xcode iOS GPUImage - drawing triangles over live video


I am making use of Brad Larson's wonderful GPUImage library for image manipulation. Thank you Brad, great work.

I am trying to add a new filter that will allow for objects to be drawn over a live video source.

This is early stages. At this point, I am just trying to draw 3 triangles over the video source. Code follows.

It seems to be working but I get an intermittent change in aspect ratio while this effect is applied. and then it settles down. The filterView is stretched vertically. looks like a strobe.

HEADER:

//  GPUImageParticles.h
#import <GLKit/GLKit.h>
#import "GPUImageFilter.h"

@interface GPUImageParticles : GPUImageFilter{

    GLint triVertexBufferIDUniform;

    GLuint triVertexBufferID;    
}

- (void)update:(CMTime)frameTime;
- (void)setDrawColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent;



@end

IMPLEMENTATION:

//  GPUImageParticles.m
#import "GPUImageParticles.h"

// SHADERS
NSString *const kParticleGenVSString = SHADER_STRING
(
 attribute vec4 position;

 void main()
 {
     gl_Position = position;
 }
 );

NSString *const kParticleGenFSString = SHADER_STRING
(
 uniform lowp vec3 drawColor;

 void main()
 {
     gl_FragColor = vec4(drawColor, 1.0);
 }
 );

// END SHADERS

@implementation GPUImageParticles


/////////////////////////////////////////////////////////////////
// This data type is used to store information for each vertex
typedef struct {
    GPUVector3 positionCoords;
}
SceneVertex;


/////////////////////////////////////////////////////////////////
// Define vertex data for a triangle to use in example
static const SceneVertex triVertices[] =
{
    {{0.0f, 0.0f, 0.0f}},
    {{0.0f, 0.1f, 0.0f}},
    {{0.1f, 0.1f, 0.0f}},


    {{-0.3f, -0.7f, 0.0}}, // lower left corner

    {{ 0.3f, -0.7f, 0.0}}, // lower right corner

    {{ 0.01f, 0.5f, 0.0}}, // upper left corner


    {{-0.5f, -0.5f, 0.0}}, // lower left corner

    {{-0.25f, -0.25f, 0.0}}, // lower right corner

    {{-0.5f, -0.25f, 0.0}} // upper left corner

};


- (id)init;
{

    if (!(self = [super initWithVertexShaderFromString:kParticleGenVSString fragmentShaderFromString:kParticleGenFSString]))
    {
        return nil;
    }

    runSynchronouslyOnVideoProcessingQueue(^{

        triVertexBufferIDUniform =[filterProgram uniformIndex:@"triVertexBuffer"];

        drawColorUniform = [filterProgram uniformIndex:@"drawColor"];

        [self setDrawColorRed:1.0 green:0.0 blue:1.0];


        glGenBuffers(1, // STEP 1
                     &triVertexBufferID);

        glBindBuffer(GL_ARRAY_BUFFER, // STEP 2
                     triVertexBufferID);

        glBufferData( // STEP 3
                     GL_ARRAY_BUFFER, // Initialize buffer contents
                     sizeof(triVertices), // Number of bytes to copy
                     triVertices, // Address of bytes to copy
                     GL_STATIC_DRAW); // Hint: cache in GPU memory


        glBindBuffer(GL_ARRAY_BUFFER, 0);


    });


    return self;
}

- (void) dealloc;
{

}



-(void)update:(CMTime)frameTime;
{
    if (self.preventRendering)
    {
        return;
    }

    runSynchronouslyOnVideoProcessingQueue(^{

        [GPUImageContext setActiveShaderProgram:filterProgram];

        [self setFilterFBO];

        glClearColor(0.0, 0.0, 0.0, 0.0);
        glClear(GL_COLOR_BUFFER_BIT);

        glBlendEquation(GL_FUNC_ADD);
        glBlendFunc(GL_ONE, GL_ONE);
        glEnable(GL_BLEND);

        glVertexAttribPointer(filterPositionAttribute, 3, GL_FLOAT, GL_FALSE, sizeof(SceneVertex), triVertices);

        glDrawArrays(GL_TRIANGLES, 0, (unsigned int)9);

        glDisable(GL_BLEND);

        [self informTargetsAboutNewFrameAtTime:frameTime];

    });

}



- (void)setDrawColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent;
{
    GPUVector3 drawColor = {redComponent, greenComponent, blueComponent};

    [self setVec3:drawColor forUniform:drawColorUniform program:filterProgram];
}


@end

Solution

  • Reference the GPUIMAGE_NOBLECORNERDETECTION example included in the FilterShowcase example provided by Brad Larson.

            GPUImageCrosshairGenerator *crosshairGenerator = [[GPUImageCrosshairGenerator alloc] init];
            crosshairGenerator.crosshairWidth = 15.0;
            [crosshairGenerator forceProcessingAtSize:CGSizeMake(480.0, 640.0)];
    
            [(GPUImageHarrisCornerDetectionFilter *)filter setCornersDetectedBlock:^(GLfloat* cornerArray, NSUInteger cornersDetected, CMTime frameTime) {
                [crosshairGenerator renderCrosshairsFromArray:cornerArray count:cornersDetected frameTime:frameTime];
            }];
    
            GPUImageAlphaBlendFilter *blendFilter = [[GPUImageAlphaBlendFilter alloc] init];
            [blendFilter forceProcessingAtSize:CGSizeMake(480.0, 640.0)];
            GPUImageGammaFilter *gammaFilter = [[GPUImageGammaFilter alloc] init];
            [videoCamera addTarget:gammaFilter];
            [gammaFilter addTarget:blendFilter];
    
            [crosshairGenerator addTarget:blendFilter];
    
            [blendFilter addTarget:filterView];