React Drei中如何配合OrbitControls固定DirectionalLight灯光方向?
解决方案
你的问题根源在于:默认的OrbitControls是控制相机围绕物体旋转,固定在世界空间的灯光相对于相机的视角会发生变化,导致物体的受光面看起来跟着转动。要实现灯光始终沿世界Z轴正方向照射,且物体受光面始终朝向屏幕正面,可以通过让物体始终朝向相机来实现,同时保持光源在世界空间静止。
修改后的代码
import { Canvas, useFrame, useThree, useRef } from "@react-three/fiber"; import { OrbitControls } from "@react-three/drei"; import "./styles.css"; function Capsule() { const { camera } = useThree(); const meshRef = useRef(); // 在每一帧更新物体朝向,使其始终看向相机 useFrame(() => { meshRef.current.lookAt(camera.position); }); return ( <mesh ref={meshRef}> <capsuleGeometry args={[1, 1, 32]} /> <meshStandardMaterial color="red" /> </mesh> ); } export default function App() { return ( <div className="main"> <Canvas> {/* 灯光固定在世界Z轴正方向,目标指向原点 */} <directionalLight position={[0, 0, 5]} intensity={10} target={[0, 0, 0]} /> <OrbitControls enableZoom={false} enablePan={false} /> <Capsule /> </Canvas> </div> ); }
关键说明
- 固定光源位置:
directionalLight的position设为[0, 0, 5],保持在世界空间的Z轴正方向,target指向原点确保灯光朝向物体。 - 物体始终朝向相机:通过
useFrame钩子在每一帧调用lookAt(camera.position),让胶囊物体始终面向相机,这样无论你用OrbitControls怎么旋转视角,看到的物体正面都是被灯光照射的面,满足“受光面始终朝向正面”的需求。 - 分离组件逻辑:将胶囊物体封装成独立组件,让代码结构更清晰,便于维护。
如果你需要灯光始终从屏幕正面照射(相对于相机固定),可以采用另一种方案:将灯光挂载到相机节点下,使其随相机一起移动旋转:
import { Canvas, useThree } from "@react-three/fiber"; import { OrbitControls } from "@react-three/drei"; import "./styles.css"; function CameraWithLight() { const { camera } = useThree(); return ( <primitive object={camera}> <directionalLight position={[0, 0, 2]} intensity={10} target={[0, 0, 0]} /> </primitive> ); } export default function App() { return ( <div className="main"> <Canvas> <CameraWithLight /> <OrbitControls enableZoom={false} enablePan={false} /> <mesh> <capsuleGeometry args={[1, 1, 32]} /> <meshStandardMaterial color="red" /> </mesh> </Canvas> </div> ); }
这种方案下,光源会跟随相机视角变化,始终从你观看的方向照射物体,但光源并非在世界空间静止,可根据你的实际需求选择。
内容的提问来源于stack exchange,提问作者Alex Advent
相关产品推荐
相关产品推荐

