Sunday, 17 September 2023

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=
      >
        {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:

enter image description here

And what I'm actually see:

enter image description here

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



from Transparent layer of meshStandardMaterial three js React

No comments:

Post a Comment