How to load GLB model with fade-in effect?

Viewed 22

Is there any way to load GLB with an opacity (0 to 1) fade-in effect??
I use useGLTF for loading.

My code:

const Cell = () => {
  const {nodes, materials} = useGLTF(`${process.env.PUBLIC_URL}/cell.glb`);

  return (
    <group scale={1}>
      <mesh
        name="Sphere001"
        geometry={nodes.Sphere001.geometry}
        material={materials.red}
        morphTargetDictionary={nodes.Sphere001.morphTargetDictionary}
        morphTargetInfluences={nodes.Sphere001.morphTargetInfluences}
      />
      <mesh
        name="Sphere001_1"
        geometry={nodes.Sphere001_1.geometry}
        material={materials['GLB GLASS']}
        morphTargetDictionary={nodes.Sphere001_1.morphTargetDictionary}
        morphTargetInfluences={nodes.Sphere001_1.morphTargetInfluences}
      />
    </group>
  );
};
2 Answers

Ok, I started to use the @react-spring/three package, but the fade-in performs with glitches and the performance wants to be better.

import {animated, useSpring} from '@react-spring/three';

const Cell = () => {
  const {nodes, materials} = useGLTF(`${process.env.PUBLIC_URL}/cell.glb`);

  const {opacity: materialOpacity} = useSpring({
    from: {
      opacity: 0
    },
    to: {
      opacity: 1
    }
  });

  return (
    <group scale={1}>
      <animated.mesh
        name="Sphere001"
        geometry={nodes.Sphere001.geometry}
        material={materials.red}
        material-transparent
        material-opacity={materialOpacity}
        morphTargetDictionary={nodes.Sphere001.morphTargetDictionary}
        morphTargetInfluences={nodes.Sphere001.morphTargetInfluences}
      />
      <animated.mesh
        name="Sphere001_1"
        geometry={nodes.Sphere001_1.geometry}
        material={materials['GLB GLASS']}
        material-transparent
        material-opacity={materialOpacity.to({range: [0, 1], output: [0, 0.2]})}
        morphTargetDictionary={nodes.Sphere001_1.morphTargetDictionary}
        morphTargetInfluences={nodes.Sphere001_1.morphTargetInfluences}
      />
    </group>
  );
};

It looks much better with the useFrame.

import {useGLTF} from '@react-three/drei';
import {useMemo, useRef} from 'react';
import {useFrame} from '@react-three/fiber';

const Cell = () => {
  const {nodes, materials} = useGLTF(`${process.env.PUBLIC_URL}/cell.glb`);

  useMemo(() => {
    materials.red.transparent = true;
    materials.red.opacity = 0;
    materials['GLB GLASS'].opacity = 0;
  }, [materials]);

  useFrame(() => {
    if (materials.red.opacity !== 1) {
      materials.red.opacity += 0.001;
    }

    if (materials['GLB GLASS'].opacity < 0.15) {
      materials['GLB GLASS'].opacity += 0.001;
    }
  });

  return (
    <group scale={1}>
      <mesh
        name="Sphere001"
        geometry={nodes.Sphere001.geometry}
        material={materials.red}
        morphTargetDictionary={nodes.Sphere001.morphTargetDictionary}
        morphTargetInfluences={nodes.Sphere001.morphTargetInfluences}
      />
      <mesh
        name="Sphere001_1"
        geometry={nodes.Sphere001_1.geometry}
        material={materials['GLB GLASS']}
        morphTargetDictionary={nodes.Sphere001_1.morphTargetDictionary}
        morphTargetInfluences={nodes.Sphere001_1.morphTargetInfluences}
      />
    </group>
  );
};
Related