1

With three and @react-three I have a component with sprite as follow:

export function Point({ position = [0, 0, 0] }: { position?: [number, number, number] }) {
  const spriteRef = useRef<THREE.Sprite>(null)
  const [hovered, setHovered] = useState(false)

  useCursor(hovered)

  useFrame(({ camera, clock }) => {
    spriteRef.current?.lookAt(camera.position);

    const scale = 0.1 + (1 + Math.sin(clock.getElapsedTime() * 5)) * 0.01;
    spriteRef.current!.scale.set(scale, scale, scale)
  })

  const onClick = () => alert('You clicked me!')

  return (
    <sprite ref={spriteRef} onClick={onClick} onPointerOver={() => setHovered(true)} onPointerOut={() => setHovered(false)} position={position}>
      <spriteMaterial attach="material" color={'hotpink'} />
    </sprite>
  )
}

Now here everything works perfectly, but the sprite is just pink square. I would like to add to it some shader to make it more attractive. So I changed it to:

export function Point({ position = [0, 0, 0] }: { position?: [number, number, number] }) {
  const spriteRef = useRef<THREE.Sprite>(null)
  const [hovered, setHovered] = useState(false)

  useCursor(hovered)

  useFrame(({ camera, clock }) => {
    spriteRef.current?.lookAt(camera.position);

    const scale = 0.1 + (1 + Math.sin(clock.getElapsedTime() * 5)) * 0.01;
    spriteRef.current!.scale.set(scale, scale, scale)
  })

  const onClick = () => alert('You clicked me!')

  return (
    <sprite ref={spriteRef} onClick={onClick} onPointerOver={() => setHovered(true)} onPointerOut={() => setHovered(false)} position={position}>
      {/* <spriteMaterial attach="material" color={'hotpink'} /> */}
      <shaderMaterial 
        attach="material"
        transparent={true}
        depthWrite={false}
        uniforms={{
          color: { value: new THREE.Color("hotpink") },
        }}
        vertexShader={`
          varying vec2 vUv;
          void main() {
            vUv = uv;
            vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);
            gl_Position = projectionMatrix * mvPosition;
            gl_PointSize = 300.0 / -mvPosition.z;
          }
        `}
        fragmentShader={`
          uniform vec3 color;
          varying vec2 vUv;
          void main() {
            float dist = length(vUv - vec2(0.5)); 
            float alpha = 1.0 - smoothstep(0.3, 0.5, dist);
            gl_FragColor = vec4(color, alpha);
          }
        `}
      />
    </sprite>
  )
}

But at this point ononClick, onPointerOver and onPointerOut do not work anymore. Would any one be able to advice me what should I change to have it working not only with sprite material but also with shader material?

1
  • I don't know if you are not willing to use drie, but I was always using their helper (the one called shaderMaterial) and that worked just fine for me in the past. I haven't tested it, but that may be an option! Commented Nov 2, 2024 at 10:10

0

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.