You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Three Fiber中SpotLight失效、HemisphereLight效果异常求助

问题描述

跟着JavaScript Mastery的YouTube视频做3D作品集网站,用下面的代码时遇到两个问题:

  1. HemisphereLight和PointLight能正常工作,但SpotLight完全照不到computer.scene模型
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 16:25:33