Search code examples
iosopengl-esquartz-2dmetal

How can I composite Quartz and OpenGL / Metal drawing efficiently?


I have a game that will require some high level drawing constructs like complex bezier curves and fills (varying with each frame) that I'd like to composite / overlay with some more primitive stuff drawn in OpenGL or Metal. Is there an efficient (high performance) way to do this?

  1. Can I simply have a quartz drawing layer over the OpenGL layer or will this suffer a huge performance hit?
  2. Should I capture my Quartz drawing to a bitmap and push it into OpenGL as a texture? Or would doing this on every frame be prohibitively slow?
  3. Can I go the other way and capture my OpenGL rendering into a bitmap that I draw with Quartz?

Solution

  • I was able to overlay a quartz view on top of an opengl view without (seemingly) too great of a performance hit. I was not actually able to figure out how to do this in Interface Builder but it was easy enough in code by simply creating a "master" view controller and procedurally adding the two views as sub-views something like this:

    let glkViewController = GLKViewController()
    self.view.addSubview( glkViewController!.view )
    
    let overlayView = OverlayView()
    overlayView.opaque = false
    overlayView.frame = self.view.frame
    let overlayViewController = OverlayViewController()
    overlayViewController.view = overlayView
    self.view.addSubview(overlayView)
    overlayViewController.viewDidLoad()
    

    Note that the glk view has its own refresh loop and the above assumes that you set up a CADisplayLink or other run loop for your quartz view controller in the viewDidLoad(). It is not necessary to call / refresh between the two. The glk view seems to refresh on the default NSRunLoop.currentRunLoop() so if you use that they will compete for time and it seems that the opengl loop wins if things get strained. You can easily create a separate loop or background thread for your overlay to separate them.