Threejs入门(三)灯光

前言

在上一章中我们搭建了整个项目的基本结构,并且创建了一个简单的立方体模型,并且在场景中添加了 辅助线 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 中的光照

在一个黑暗的房间中打开一个灯泡,那个房间里的物体会以两种方式接收到光

  1. 直接照明: 直接来自灯泡并撞击物体的光线
  2. 间接照明: 光线在撞击到物体之前已经从墙壁和房间内其他物体的反弹,每次反弹都会改变颜色并失去强度

与之相匹配的,Threejs中的灯光类分为两种类型

  1. 直接光照: 模拟直接光照
  2. 环境光: 这是一种廉价的且可信的间接照明方式

因为真正的光线模拟成本太高,所以我们需要某种方式来伪造间接光照,其中环境光就是其中之一

直接照明

我们添加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 这一种类型的灯光,有兴趣的可以尝试一下另外三种类型的灯光,看看有什么不同;也可以改变灯光的颜色和模型的颜色,他们也会产生不一样的化学反应

如果文章中有描述不准确或错误的地方,欢迎各位大佬指正😀😀😀

相关推荐
Leyla7 分钟前
【代码重构】好的重构与坏的重构
前端
影子落人间10 分钟前
已解决npm ERR! request to https://registry.npm.taobao.org/@vant%2farea-data failed
前端·npm·node.js
世俗ˊ34 分钟前
CSS入门笔记
前端·css·笔记
子非鱼92134 分钟前
【前端】ES6:Set与Map
前端·javascript·es6
6230_39 分钟前
git使用“保姆级”教程1——简介及配置项设置
前端·git·学习·html·web3·学习方法·改行学it
想退休的搬砖人1 小时前
vue选项式写法项目案例(购物车)
前端·javascript·vue.js
加勒比海涛1 小时前
HTML 揭秘:HTML 编码快速入门
前端·html
啥子花道1 小时前
Vue3.4 中 v-model 双向数据绑定新玩法详解
前端·javascript·vue.js
麒麟而非淇淋1 小时前
AJAX 入门 day3
前端·javascript·ajax
茶茶只知道学习1 小时前
通过鼠标移动来调整两个盒子的宽度(响应式)
前端·javascript·css