Reflection Issue with DoubleSide in Transmission Material

Dear Three.js community,

I am encountering an issue where a transmission material reflects its own geometry when side: THREE.DoubleSide is used. Here’s the relevant part of my material configuration:

roughnessMap: environmentTexture,
roughness: .1,
transmission: 1,
ior: 1.33,
thickness: 2.5,
side: THREE.DoubleSide,

This setup causes the object to reflect itself, which is not the desired effect.

I’ve consulted GPT, and it suggested using a technique called “Dual Depth Peeling”. I’ve also looked at the rendering part of the meshTransmissionMaterial example in drei-vanilla, which seems to render the front and back faces separately before combining them (though I don’t fully understand the specifics).

Could anyone please advise on a better way to prevent a transmission material from self-reflecting when using DoubleSide, either by improving upon the meshTransmissionMaterial approach or suggesting an alternative technique?


  // runs on every frame
  animateLoop((time: number) => {
    meshTransmissionMaterial.time = time * 0.001

    for (const mesh of transmissionMeshes) {
      if (meshTransmissionMaterial.buffer === fboMain.texture) {
        // Save defaults
        oldTone = state.gl.toneMapping
        oldBg = state.scene.background
        oldSide = mesh.material.side

        // Switch off tonemapping lest it double tone maps
        // Save the current background and set the HDR as the new BG
        // Use discardMaterial, the parent will be invisible, but it's shadows will still be cast
        state.gl.toneMapping = THREE.NoToneMapping
        mesh.material = discardMaterial

        if (mtmParams.backside) {
          // Render into the backside buffer
          state.gl.setRenderTarget(fboBack)
          state.gl.render(state.scene, state.camera)
          // And now prepare the material for the main render using the backside buffer
          mesh.material = meshTransmissionMaterial
          mesh.material.buffer = fboBack.texture
          mesh.material.thickness = mtmParams.backsideThickness
          mesh.material.side = THREE.BackSide
        }

        // Render into the main buffer
        state.gl.setRenderTarget(fboMain)
        state.gl.render(state.scene, state.camera)

        mesh.material = meshTransmissionMaterial
        mesh.material.thickness = mtmParams.thickness
        mesh.material.side = oldSide
        mesh.material.buffer = fboMain.texture

        // Set old state back
        state.scene.background = oldBg
        state.gl.setRenderTarget(null)
        state.gl.toneMapping = oldTone
      }
    }
  })