Search code examples
sprite-kitios9cifilter

CIFilter GaussianBlur seems to be broken on iOS9.x (used with SKEffectNode)


I am trying to create a blur effect using the following snippet:

  let glowEffectNode = SKEffectNode()
  glowEffectNode.shouldRasterize = true

  let glowSize = CGSize(width: barSize.width, height: barSize.height)
  let glowEffectSprite = SKSpriteNode(color: barColorData.topColor, size: glowSize)
  glowEffectNode.addChild(glowEffectSprite)

  let glowFilter = CIFilter(name: "CIGaussianBlur")
  glowFilter!.setDefaults()
  glowFilter!.setValue(5, forKey: "inputRadius")

  glowEffectNode.filter = glowFilter

Of course on iOS 8.x it works perfectly but from iOS 9.x (tried it both both on 9.0 and 9.1) the blur is not working properly. (On the simulator the node seems to be a bit transparent but definitely not blurred and on the device it seems blurred but cropped and also has an offset from its center position:/)

Is there a quick way to fix this using CIFilter ?


Solution

  • I fiddled a bit more with this and found a solution...

    First of all, it seems that using odd numbers for the blur radius causes the entire node to be rendered with an offset (???) so using 10 for example fixed the offset issue.

    Secondly, it seems that the blur is cropped since the entire node is the rendered sprite and for a blur effect you need an extra space so I use a transparent sprite for the extra space and the following code snippet now works:

    let glowEffectNode = SKEffectNode()
    glowEffectNode.shouldRasterize = true
    
    let glowBackgroundSize = CGSize(width: barSize.width + 60, height: barSize.height + 60)
    let glowSize = CGSize(width: barSize.width + 10, height: barSize.height + 10)
    let glowEffectSprite = SKSpriteNode(color: barColorData.topColor, size: glowSize)
    glowEffectNode.addChild(SKSpriteNode(color: SKColor.clearColor(), size: glowBackgroundSize))
    glowEffectNode.addChild(glowEffectSprite)
    
    let glowFilter = CIFilter(name: "CIGaussianBlur")
    glowFilter!.setDefaults()
    glowFilter!.setValue(10, forKey: "inputRadius")
    
    glowEffectNode.filter = glowFilter
    

    I should have mentioned that I am creating a texture from this node using view.textureFromNode(glowEffectNode) for efficiency purposes but I tried using the node itself and the problem was still there so the above should work regardless