Search code examples
three.jsreact-three-fiber

@react-three/fiber: How do I create a helper for a shadow camera?


So I am used to setting helpers like this:

useHelper(sLightRef, THREE.SpotLightHelper);

return (
    <spotLight
        castShadow
        ref={sLightRef}
        position={[0, 2, 2]}
        args={["#fff", 0.4, 10, Math.PI * 0.3]}
    >
    </spotLight>
)

Which will create a helper on the SpotLight object.

What I don't understand is how to create one on the SpotLight's shadow camera. (spotlight.shadow.camera) We can't assign a ref() to it, since it's not in my return statement. It's created inside of SpotLight component.

In normal Three.js, this is easy:

const helper = new THREE.CameraHelper(spotlight.shadow.camera);
scene.add(helper);

How would I go about doing this in react-three-fiber? Is there something obvious i'm missing? Thank you.


Solution

  • I played around with it a bit but I couldn't find a clean solution. That's why I made my own hook that's built similarly to the useHelper hook.

    // Components==============
    import { useFrame, useThree } from '@react-three/fiber';
    import React, { useRef } from 'react';
    import { CameraHelper, Light } from 'three';
    // =========================
    
    export default function useShadowHelper(
        ref: React.MutableRefObject<Light | undefined>
    ) {
        const helper = useRef < CameraHelper > ();
        const scene = useThree((state) => state.scene);
    
        React.useEffect(() => {
            if (!ref.current) return;
    
            helper.current = new CameraHelper(ref.current?.shadow.camera);
            if (helper.current) {
                scene.add(helper.current);
            }
    
            return () => {
                if (helper.current) {
                    scene.remove(helper.current);
                }
            };
        }, [helper.current?.uuid, ref.current]);
    
        useFrame(() => {
            if (helper.current?.update) {
                helper.current.update();
            }
        });
    }