How to use stencils with SCNTechnique?

1.5k views Asked by At

Basically, I would like to render an outline around a cube. To do this, I think I can use an SCNTechnique which has the following render passes:

  1. Render the cubes normally, and also write their occupied pixels to a stencil buffer.
  2. Render slightly larger cubes if they don't intersect with the stencil in the first pass.

The problem is, the documentation for stencils in SCNTechnique is very sparse, and I can't work out exactly how to use it.

I have already successfully drawn outlines by drawing the larger 'outline cubes' first with depth testing disabled and then drawing the normal cubes afterwards, and this works fairly well, however I'd like to use stencils instead due to other complications with this method.

In an attempt to get it to work using stencil buffers, my first pass's stencilStates looks like (along with why I think I need the properties):

clear = YES  // To clear the buffer from last 
enable = YES // To write to the buffer
behavior:
    writeMask = 1     // Use bit 1
    function = always // Always write to stencil regardless?

The second pass's stencilStates looks like:

clear = NO   // Keep the buffer from last step
enable = NO  // Don't write to the buffer (only read?)
behavior:
    readMask = 1      // Use bit 1
    fail     = keep   // Not sure if these...
    pass     = zero   // ...should be the other way round

There are quite a few other properties for stencil buffer behaviours, but I'm not sure which I need and how to use them. I'm also not certain if the stencil buffer needs to be listed as an input or output for each pass?

Edit 1: Here's exactly what I'm looking to implement, rendered by drawing the blue, larger outline cube first without writing to the depth buffer:

Cube with blue outline

If it wasn't for some side-effects with drawing in this manor, I'd leave the implementation like this, but instead I think the stencil approach would avoid these side effects and I think it would be useful to know how to use them anyway!

Edit 2: I've been playing around, trying to produce a similar effect using OpenGL (in C) directly. I don't pretend to fully understand how stencils work (and I basically borrowed the code from a tutorial), but these commands produce what I'm trying to achieve.

Before drawing the main cube, writing to the stencil buffer:

glStencilFunc(GL_ALWAYS, 1, 0xFF); // Set any stencil to 1
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilMask(0xFF); // Write to stencil buffer
glClear(GL_STENCIL_BUFFER_BIT); // Clear stencil buffer (0 by default)

After drawing the main cube, and before drawing the larger outline cube, testing the current stencil buffer:

glStencilFunc(GL_EQUAL, 0, 0xFF); // Pass test if stencil value is 0
glStencilMask(0x00); // Don't write anything to stencil buffer

The question, therefore, is how to achieve the above using an SCNTechnique.

1

There are 1 answers

0
Morty On

You can use SCNTechnique to draw an outline. The idea is to draw the object masks to a buffer, blur one channel of the mask, then combine it with the original rendered frame. That combination shader checks the blurred channel, and the non-blurred one and only renders the outline outside of the object.

There is an example that draws a glow around nodes here: https://github.com/laanlabs/SCNTechniqueGlow You should be able to modify it to get the effect you want.