0

Similar to the simpleVideoFilter and face detection, I would like to highlight a portion of my GPUImage2 video feed with colored rectangles. The SolidColorGenerator seems like a good start with two exceptions. First, I am unsure how to transpose the SolidColorGenerator output to the right place on my original image. Second, I am unsure how to add N rectangles to my original image. In the mean time I have had success with the LineGenerator but I think a rectangle would look better.

Bonus: Rectangles with rounded corners and a single pixel border.

enter image description here

Joe Andolina
  • 648
  • 1
  • 11
  • 23

1 Answers1

0

What worked for me was writing a RectangleGenerator. The key to the new RectangleGenerator was to draw GL_TRIANGLES.

glDrawArrays(GLenum(GL_TRIANGLES), 0, GLsizei(positions.count) * 2)

One optimization that could be made would be to use GL_Elements and GL_TRIANGLE_STRIP, though I was not able to figure that out.

enter image description here

The full solution should support border, borderWidth and cornerRadius. For now simple rectangles will suffice. Full code below.

let vertex = "attribute vec4 position; void main(){ gl_Position = position; }"

let fragment = "uniform lowp vec3 fillColor; void main(){ gl_FragColor = vec4(fillColor, 1.0); }"

public class RectangleGenerator: ImageGenerator {

let rectangleShader:ShaderProgram
var uniformSettings = ShaderUniformSettings()

public var fillColor:Color = Color.green { didSet { uniformSettings["fillColor"] = fillColor } }

public override init(size:Size) {
    rectangleShader = crashOnShaderCompileFailure("RectangleGenerator"){try sharedImageProcessingContext.programForVertexShader(vertex, fragmentShader:fragment)}
    super.init(size:size)

    ({fillColor = Color.green})()
}

public func renderRectangles(_ positions:[Position]) {
    guard positions.count > 3 else { return }

    imageFramebuffer.activateFramebufferForRendering()

    rectangleShader.use()
    uniformSettings.restoreShaderSettings(rectangleShader)
    clearFramebufferWithColor(Color.transparent)

    guard let positionAttribute = rectangleShader.attributeIndex("position") else { fatalError("A position attribute was missing from the shader program during rendering.") }

    let convertedPositions = positions.flatMap{$0.toGLArray()}
    glVertexAttribPointer(positionAttribute, 2, GLenum(GL_FLOAT), 0, 0, convertedPositions)

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

    glDrawArrays(GLenum(GL_TRIANGLES), 0, GLsizei(positions.count) * 2)
    glDisable(GLenum(GL_BLEND))

    notifyTargets()
}
}

Happy Coding

Joe Andolina
  • 648
  • 1
  • 11
  • 23