前言
在上一章中我们搭建了整个项目的基本结构,并且创建了一个简单的立方体模型,并且在场景中添加了 辅助线 AxesHelper
,帮助我们更快的定位到自己当前所处的空间坐标,还添加了 轨道控制器 OrbitControls
来帮助我们更直观的观察三维图形,由于OrbitControls
是作为一个附加工具而存在的,不是Threejs
核心库的一部分,所以它的引入方式和别的API
有些不同
这一章中我们要介绍一下 灯光 的使用,在场景中,如果没有灯光,我们所看到的物体是完全黑色的,前面的我们之所在没有灯光的情况下也可以看到立方体,是因为我们使用的材料MeshBasicMaterial
不是基于物理的,不需要灯光也可以看到
下面我们会使用MeshStandardMaterial
来创建模型,因为MeshStandardMaterial
创建的模型是基于物理的,这就需要我们给场景布置上 灯光 才可以看到
启用物理上正确的光照
物理上正确的照明意味着使用真实世界的物理方程进行计算,但是这些方程的计算极其复杂,我们在开发中只需启用渲染器的 .physicallyCorrectLights
就可以打开物理上正确的照明
js
// src/World/systems/renderer.js
const createRenderer = () => {
const renderer = new WebGLRenderer()
renderer.physicallyCorrectLights = true
return renderer
}
export {createRenderer}
创建物理大小的场景
有人会好奇之前们 创建模型、设置相机位置和相机的远近截面 时为什么只输入了数字,却没有单位,这是因为他们的默认单位是 米
,这是一种约定,而不是规则,如果你不遵守它,那么除了物理上精确的照明之外的一切仍然有效,所以我们尽量是遵守这个约定
注: 1单位 = 1米
Threejs 中的光照
在一个黑暗的房间中打开一个灯泡,那个房间里的物体会以两种方式接收到光
- 直接照明: 直接来自灯泡并撞击物体的光线
- 间接照明: 光线在撞击到物体之前已经从墙壁和房间内其他物体的反弹,每次反弹都会改变颜色并失去强度
与之相匹配的,Threejs
中的灯光类分为两种类型
- 直接光照: 模拟直接光照
- 环境光: 这是一种廉价的且可信的间接照明方式
因为真正的光线模拟成本太高,所以我们需要某种方式来伪造间接光照
,其中环境光
就是其中之一
直接照明
我们添加DirectionalLight
,它模拟来自太阳或者另一个非常明亮的遥远光源的光
threejs
核心中总共有四种直接光源可以使用,每一种都模拟一个常见的现实世界光源
DirectionalLight
=> 阳光PointLight
=> 灯泡RectAreaLight
=> 条形照明或明亮的窗户SpotLight
=> 聚光灯
有光照到物体上,物体必然会产生阴影,因为阴影的处理很昂贵,书中没有具体的介绍,我也不是很了解,后面学习之后在具体讲一下
阳光 DirectionalLight
DirectionalLight
设计的目的是模仿遥远的光源,例如太阳;DirectionalLight
的光线不会随着距离而消失,场景中的所有对象都将被同样地照亮,无论他们放在哪里
DirectionalLight
的光线是平行的,从一个位置照向一个目标
所有threejs
灯都有颜色和强度设置,继承自Light
基类。
创建光照
js
// src/World/components/lights.js
import { DirectionalLight } from 'three'
const createLights() {
// 设置光的颜色和强度
const light = new DirectionalLight('white', 8)
// 设置光的位置
light.position.set(10, 10, 10)
return light
}
export { createLights }
在World.js
中引入
js
// src/World.js
import { createLights } from "./World/components/lights"
...
class World {
...
constructor(container) {
...
cosnt lights = createLights()
this.#scene.add(cube, lights)
...
}
...
}
export { World }
虽然我们将灯光添加到了场景
之中,但是目前还不会有任何效果,因为我们创建的模型时用的材质
还是MeshBasicMaterial
,接下来我们要将材质切换为MeshStandardMaterial
标准材质 MeshStandardMaterial
MeshStandardMaterial
是一种 高质量、通用、物理精确 的材料,可以使用真实世界的物理方程对光做出反应,几乎是所有情况下首选 标准材料 , 后面可以添加精心制作的纹理
,几乎可以重建任何常见的表面
所有的
threejs
材料,都继承自Material
基类
切换立方体材质
js
// src/World/components/cube.js
import { BoxGeometry, Mesh, MeshStandardMaterial } from 'three'
const createCube = () => {
const geometry = new BoxGeometry(2,2,2)
const material = new MeshStandardMaterial({color: 'purple'}) // 紫色
const cube = new Mesh(geometry, material)
return cube
}
export {createCube}
最终得到的效果如下图,我们可以清楚的看到立方体的棱角,以及没有被光照到的黑色
部分。现在我们的模型是一个完完整整的立方体,但是这种立方体现实中肯定是不存在的,后面我们还会往这个立方体上添加不同的纹理
,使他更接近真实
总结
这一章的代码内容不是很多,基本都是在讲灯光的原理,以及不同类型的灯光,这里我们只是使用了 DirectionalLight
这一种类型的灯光,有兴趣的可以尝试一下另外三种类型的灯光,看看有什么不同;也可以改变灯光的颜色和模型的颜色,他们也会产生不一样的化学反应
如果文章中有描述不准确或错误的地方,欢迎各位大佬指正😀😀😀