swiftaugmented-realityscenekitarkitcifilter

SceneKit – Applied CIFilter on SCNNode hides SCNTorus


I have the following node setup on my scene: A container node with child nodes: earth, torus, and moon. I applied to the earth node's filter property the following custom HighlightFilter with CIBloom and CISourceOverCompositing filter for the glow effect:

CIFilter Class (code from awesome blog: Highlighting SCNNode with Glow)

class HighlightFilter: CIFilter {

static let filterName = "highlightFilter"

@objc dynamic var inputImage: CIImage?
@objc dynamic var inputIntensity: NSNumber?
@objc dynamic var inputRadius: NSNumber?

override var outputImage: CIImage? {
    guard let inputImage = inputImage else {
        return nil
    }

    let bloomFilter = CIFilter(name:"CIBloom")!
    bloomFilter.setValue(inputImage, forKey: kCIInputImageKey)
    bloomFilter.setValue(inputIntensity, forKey: "inputIntensity")
    bloomFilter.setValue(inputRadius, forKey: "inputRadius")

    let sourceOverCompositing = CIFilter(name:"CISourceOverCompositing")!
    sourceOverCompositing.setValue(inputImage, forKey: "inputImage")
    sourceOverCompositing.setValue(bloomFilter.outputImage, forKey: "inputBackgroundImage")

    return sourceOverCompositing.outputImage
}}

I don't understand this invisible rectangle. I assume it is because of the CIFilter SourceOverCompositing which overlays the modified image over the original. But why is the torus hidden and the moon not? I added the torus material to the moons'. material property, to see if something is wrong with the material. But still the same, moon is visible, torus is hidden. The moon rotates around with a helperNode as a child to the containerNode.

Moon is in visible, but torus not Torus is not visible behind this omninius rectangle

Scenegraph enter image description here


Solution

  • This may happen due to two potential problems.

    SOLUTION 1.

    When you're using CISourceOverCompositing you need a premultiplied RGBA image (RGB * A) for foreground, where an alpha channel has the same shape as the Earth (left picture). But you're having an alpha channel covering all the image (right picture).

    If you wanna know what's the shape of Alpha channel in your Earth image – use one of these compositing applications: The Foundry Nuke, Adobe After Effect, Apple Motion, Blackmagic Fusion, etc.

    Also, if you want to composite the Moon and the Earth separately, you have to have them as two different images.

    enter image description here

    In compositing classical OVER operation has the following formula:

    (RGB_image1 * A_image1) + (RGB_image2 * (1 – A_image1))
    

    The first part of this formula is a premultiplied foreground image (the Earth) – RGB1 * A1.

    The second part of this formula is a background image with a hole – RGB2 * inverted_A1. You've got the inversion of the alpha channel using (1-A). The background image itself could have only three components – RGB (without A).

    Then you add two images together using simple addition operation. If you have several OVER operations – the order of these ops is crucial.


    SOLUTION 2.

    It could be due to a Depth Buffer. Disable writesToDepthBuffer instance property. It is a Boolean value that determines whether SceneKit produces depth information when rendering the material.

    yourTorusNode.geometry?.materials.first?.writesToDepthBuffer = false
    

    enter image description here

    Hope this helps.