接上文# 3D数字孪生 – Three.js 场景光源(二)最后的问题:
“为何已关闭场景中所有光源,仍然有些面是亮的呢?”
我们不妨近距离的观察一下,打开场景中的方向光 DirectionalLight
,发光的 线
,面
const Lights = () => {
return (
<>
{/* 首先添加个环境光,AmbientLight,影响整个场景的光源 */}
{/* <ambientLight intensity={0.5} /> */}
{/* 模拟远处类似太阳的光源 */}
<directionalLight color={0xffffff} intensity={3} position={[10, 10, 0]} />
{/* <MovingSpot color="#fff" position={[3, 2000, 2]} /> */}
</>
);
};
不难发现,在绿色的巷道上,是有类似油漆的镜面投影效果的,而黄色面却没有,所以,顺藤摸瓜很自然就可以想到,它们的材质(Material)有问题!
OK,定位到问题,我们看下绘制巷道的组件tunnel.tsx组件的代码:
代码位置: 查看BaseScene=>components=>tunnel.tsx文件(项目结构,可以查看上篇# 3D数字孪生 – Three.js 项目介绍与基础环境搭建(一))
import React from 'react';
import { Vector3 } from 'three';
import { MeshReflectorMaterial, Html } from '@react-three/drei';
export interface ITunnelProps {
x: number;
y: number;
width: number;
height: number;
tunnelNumber: string;
}
const Tunnel: React.FC<ITunnelProps> = ({ x, y, width, height, tunnelNumber }) => {
// 巷道的位置
const innerPosition = new Vector3(x + width / 2, 1.1, y + height / 2);
const outerPosition = new Vector3(x + width / 2, 1, y + height / 2);
const textPosition = new Vector3(x + width / 2, 1.2, y + height / 2);
return (
<group>
<mesh position={innerPosition} rotation={[-Math.PI / 2, 0, 0]}>
<planeGeometry args={[width, height]}></planeGeometry>
<MeshReflectorMaterial
blur={[400, 100]}
resolution={1024}
mixBlur={1}
mixStrength={5}
depthScale={1}
minDepthThreshold={1}
color="rgb(0, 73, 45)"
metalness={0.85}
roughness={0.95}
mirror={0}
></MeshReflectorMaterial>
</mesh>
<mesh position={outerPosition} rotation={[-Math.PI / 2, 0, 0]}>
<planeGeometry
args={[width > 0 ? width + 20 : width - 20, height > 0 ? height + 20 : height - 20]}
></planeGeometry>
<meshBasicMaterial color="rgb(221, 165, 15)"></meshBasicMaterial>
</mesh>
<Html scale={100} rotation={[-Math.PI / 2, 0, 0]} position={textPosition} transform occlude>
{tunnelNumber}
</Html>
</group>
);
};
export default Tunnel;
Group
中的代码分三块,第一个网格(mesh)是绿色的镜面。
将其中另外两块组件注释:
<group>
<mesh position={innerPosition} rotation={[-Math.PI / 2, 0, 0]}>
<planeGeometry args={[width, height]}></planeGeometry>
<MeshReflectorMaterial
blur={[400, 100]}
resolution={1024}
mixBlur={1}
mixStrength={5}
depthScale={1}
minDepthThreshold={1}
color="rgb(0, 73, 45)"
metalness={0.85}
roughness={0.95}
mirror={0}
></MeshReflectorMaterial>
</mesh>
{/* <mesh position={outerPosition} rotation={[-Math.PI / 2, 0, 0]}>
<planeGeometry
args={[width > 0 ? width + 20 : width - 20, height > 0 ? height + 20 : height - 20]}
></planeGeometry>
<meshBasicMaterial color="rgb(221, 165, 15)"></meshBasicMaterial>
</mesh>
<Html scale={100} rotation={[-Math.PI / 2, 0, 0]} position={textPosition} transform occlude>
{tunnelNumber}
</Html> */}
</group>
可以看到,绿色的网格,我们使用的是MeshReflectorMaterial
材质,我们接下来,切换一下地下黄色面的网格。
<group>
{/* <mesh position={innerPosition} rotation={[-Math.PI / 2, 0, 0]}>
<planeGeometry args={[width, height]}></planeGeometry>
<MeshReflectorMaterial
blur={[400, 100]}
resolution={1024}
mixBlur={1}
mixStrength={5}
depthScale={1}
minDepthThreshold={1}
color="rgb(0, 73, 45)"
metalness={0.85}
roughness={0.95}
mirror={0}
></MeshReflectorMaterial>
</mesh> */}
<mesh position={outerPosition} rotation={[-Math.PI / 2, 0, 0]}>
<planeGeometry
args={[width > 0 ? width + 20 : width - 20, height > 0 ? height + 20 : height - 20]}
></planeGeometry>
<meshBasicMaterial color="rgb(221, 165, 15)"></meshBasicMaterial>
</mesh>
<Html scale={100} rotation={[-Math.PI / 2, 0, 0]} position={textPosition} transform occlude>
{tunnelNumber}
</Html>
</group>
可以看到黄色网格面,我们使用的是meshBasicMaterial
。
那么,MeshReflectorMaterial
与meshBasicMaterial
又有什么区别,它们对于我们的问题,又有什么关联呢?
MeshReflectorMaterial和MeshBasicMaterial是Three.js中的两种材质类型,它们在渲染和功能上有一些区别。
-
反射:
MeshBasicMaterial
没有反射属性,只能显示基本的材质颜色。 -
环境贴图:
MeshReflectorMaterial
可以使用环境贴图来模拟物体周围的环境光照效果,使其看起来更加真实。MeshBasicMaterial
不支持环境贴图,只能显示固定的颜色。 -
高光反射:
MeshReflectorMaterial
可以通过镜面反射属性显示高光反射,使物体表面出现明亮的高光效果。MeshBasicMaterial
不支持高光反射。 -
性能:由于
MeshReflectorMaterial
具有反射和高光反射等更复杂的属性,它可能会比MeshBasicMaterial
更加耗费性能。如果你只需要简单的材质显示,MeshBasicMaterial可能是更好的选择。
总的来说,MeshReflectorMaterial
适用于需要模拟反射和高光效果的场景,而MeshBasicMaterial
适用于简单的、没有复杂需求的材质显示场景。选择使用哪种材质取决于你的需求和对性能的考虑。
所以,MeshReflectorMaterial
受环境光的影响,而MeshBasicMaterial
只是显示自身固定的颜色,这就能解释,为什么场景灯都关闭,还能看到网格线和面的原因啦~
在 three/drei
中,关于着色器(shaders)还有很多玩法,以下是几种常用的材质:
MeshReflectorMaterial
:MeshReflectorMaterial
是一种用于创建反射效果的材质。它可以应用于Mesh
对象,使其表面反射周围环境的内容。
-
MeshWobbleMaterial
:MeshWobbleMaterial
是一种用于创建弹跳或扭曲效果的材质。它可以应用于Mesh
对象,使其以一种有趣的方式呈现动画效果。 -
MeshDistortMaterial
:MeshDistortMaterial
是一种用于创建扭曲效果的材质。它可以应用于Mesh
对象,使其以一种扭曲的方式呈现。 -
MeshRefractionMaterial
:MeshRefractionMaterial
是一种用于创建折射效果的材质。它可以应用于Mesh
对象,使其通过物体的表面产生折射效果。 -
MeshTransmissionMaterial
:MeshTransmissionMaterial
是一种用于创建透明传输效果的材质。它可以应用于Mesh
对象,使其表现出透明度和光线传输的效果。 -
MeshDiscardMaterial
:MeshDiscardMaterial
是一种用于创建丢弃(discard)效果的材质。它可以应用于Mesh
对象,根据给定的条件来丢弃或保留片段。 -
PointMaterial
:PointMaterial
是一种用于创建点精灵(point sprites)的材质。它可以应用于Points
对象,使其以一种精灵化的方式呈现。 -
SoftShadows
:SoftShadows
是一种用于创建柔和阴影效果的组件。它可以应用于场景中的光源,通过模糊处理来实现更柔和和更真实的阴影效果。
-
shaderMaterial
:shaderMaterial
是一种自定义着色器材质,它允许您通过编写自定义着色器代码来创建完全定制的材质效果。
具体材质不同的玩法可以直接在这查看: Shaders demo案例
好啦,想必对于小白还有新手对材质都有一定的了解了吧o( ̄︶ ̄)o,下一章,我们继续讲解,场景中的相机以及相机控制器,分享如何在场景中行走与飞行,以及制作固定巡航大片!