I’m using a library called react-three-fiber
to play around with three.js
and have basically recreated this example: https://threejs.org/docs/#api/en/lights/shadows/LightShadow
It renders a sphere with shadow on a plane.
In addition, I’ve wrapped the sphere in a group and am updating the group position using the mouse scrollwheel. However, when I update the group position the sphere’s shadow moves but is only rendered in the same area that the shadow was originally rendered.
Do I need to somehow need to update the plane or light source when I move the sphere position?
import React, { useRef, useCallback } from 'react'
import ReactDOM from 'react-dom'
import { Canvas, useThree, useRender } from 'react-three-fiber'
import * as THREE from 'three'
import './styles.css'
import { observable } from 'mobx'
const Store = observable({
xPos: 0,
yPos: 0
})
const ShadowTest = () => {
const { gl } = useThree()
const group = useRef()
useRender(() => {
gl.shadowMap.type = THREE.PCFSoftShadowMap
gl.shadowMap.enabled = true
group.current.position.set(Store.xPos, Store.yPos, 0)
})
return (
<group>
<Light />
<Plane />
<group ref={group}>
<Sphere />
</group>
</group>
)
}
const Light = () => {
//Create a PointLight and turn on shadows for the light
const light = new THREE.DirectionalLight(0xffffff, 1, 100)
light.position.set(10, 10, 10)
light.castShadow = true // default false
//Set up shadow properties for the light
light.shadow.mapSize.width = 512 // default
light.shadow.mapSize.height = 512 // default
light.shadow.camera.near = 0.5 // default
light.shadow.camera.far = 500 // default
return <primitive object={light} />
}
const Sphere = () => {
//Create a sphere that cast shadows (but does not receive them)
return (
<mesh castShadow>
<ambientLight color={0x404040} intensity={2} />
<sphereBufferGeometry attach="geometry" args={[5, 32, 32]} />
<meshStandardMaterial attach="material" color={0xff0000} />
</mesh>
)
}
const Plane = () => {
//Create a plane that receives shadows (but does not cast them)
return (
<mesh receiveShadow>
<planeBufferGeometry attach="geometry" args={[200, 200, 32, 32]} />
<meshStandardMaterial attach="material" color={0xffffff} />
</mesh>
)
}
const App = () => {
const handleScroll = useCallback(e => {
Store.xPos += e.deltaX / 10
Store.yPos -= e.deltaY / 10
}, [])
return (
<Canvas camera={{ position: [0, 0, 50] }} onWheel={handleScroll}>
<ShadowTest />
</Canvas>
)
}
ReactDOM.render(<App />, document.getElementById('root'))