1

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

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

1

这是我的沙箱:
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;

任何帮助,将不胜感激。
非常感谢。

4

1 回答 1

2

您的模型确实收到了阴影。问题是你有几个PointLight全强度的 s 正在把所有东西都洗成白色。甚至阴影区域也被吹成白色。看到这里,我已经禁用了你所有的PointLights,只保留了聚光灯和环境光,这样你就可以再次看到阴影:

在此处输入图像描述

我建议您使用尽可能少的灯光以减少渲染资源密集型。添加如此多的灯可能会降低帧速率,使笔记本电脑过热,并消耗更多手机电池。对于一个非常逼真的照明设置,我喜欢在这个演示中使用带有定向光的单个半球灯。半球让人感觉好像有来自顶部的大气光,以及来自底部的反射地面光。

就像素化阴影而言,您使用的是大型 2048x2048 贴图,但它分布在太大的区域中。我看到您正在尝试设置left, right, top, bottom距离,但这些距离仅适用于使用正交相机的DirectionalLight 。Left、right、top 和 bottom 属性不适用于使用透视相机的 SpotLight。如果要使 Spotlight 阴影贴图更窄,请使用.angle属性

于 2020-11-14T01:56:24.420 回答