3D数字孪生 – Three.js 场景光源(二)

前言

20230619194852_rec_.gif

接下来的项目实战讲解过程中,有必要多花几个篇幅介绍一下项目中用到的两个库。

"@react-three/drei": "^9.70.3",
"@react-three/fiber": "^8.13.0"

此篇仅对入门不久或者新手小白,如果对 threejs 有一定的了解,完全可以跳过,直接看对应的文档。

文档链接: react-three/fiber, react-three/drei

请记住这两个版本号,因为在实战的过程中,不同的版本,api 也会有所不同,具体可以查看对应的版本。

值得一提的是,新手在看文档案例的时候,很容易对文档中的案例代码误解,比如案例的代码给的是这样:

image.png

实际上,它的代码是这样用的,具体可以到它的github上进行查看。

image.png

若有小伙伴找到官网案例的代码入口,可以在评论区留言~

光源

OK,言归正传,下面,我们介绍常见的几种光源,与本项目中使用到的光源,为了更好的理解,本篇会将工厂类部分效果打开。

20230619200956_rec_.gif

基础光源

在three.js中,光源是用于照亮场景中的对象的关键组件之一。它们模拟了现实世界中的光源,包括太阳光、点光源、聚光灯和方向光等。下面是three.js中几种常见的光源类型及其用法:

  1. AmbientLight(环境光): AmbientLight是一种均匀分布的光源,它不会产生阴影,而是向场景中的所有对象提供一个均匀的亮度。创建AmbientLight的代码如下所示:
const ambientLight = new THREE.AmbientLight(0xffffff, intensity);
scene.add(ambientLight);

  1. DirectionalLight(方向光): DirectionalLight模拟了来自一个远处的平行光源,例如太阳。它发射的光线是平行的,并且具有方向性,可以产生阴影效果。创建DirectionalLight的代码如下所示:
const directionalLight = new THREE.DirectionalLight(0xffffff, intensity);
directionalLight.position.set(x, y, z);
scene.add(directionalLight);


  1. PointLight(点光源): PointLight模拟了一个点状的光源,可以从一个点向所有方向发射光线。它可以产生逼真的光照和阴影效果。创建PointLight的代码如下所示:
const pointLight = new THREE.PointLight(0xffffff, intensity, distance, decay);
pointLight.position.set(x, y, z);
scene.add(pointLight);
  1. SpotLight(聚光灯): SpotLight模拟了一个具有方向性的聚光灯光源,类似于手电筒的效果。它可以发射锥形的光束,可以产生聚焦的光照和阴影效果。创建SpotLight的代码如下所示:
const spotLight = new THREE.SpotLight(0xffffff, intensity, distance, angle, penumbra, decay);
spotLight.position.set(x, y, z);
spotLight.target.position.set(targetX, targetY, targetZ);
scene.add(spotLight);

在上述代码中

intensity表示光源的强度

distance表示光源的最大照射距离

decay表示光照强度的衰减系数

angle表示聚光灯的锥形角度

penumbra表示聚光灯的柔化程度

position表示光源在场景中的位置

target.position表示聚光灯的照射目标的位置。

以上四种灯光,只有AmbientLight是无法产生投影,其他三种,均可以产生投影。

介绍完基础的光源后,我们来看,项目中,光源都是如何生效的吧。

实战光

首先,我们先看看项目实际的光源效果。

20230619203139_rec_.gif

这里一共用到了三种光,查看BaseScene=>components=>Lights.tsx文件(项目结构,可以查看上篇# 3D数字孪生 – Three.js 项目介绍与基础环境搭建(一)

// 初始化场景灯光
import React, { useRef } from 'react';
import { SpotLight, SpotLightProps } from '@react-three/drei';


function MovingSpot(props: SpotLightProps) {
  const light = useRef();
  return (
    <SpotLight
      ref={light}
      castShadow
      penumbra={2}
      distance={6000}
      angle={Math.PI * 0.6}
      attenuation={5}
      anglePower={Math.PI / 2}
      intensity={6}
      shadow-mapSize={[1024, 1024]}
      shadow-camera-near={200}
      shadow-camera-far={2000}
      {...props}
    />
  );
}

const Lights = () => {
  return (
    <>
      {/* 环境光,AmbientLight,影响整个场景的光源 */}
      <ambientLight intensity={0.5} />
      {/* 模拟远处类似太阳的光源 */}
      <directionalLight color={0xffffff} intensity={3} position={[10, 10, 0]} />
      <MovingSpot color="#fff" position={[3, 2000, 2]} />
    </>
  );
};

export { MovingSpot };
export default Lights;

是否会好奇,为什么光源在上面介绍基础光源的时候,需要手动初始化,而在这里,我们却可以像原生组件一样写就行而无需声明呢? 我们看react-three/fiber文档中的解释:

image.png
也就是说,在驼峰命名的版本中,我们只需要像写原生的html元素一样,写threejs的组件,这个很重要,因为在接下来的实战项目中,到处都是这种写法。

接下来,我们关闭环境光,看看效果:

20230619204453_rec_.gif

可以看到,物体有两个面,已经没有了光源,只剩下一个太阳光,与聚光灯。

接下来,我们再将太阳光关闭。

20230619204742_rec_.gif
整个场景的亮度变暗,因为只剩下我们的聚光灯啦。

那么,如果我将我们的聚光灯关闭,是否会以为,整个场景失去了所有光源,就全暗了呢?

20230619205037_rec_.gif

结局是不是会让你意外,为什么不是整个场景都无光了呢?

答案我们将在下一期揭晓~

image.png

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYsEDrZW' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片