Three.js - 模型无法接收任何阴影

Three.js - Model cannot receive any shadow

我目前是新手,正在学习 three.js。我正在使用 react-three-fiber 来实现 React,但我偶然发现了一个问题。但是,该模型无法从另一个模型接收任何阴影。我也尝试将 obj.castShadow = trueobj.receiveShadow = true 用于父项和子项上的接收阴影模型对象之一,但没有显示任何区别。有没有办法给另一个模型投下阴影?

还有影子..看起来很粗糙。有什么办法可以平滑吗?

这是我的沙箱:
https://codesandbox.io/s/modest-newton-np1sw

代码:

import React, { Suspense, useMemo, useState } from "react";
import { Canvas } from "react-three-fiber";
import { OBJLoader } from "three/examples/jsm/loaders/OBJLoader";
import { OrbitControls} from "drei";
import { Mesh } from "three";

import billboard from "../assets/models/billboard.obj";
import bridge from "../assets/models/bridge.obj";

const Model = ({ modelPath }) => {
  const [obj, setObj] = useState();
  useMemo(() => new OBJLoader().load(modelPath, setObj), [modelPath]);
  if (obj) {
    obj.castShadow = true;
    obj.traverse((children) => {
      if (children instanceof Mesh) {
        children.castShadow = true;
      }
    });
  }
  return obj ? <primitive object={obj} /> : null;
};

const ShadowedModel = ({ modelPath }) => {
  const [obj, setObj] = useState();
  useMemo(() => new OBJLoader().load(modelPath, setObj), [modelPath]);
  if (obj) {
    obj.castShadow = true;
    obj.receiveShadow = true;
    obj.traverse((children) => {
      if (children instanceof Mesh) {
        children.castShadow = true;
        children.receiveShadow = true;
      }
    });
  }
  return obj ? <primitive object={obj} /> : null;
};

const Lights = () => {
  return (
    <>
      <ambientLight intensity={0.1} />
      <spotLight
        castShadow
        position={[-50, 50, 20]}
        intensity={0.5}
        shadow-mapSize-shadowMapWidth={2048}
        shadow-mapSize-shadowMapHeight={2048}
        shadow-camera-left={-50}
        shadow-camera-right={50}
        shadow-camera-top={-50}
        shadow-camera-bottom={50}
      />
      <pointLight position={[10, -10, -20]} intensity={0.3} />
      <pointLight position={[0, 10, 5]} intensity={0.3} />
      <spotLight intensity={1} position={[0, 1000, 0]} />
    </>
  );
};

const Billboard = () => {
  return (
    <mesh
      castShadow
      position={[-15, 5, -35]}
      scale={[0.05, 0.05, 0.05]}
      rotation={[0, 20, 0]}
    >
      <Model modelPath={billboard} />
    </mesh>
  );
};

const Bridge = () => {
  return (
    <mesh
      castShadow
      receiveShadow
      position={[10, -40, -80]}
      // position={[-80, -40, -150]}
      scale={[0.15, 0.15, 0.15]}
      rotation={[0, 10.2, 0]}
    >
      <ShadowedModel modelPath={bridge} />
    </mesh>
  );
};

const Shadow = () => {
  return (
    <group>
      <mesh
        receiveShadow
        rotation={[-Math.PI / 2, 0, 0]}
        position={[-20, -32, -40]}
      >
        <planeBufferGeometry attach="geometry" args={[500, 500]} />
        <meshLambertMaterial attach="material" color={"lightblue"} />
      </mesh>
    </group>
  );
};

const MegatronModel = () => {
  return (
    <>
      <Canvas
        shadowMap
        colorManagement
        camera={{ position: [0, 0, 5], fov: 60 }}
      >
        <OrbitControls
          enablePan={Boolean("Pan", true)}
          enableZoom={Boolean("Zoom", true)}
          enableRotate={Boolean("Rotate", true)}
        />
        <Shadow />
        <Suspense fallback={null}>
          <Bridge />
        </Suspense>
        <Billboard />
        <Lights />
      </Canvas>
    </>
  );
};

export default MegatronModel;

如有任何帮助,我们将不胜感激。
非常感谢。

您的模型确实有阴影。问题是你有几个 PointLight 处于最大强度,将所有东西都洗成白色。甚至阴影区域也会被吹成白色。看这里,我已经禁用了你所有的 PointLights 并且只保留了聚光灯和环境光所以你可以再次看到阴影:

我建议您使用尽可能少的灯光,以减少渲染占用的资源。添加如此多的灯可能会降低帧率、笔记本电脑过热并耗尽手机的电池电量。对于非常逼真的照明设置,我喜欢使用带有定向光的单个半球光 like in this demo。半球给人的感觉是大气光从上面射进来,地面光从下面反射过来。

就像素化阴影而言,您使用的是 2048x2048 大地图,但它分布在太大的区域中。我看到您正在尝试设置 left, right, top, bottom 距离,但这些距离仅适用于 DirectionalLight, which uses an orthographic camera. Left, right, top, & bottom properties don't apply to SpotLight, which uses a perspective camera. If you want to make the Spotlight shadowmap narrower, use the .angle property.