React Three Fiber中SpotLight失效、HemisphereLight效果异常求助
问题描述
跟着JavaScript Mastery的YouTube视频做3D作品集网站,用下面的代码时遇到两个问题:
- HemisphereLight和PointLight能正常工作,但SpotLight完全照不到
computer.scene模型 - HemisphereLight的效果和视频里的差很多
import React from "react"; import { Suspense, useState, useEffect } from "react"; import { Canvas } from "@react-three/fiber"; import { OrbitControls, Preload, useGLTF } from "@react-three/drei"; import CanvasLoader from "../Loader"; const Computers = () => { const computer = useGLTF("./desktop_pc/scene.gltf"); return ( <mesh> <hemisphereLight intensity={1} position={[0, 1, 0]} groundColor="black" /> <spotLight angle={0.12} penumbra={1} intensity={1} castShadow shadow-mapSize={1024} /> <pointLight intensity={1} /> <primitive object={computer.scene} scale={0.75} position={[0, -3.25, -1.5]} rotation={[-0.01, -0.2, -0.1]} /> </mesh> ); }; const ComputersCanvas = () => { return ( <Canvas frameloop="demand" shadows camera={{ position: [20, 3, 5], fov: 25 }} gl={{ preserveDrawingBuffer: true }} > <Suspense fallback={<CanvasLoader />}> <OrbitControls enableZoom={false} maxPolarAngle={Math.PI / 2} minPolarAngle={Math.PI / 2} /> <Computers /> </Suspense> <Preload all /> </Canvas> ); }; export default ComputersCanvas;
解决方案
一、搞定SpotLight不亮的问题
- 灯光位置没对准:SpotLight默认在
[0,0,0],你的模型在[0, -3.25, -1.5],光线默认朝下,根本照不到模型。得把灯光移到模型斜上方,再设置目标点对准模型位置。 - 模型没开阴影:你开了Canvas的
shadows,但模型的mesh默认没开启castShadow和receiveShadow,需要遍历模型子元素手动开启。 - 灯光参数太保守:
angle=0.12光线范围太窄,intensity=1亮度不够,适当调大这两个值。
二、优化HemisphereLight效果
- 位置和强度不够:当前灯光在
[0,1,0],离模型太近,强度1也不够。把位置调高到[0,5,0],强度加到1.5,groundColor别用纯黑,换成深灰色#222,环境光效果会更接近视频。 - 别把灯光放mesh里:
<mesh>是装几何体的容器,灯光放里面会限制作用范围,直接作为独立元素放在场景里就行。
修改后的代码
import React from "react"; import { Suspense, useEffect } from "react"; import { Canvas } from "@react-three/fiber"; import { OrbitControls, Preload, useGLTF } from "@react-three/drei"; import CanvasLoader from "../Loader"; const Computers = () => { const computer = useGLTF("./desktop_pc/scene.gltf"); // 遍历模型所有mesh,开启阴影投射和接收 useEffect(() => { computer.scene.traverse((child) => { if (child.isMesh) { child.castShadow = true; child.receiveShadow = true; } }); }, [computer.scene]); return ( <> {/* 灯光移出mesh容器,直接作用于场景 */} <hemisphereLight intensity={1.5} position={[0, 5, 0]} groundColor="#222" /> <spotLight angle={0.3} penumbra={0.5} intensity={2} castShadow shadow-mapSize={2048} position={[0, 4, 2]} // 移到模型斜上方 target-position={[0, -3, -1.5]} // 对准模型位置 /> <pointLight intensity={1.2} position={[2, 0, 0]} /> <primitive object={computer.scene} scale={0.75} position={[0, -3.25, -1.5]} rotation={[-0.01, -0.2, -0.1]} /> </> ); }; const ComputersCanvas = () => { return ( <Canvas frameloop="demand" shadows camera={{ position: [20, 3, 5], fov: 25 }} gl={{ preserveDrawingBuffer: true }} > <Suspense fallback={<CanvasLoader />}> <OrbitControls enableZoom={false} maxPolarAngle={Math.PI / 2} minPolarAngle={Math.PI / 2} /> <Computers /> </Suspense> <Preload all /> </Canvas> ); }; export default ComputersCanvas;
关键修改点说明
- 把灯光从
<mesh>里拿出来,确保灯光能覆盖整个场景 - 调整SpotLight的位置和目标点,扩大光照范围、提高亮度
- 用
traverse遍历模型,给所有mesh开启阴影投射和接收,让阴影效果生效 - 提升HemisphereLight的高度和强度,调整地面色,增强环境光氛围
- 微调PointLight的位置和强度,补充场景照明
内容的提问来源于stack exchange,提问作者G raj Kumar
相关产品推荐
相关产品推荐

