Three.js - 模型无法接收任何阴影
Three.js - Model cannot receive any shadow
我目前是新手,正在学习 three.js。我正在使用 react-three-fiber
来实现 React,但我偶然发现了一个问题。但是,该模型无法从另一个模型接收任何阴影。我也尝试将 obj.castShadow = true
和 obj.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
处于最大强度,将所有东西都洗成白色。甚至阴影区域也会被吹成白色。看这里,我已经禁用了你所有的 PointLight
s 并且只保留了聚光灯和环境光所以你可以再次看到阴影:
我建议您使用尽可能少的灯光,以减少渲染占用的资源。添加如此多的灯可能会降低帧率、笔记本电脑过热并耗尽手机的电池电量。对于非常逼真的照明设置,我喜欢使用带有定向光的单个半球光 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.
我目前是新手,正在学习 three.js。我正在使用 react-three-fiber
来实现 React,但我偶然发现了一个问题。但是,该模型无法从另一个模型接收任何阴影。我也尝试将 obj.castShadow = true
和 obj.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
处于最大强度,将所有东西都洗成白色。甚至阴影区域也会被吹成白色。看这里,我已经禁用了你所有的 PointLight
s 并且只保留了聚光灯和环境光所以你可以再次看到阴影:
我建议您使用尽可能少的灯光,以减少渲染占用的资源。添加如此多的灯可能会降低帧率、笔记本电脑过热并耗尽手机的电池电量。对于非常逼真的照明设置,我喜欢使用带有定向光的单个半球光 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.