#import "GPUImageLineGenerator.h" NSString *const kGPUImageLineGeneratorVertexShaderString = SHADER_STRING ( attribute vec4 position; void main() { gl_Position = position; } ); #if TARGET_IPHONE_SIMULATOR || TARGET_OS_IPHONE NSString *const kGPUImageLineGeneratorFragmentShaderString = SHADER_STRING ( uniform lowp vec3 lineColor; void main() { gl_FragColor = vec4(lineColor, 1.0); } ); #else NSString *const kGPUImageLineGeneratorFragmentShaderString = SHADER_STRING ( uniform vec3 lineColor; void main() { gl_FragColor = vec4(lineColor, 1.0); } ); #endif @interface GPUImageLineGenerator() - (void)generateLineCoordinates; @end @implementation GPUImageLineGenerator @synthesize lineWidth = _lineWidth; #pragma mark - #pragma mark Initialization and teardown - (id)init; { if (!(self = [super initWithVertexShaderFromString:kGPUImageLineGeneratorVertexShaderString fragmentShaderFromString:kGPUImageLineGeneratorFragmentShaderString])) { return nil; } runSynchronouslyOnVideoProcessingQueue(^{ lineWidthUniform = [filterProgram uniformIndex:@"lineWidth"]; lineColorUniform = [filterProgram uniformIndex:@"lineColor"]; self.lineWidth = 1.0; [self setLineColorRed:0.0 green:1.0 blue:0.0]; }); return self; } - (void)dealloc { if (lineCoordinates) { free(lineCoordinates); } } #pragma mark - #pragma mark Rendering - (void)generateLineCoordinates; { lineCoordinates = calloc(1024 * 4, sizeof(GLfloat)); } - (void)renderLinesFromArray:(GLfloat *)lineSlopeAndIntercepts count:(NSUInteger)numberOfLines frameTime:(CMTime)frameTime; { if (self.preventRendering) { return; } if (lineCoordinates == NULL) { [self generateLineCoordinates]; } // Iterate through and generate vertices from the slopes and intercepts NSUInteger currentVertexIndex = 0; NSUInteger currentLineIndex = 0; NSUInteger maxLineIndex = numberOfLines *2; while(currentLineIndex < maxLineIndex) { GLfloat slope = lineSlopeAndIntercepts[currentLineIndex++]; GLfloat intercept = lineSlopeAndIntercepts[currentLineIndex++]; if (slope > 9000.0) // Vertical line { lineCoordinates[currentVertexIndex++] = intercept; lineCoordinates[currentVertexIndex++] = -1.0; lineCoordinates[currentVertexIndex++] = intercept; lineCoordinates[currentVertexIndex++] = 1.0; } else { lineCoordinates[currentVertexIndex++] = -1.0; lineCoordinates[currentVertexIndex++] = slope * -1.0 + intercept; lineCoordinates[currentVertexIndex++] = 1.0; lineCoordinates[currentVertexIndex++] = slope * 1.0 + intercept; } } runSynchronouslyOnVideoProcessingQueue(^{ [GPUImageContext setActiveShaderProgram:filterProgram]; outputFramebuffer = [[GPUImageContext sharedFramebufferCache] fetchFramebufferForSize:[self sizeOfFBO] textureOptions:self.outputTextureOptions onlyTexture:NO]; [outputFramebuffer activateFramebuffer]; 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, 2, GL_FLOAT, 0, 0, lineCoordinates); glDrawArrays(GL_LINES, 0, ((unsigned int)numberOfLines * 2)); glDisable(GL_BLEND); [self informTargetsAboutNewFrameAtTime:frameTime]; }); } - (void)renderToTextureWithVertices:(const GLfloat *)vertices textureCoordinates:(const GLfloat *)textureCoordinates; { // Prevent rendering of the frame by normal means } #pragma mark - #pragma mark Accessors - (void)setLineWidth:(CGFloat)newValue; { _lineWidth = newValue; [GPUImageContext setActiveShaderProgram:filterProgram]; glLineWidth(newValue); } - (void)setLineColorRed:(GLfloat)redComponent green:(GLfloat)greenComponent blue:(GLfloat)blueComponent; { GPUVector3 lineColor = {redComponent, greenComponent, blueComponent}; [self setVec3:lineColor forUniform:lineColorUniform program:filterProgram]; } @end