Transparent Layer of meshStandardMaterial Three Js React

I'm implementing a simple 3D-paint and want to implement an erasing. In order to do it I decided to use two layers of canvas: one for texture image and another one (transparent) for drawing to erase only canvas for drawing. Can you please advice how to have one meshStandardMaterial with the image texture (which shouldn't be modified while painting/erasing) and one ore more transparent meshStandardMaterial just for painting Here is the component code:

<Canvas
        onCreated={({ gl }) => {
          gl.physicallyCorrectLights = true;
        }}
        camera={{ position: [0, 0, 10] }}
      >
        {isControlsAllowed && <Controls />}
        <mesh
          onPointerLeave={handleDrawStop}
          onPointerDown={() => {
              setIsControlsAllowed(false);
          }}
          onPointerUp={() => {
            setIsControlsAllowed(true);
          }}
          onPointerMove={(ev) => {
            handleBrushPointerMove(ev, previousPoint.current);
          }}
          geometry={geometry}
        >
          <meshStandardMaterial
            attach="material"
            metalness={0}
            roughness={1}
          >
            <canvasTexture
              ref={currentTextureRef}
              attach="map"
              image={currentCanvasRef.current}
            />
          </meshStandardMaterial>
          <meshStandardMaterial attach="material" metalness={0} roughness={1}>
            <canvasTexture
              ref={currentDrawingTextureRef}
              attach="map"
              image={currentDrawingCanvasRef.current}
            />
          </meshStandardMaterial>
        </mesh>
        <ambientLight intensity={1} />
        <spotLight position={[0, 0, 10]} intensity={10} />
        <spotLight position={[-10, 0, -5]} intensity={10} />
        <spotLight position={[10, 0, -5]} intensity={10} />
      </Canvas>

My hook code:

const currentCanvasRef = useRef(document.createElement("canvas"));
  const currentTextureRef = useRef<CanvasTexture>(null);

  const currentDrawingCanvasRef = useRef(document.createElement("canvas"));
  const currentDrawingTextureRef = useRef<CanvasTexture>(null);

  useLayoutEffect(() => { 
    const context = currentDrawingCanvasRef.current.getContext("2d");
    context?.clearRect(
      0,
      0,
      currentDrawingCanvasRef.current.width,
      currentDrawingCanvasRef.current.height
    );
    createCanvasTextureFromImage("/Stool.jpg");
  }, []);

  const createCanvasTextureFromImage = (
    imageUrl: string,
  ) => {
    const canvas = currentCanvasRef.current;

    new ImageLoader().load(imageUrl, (image) => {
      const ctx = canvas.getContext("2d");
      canvas.width = image.width;
      canvas.height = image.height;
      if (ctx) {
        ctx.clearRect(0.0, 0.0, canvas.width, canvas.height);
        ctx.drawImage(image, 0.0, 0.0, image.width, image.height);
      }
    });
  };

const handleBrushPointerMove = (
    currentPoint: ThreeEvent<PointerEvent>,
    prevPoint?: ThreeEvent<PointerEvent>
  ) => {
    // Some drawing logic
  };

What I'm expecting to see:

And what I'm actually see:

UPDATE: I just checked that array of materials doesn't work for mesh. Although each of the materials works separately, when using an array, the 3D model is not displayed at all

1 Answer

To Answer Your Comment :

  1. Increase the Offset: Increase the distance between the two meshes to prevent overlap. Adjust the mesh position:
position={[0, 0, 0.005]}
  1. Depth Write/Read: Modify depth settings of the materials:
depthWrite={false}
depthTest={false}
  1. Polygon Offset: Use Three.js's polygon offset to artificially push the mesh backward in z-depth:
polygonOffset={true}
polygonOffsetFactor={1}
polygonOffsetUnits={1}
  1. Use a Shader: Manipulate the depth in shaders to ensure correct rendering order. Requires knowledge of GLSL.

  2. Rethink Layering: Consider painting directly onto the image canvas, eliminating the need for a second mesh.

Start with the simplest solution (increasing the offset) and progress to more complex solutions as needed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Sarah Jenkins

Sarah Jenkins

Senior Technology Editor & AI Specialist

Sarah Jenkins is a veteran tech journalist with over 12 years of experience covering artificial intelligence, mobile innovations, and digital ethics. Her insights have appeared in leading technology publications worldwide.

Share this article
Twitter Facebook Pinterest