Clipping plane stencil capping

Hi
After upgrading from v160 to v170 the capping of the clipping planes no longer works for me.

Specifically: I’ve created a capping plane (with PlaneGeometry). And the stencils no longer seem to be working - the plane is visible everywhere (not only where the stencils would allow). Some code details:

  1. I create a cross section material (to cap the clipped surfaces) like this:
const crossSectionMat = new THREE.MeshBasicMaterial({
        color: hex,
        stencilWrite: true,
        stencilRef: 0,
        stencilFunc: THREE.NotEqualStencilFunc,
        stencilFail: THREE.ReplaceStencilOp,
        stencilZFail: THREE.ReplaceStencilOp,
        stencilZPass: THREE.ReplaceStencilOp,
    });
  1. I’ve set the cross section ‘onAfterRender’ function like this:
crossSection.onAfterRender = function (renderer) {
        renderer.clearStencil();
    };
  1. I’ve created two stencils (front and back) with the following materials:
const stencilBack = () => {
    const clippingPlane = CrossSection.getClippingPlane();
    const stencilBackMat = new THREE.MeshBasicMaterial();
    stencilBackMat.side = THREE.BackSide;

    stencilBackMat.depthWrite = false;
    stencilBackMat.depthTest = false;
    stencilBackMat.colorWrite = false;
    stencilBackMat.stencilWrite = true;
    stencilBackMat.stencilFunc = THREE.AlwaysStencilFunc;

    stencilBackMat.clippingPlanes = [clippingPlane];
    stencilBackMat.stencilFail = THREE.IncrementWrapStencilOp;
    stencilBackMat.stencilZFail = THREE.IncrementWrapStencilOp;
    stencilBackMat.stencilZPass = THREE.IncrementWrapStencilOp;

    return stencilBackMat;
};

const stencilFront = () => {
    const clippingPlane = CrossSection.getClippingPlane();
    const stencilFrontMat = new THREE.MeshBasicMaterial();
    stencilFrontMat.side = THREE.FrontSide;

    stencilFrontMat.depthWrite = false;
    stencilFrontMat.depthTest = false;
    stencilFrontMat.colorWrite = false;
    stencilFrontMat.stencilWrite = true;
    stencilFrontMat.stencilFunc = THREE.AlwaysStencilFunc;

    stencilFrontMat.clippingPlanes = [clippingPlane];
    stencilFrontMat.stencilFail = THREE.DecrementWrapStencilOp;
    stencilFrontMat.stencilZFail = THREE.DecrementWrapStencilOp;
    stencilFrontMat.stencilZPass = THREE.DecrementWrapStencilOp;

    return stencilFrontMat;
};
  1. I’ve created the stencils based off an objects geometry like this:
const createStencil = (obj) => {
    if (!obj.geometry) return;
    const geometry = obj.geometry;
    const stencil = new THREE.Group();
    stencil.name = "stencilGroup";

    // back faces
    const mat0 = Material.stencilBack();
    const mesh0 = new THREE.Mesh(geometry, mat0);
    mesh0.name = "stencilMesh0";
    stencil.add(mesh0);

    // front faces
    const mat1 = Material.stencilFront();
    const mesh1 = new THREE.Mesh(geometry, mat1);
    mesh1.name = "stencilMesh1";
    stencil.add(mesh1);

    obj.add(stencil);
};
  1. When a button is clicked to apply the stencils I do the following:
renderer.stencil = true;
renderer.localClippingEnabled = true;
crossSection.visible = true;

I’ve gone over this example a number of times and can’t work out what’s different: three.js examples

Any help - hugely appreciated!!

From r163 stencil context attribute of WebGLRenderer is now false by default for performance reasons…

You need to enable the stencil buffer.

const renderer = new THREE.WebGLRenderer({
   // antialias: true,
    stencil: true
});

More HERE

3 Likes

That did it! many thanks. I had done it this way: renderer.stencil = true; which didn’t work

1 Like

Yeah, I think all those params need to be provided at construction time.

Can anyone speak to the performance impact of stencil? If it was removed for performance, it would be nice to know how heavy it is. Is it a framerate slowdown? A memory thing?

It has not been removed for performance, just disabled by default. I can’t speak to the performance of it. It’s possibly 8 bits per pixel that wont be used. Most applications dont do stencil testing, so im not sure what savings are to be gained there. Ie. if it was never turned on, and no testing ever happened, nothing is to be gained.