6
votes

I have a SCNScene rendering in a SCNView. I have some *.dae models that are rendered/moving in the scene.

I have a transparent cube, when one of my models goes behind it, I would like the model to not be rendered, because at the moment, as the cube is transparent, you can see it through the cube.

Is there any property/setting/shader I can apply to the transparent cube so that anything behind it is not rendered?

Example:

My eye is the green dot, the cube is the blue square, my model is the red circle, However the part of the circle hidden by the cube is purple...this would actually be invisible. The blue square would be invisible too.

Cull

This developer has an occlusion shader which does what I need, but it's Unity: https://youtu.be/MK3D91kCKzM

Kind Regards

Chris

2
What do you want to see instead? A screenshot and a sketch would help a lot.Hal Mueller
I've added an image for a better idea of what I need.Chris
Well something has to be rendered there; "invisible" isn't a color. In the part of the red/purple ball that's occluded by the transparent cube, what should be drawn? Black? White? An object behind the ball? Can you post a screenshot of what you have now, and describe how that's different from what you want?Hal Mueller
Ideally, nothing, you would only see the red sides :-/Chris
If the purple were transparent, that would be great!Chris

2 Answers

17
votes

Here's a solution

  1. For the cube, use a material with constant as its lightingModel. It's the cheapest one.
  2. This material will have writesToDepthBuffer set to true and colorBufferWriteMask set to [] (empty option set). That way the cube will write in the depth buffer, but won't draw anything on screen.
  3. Set the cube's renderingOrder to -1 so that it's drawn before any other node in the scene. This will make the cube write in the depth buffer before any other object, preventing them from being drawn if they are behind the cube.
1
votes

Based on @mnuages answer, you can use this class :

import SceneKit

class OccludingNode : SCNNode {
    convenience init(geometry: SCNGeometry) {
        geometry.materials = [OccludingMaterial()]

        self.init()
        self.geometry = geometry
        self.renderingOrder = -1
    }
}

class OccludingMaterial : SCNMaterial {
    override init() {
        super.init()
        isDoubleSided = true
        lightingModel = .constant
        writesToDepthBuffer = true
        colorBufferWriteMask = []
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Create an OccludingNode from any geometry you want and anything behind it won't be rendered.