Why is polygonOffset not working in this case?

Viewed 21

I have some text rendering over a background quad. Let's call this a 'label'. Both are positioned at the same point which causes z-fighting.

I'd like to promote the text to avoid z-fighting using polygon offset.

This is how I add the polygon offset to the text material:

const material = new THREE.RawShaderMaterial(
  CreateMSDFShader({
    map: this.glyphs,
    opacity: opt.opacity ?? 1,
    alphaTest: (opt.opacity ?? 1) < 1 ? 0.001 : 1,
    color: opt.colour ?? '#ffffff',
    transparent: opt.transparent ?? true,
    glslVersion: opt.renderMode === 'webgl' ? THREE.GLSL1 : THREE.GLSL3,
    side: opt.side ?? THREE.DoubleSide,
    depthFunc: opt.depthFunc ?? THREE.LessEqualDepth,

    depthTest: true,
    depthWrite: false,
    polygonOffset: true,
    polygonOffsetUnits: -1.0,
    polygonOffsetFactor: -4.0,
  })
);
const mesh = new THREE.Mesh(geom, material);

and this is the background material:

  if (tableOptions.background) {
  const geometry = new THREE.PlaneGeometry(1, 1, 1, 1);
  const backgroundMaterial = new ActivatableMaterial(
    {
      color: new THREE.Color(tableOptions.backgroundColour),
      toneMapped: false,
      opacity: 1,
      alphaTest: 0.001,
      transparent: true,
    },

    {
      activationColour: new THREE.Color(tableOptions.activationColour),
    }
  );

  this.background = buildUIObject(
    Actions.ExpandLabel as Action,
    geometry,
    backgroundMaterial
  );
  setName(this.background, 'Background');
  this.tableGroup.add(this.background);
}

The polygon offset just isn't working (using Chrome). The text disappears behind the background quad as I orbit the camera around, and reappears at random. The labels are always facing the camera (using lookAt).

What could stop the polygon offset from working?

The labels are rendering to a renderpass with a render taget set up as follows:

const pars = {
  minFilter: THREE.LinearFilter,
  magFilter: THREE.LinearFilter,
  format: THREE.RGBAFormat,
  stencilBuffer: false,
  depthBuffer: false,
};

this.renderTargetBuffer = new THREE.WebGLRenderTarget(
  resolution.x,
  resolution.y,
  pars
);
this.renderTargetBuffer.texture.name = 'RenderTargetBuffer';
this.renderTargetBuffer.texture.generateMipmaps = false;

I'm assuming that because the polygonOffset is a state thing it doesn't matter that this is a RawShaderMaterial. Is that a safe assumption?

Edit: I have added the opposite polygonOffset to the background mesh separately and again it doesn't work.

1 Answers

Polygon offset wasn't the best solution in this case. I switched to maintaining a custom order for the labels based on distance to the camera. That way I could force the text render order to be greater than the background.

Related