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.