BradLarson / GPUImage2

GPUImage 2 is a BSD-licensed Swift framework for GPU-accelerated video and image processing.
BSD 3-Clause "New" or "Revised" License
4.87k stars 609 forks source link

rendering image to gl texture using PictureInput returns an empty texture #228

Open cuhte3 opened 6 years ago

cuhte3 commented 6 years ago

I'm trying to modify Crosshair generator to replace default crosshairs with gl texture made of UIImage, my image is 128x128 png file.

Using PictureInput for converting UIImage to gl texture and it returns the instance of PictureInput without any issues/warnings.

Next I'm modifying CrosshairFragmentShader to add support of the new texture:

uniform sampler2D inputImageTexture;
varying lowp vec3 crosshairColor;
varying highp vec2 centerLocation;
varying highp float pointSpacing;

void main() {
    highp vec4 tex = texture2D(inputImageTexture, centerLocation);
    gl_FragColor = vec4(tex.r, tex.g, tex.b, tex.a);
}

Here is the code of modified CrosshairGenerator:

import UIKit

public class CrosshairGenerator: ImageGenerator {

public var crosshairWidth:Float = 5.0 { didSet {    uniformSettings["crosshairWidth"] = crosshairWidth } }
public var crosshairColor:Color = Color.green { didSet { uniformSettings["crosshairColor"] = crosshairColor } }
public var crosshairImage: PictureInput = PictureInput(imageName:"monohrome.png") {
    didSet {
        uniformSettings["inputImageTexture"] = crosshairImage //Here I pass the texture to shader?
        crosshairImage.processImage()
   }
}

 let crosshairShader:ShaderProgram
 var uniformSettings = ShaderUniformSettings()

public override init(size:Size) {        
    crosshairShader = crashOnShaderCompileFailure("CrosshairGenerator"){try    sharedImageProcessingContext.programForVertexShader(vertexShader, fragmentShader: fragmentShader)}

   super.init(size:size)

   ({crosshairWidth = 5.0})()
   ({crosshairColor = Color.green})()
   ({crosshairImage = PictureInput(imageName:"monohrome.png")})()
}

public func renderCrosshairs(_ positions:[Position]) {
    imageFramebuffer.activateFramebufferForRendering()
    imageFramebuffer.timingStyle = .stillImage 
    #if GL
    glEnable(GLenum(GL_POINT_SPRITE))
    glEnable(GLenum(GL_VERTEX_PROGRAM_POINT_SIZE))
    #else
   glEnable(GLenum(GL_POINT_SPRITE_OES))
   #endif

     crosshairShader.use()
     uniformSettings.restoreShaderSettings(crosshairShader)

     clearFramebufferWithColor(Color.transparent)

     guard let positionAttribute = crosshairShader.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)

   glDrawArrays(GLenum(GL_POINTS), 0, GLsizei(positions.count))

   notifyTargets()
 }

}

the initialization of corner detector remains the same:

  FilterOperation(
      filter:{HarrisCornerDetector()},
      listName:"Harris corner detector",
      titleName:"Harris Corner Detector",
      sliderConfiguration:.enabled(minimumValue:0.01, maximumValue:0.70, initialValue:0.20),
      sliderUpdateCallback: {(filter, sliderValue) in
       filter.threshold = sliderValue
   }
      filterOperationType:.custom(filterSetupFunction:{(camera, filter, outputView) in
       let castFilter = filter as! HarrisCornerDetector
       // TODO: Get this more dynamically sized
    #if os(iOS)
       let crosshairGenerator = CrosshairGenerator(size:Size(width:480, height:640))
    #else
       let crosshairGenerator = CrosshairGenerator(size:Size(width:1280, height:720))
    #endif
       crosshairGenerator.crosshairWidth = 30.0

       castFilter.cornersDetectedCallback = { corners in
           crosshairGenerator.renderCrosshairs(corners)
       }

       camera --> castFilter

       let blendFilter = AlphaBlend()
       camera --> blendFilter --> outputView
       crosshairGenerator --> blendFilter
       return blendFilter
   })
  )

The code compiles and works fine, but the texture looks empty (coloured squares) when rendered on screen, see the screenshot - https://i.stack.imgur.com/NMoyO.jpg

if I comment out this line - uniformSettings["inputImageTexture"] = crosshairImage - the result remains the same which makes me think the texture isn't passed to shader at all.

What I'm missing here? Mighty @BradLarson could you gave me an idea what I'm doing wrong here, thanks in advance.