【Three.js入门】灯光与阴影、平行光阴影属性、聚光灯的属性和应用

简介: 【Three.js入门】灯光与阴影、平行光阴影属性、聚光灯的属性和应用

https://www.bilibili.com/video/BV1hD4y1h7pi?t=1.4

【使用 Three.js 实现的效果】


一、灯光与阴影的关系与设置

灯光阴影:


材质要满足能够对光照有反应

设置渲染器开启阴影计算 renderer.shadowMap.enabled = true

设置光照投射阴影 directionalLight.castShadow = true

设置物体投射阴影 sphere.castShadow = true

设置物体接收阴影 plane.receiveShadow = true

下面的解释与上面的灯光阴影相对应:


.shadowMap 它包含阴影贴图的引用


.castShadow 如果设置为 true 该平行光会产生动态阴影


.castShadow 对象是否被渲染到阴影贴图中


.receiveShadow 材质是否接收阴影


我们先创建一个球体和一个平面,为球体阴影到平面上做准备。之后以上的四步也是缺一不可的(渲染器阴影计算,光照投射阴影,球体投射阴影,平面接收阴影)

// 创建一个球
const sphereGeometry = new THREE.SphereBufferGeometry(1, 20, 20)
// 设置材质
const material = new THREE.MeshStandardMaterial()
// 结合实体和材质
const sphere = new THREE.Mesh(sphereGeometry, material)
// 打开球体的投射阴影
sphere.castShadow = true
// 添加到场景中
scene.add(sphere)
// 创建平面
const planeGeometry = new THREE.PlaneBufferGeometry(10, 10)
const plane = new THREE.Mesh(planeGeometry, material)
plane.position.set(0, -1, 0)
// 正面旋转 90°,调整平面的位置
plane.rotation.x = -Math.PI / 2
// 开启平面接收阴影
plane.receiveShadow = true
scene.add(plane)
// 环境光:均匀的照亮场景中的所有物体
const light = new THREE.AmbientLight(0xffffff, 0.9)
scene.add(light)
// 平行光:方向从一个平行光位置 position 到 target 位置
const directionLight = new THREE.DirectionalLight(0xffffff, 0.95)
// 设置光的位置
directionLight.position.set(10, 10, 10)
// 开启光照投射阴影
directionLight.castShadow = true
scene.add(directionLight)
// 初始化渲染器
const renderer = new THREE.WebGLRenderer()
// 设置渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight)
// 开启场景中的阴影贴图
renderer.shadowMap.enabled = true
// 将 webgl 渲染的 canvas 内容添加到 body
document.body.appendChild(renderer.domElement)
......

de2ff999d6a14af0ac644663f43875b7.png

二、平行光阴影属性

1、设置阴影模糊度

.radius 将此值设置为大于 1 的值将模糊阴影的边缘。较高的值会在阴影中产生不必要的条带效果

// 设置阴影贴图模糊度
directionLight.shadow.radius = 20

583c4331a8454bec9f41fa2d49532abb.png

2、阴影贴图

.mapSize 一个 Vector2 定义阴影贴图的宽度和高度。较高的值会以计算时间为代价提供更好地阴影质量。但值必须是 2 的幂,默认值是(512, 512)

// 设置阴影贴图的分辨率
directionLight.shadow.mapSize.set(2048, 2048)

657e370353dc46d39986fce632cdf748.png

3、平行光投射相机的属性

近端,远端,上下左右。当我们改变近端的值时,阴影的大小会相应的发生改变

// 设置平行光投射相机的属性
directionLight.shadow.camera.near = 18.2
directionLight.shadow.camera.far = 500
directionLight.shadow.camera.top = 5
directionLight.shadow.camera.bottom = -5
directionLight.shadow.camera.left = -5
directionLight.shadow.camera.right = 5

33293990f9254782a39f363da4c33037.png

三、聚光灯的属性和应用

聚光灯(SpotLight):光线从一个点沿一个方向射出,随着光线照射的变远,光线圆锥体的尺寸也逐渐增大。

相关属性:

color 十六进制光照颜色,缺省值 0xffffff(白色)

intensity (可选参数)光照强度,缺省值 1

distance 从光源发出光的最大距离,其强度根据光源的距离线性衰减

angle 光线散射角度,最大值为 Math.PI/2

penumbra 聚光锥的半影衰减百分比。在0和1之间的值。默认为 0

decay 沿着光照距离的衰减量

使用聚光灯,改变 target 的位置,通过 GUI 来查看不同距离的显示效果

......
// 聚光灯
const spotLight = new THREE.SpotLight(0xffffff, 0.5)
// 设置光的位置
spotLight.position.set(5, 5, 5)
// 设置阴影贴图模糊度
spotLight.shadow.radius = 20
// 设置阴影贴图的分辨率
spotLight.shadow.mapSize.set(4096, 4096)
// 设置目标
spotLight.target = sphere
// 设置光照投射阴影
spotLight.castShadow = true
scene.add(spotLight)
// 使用 GUI,改变球体在 x 轴的位置,查看投影效果
gui
    .add(spotLight.position, 'x')
    .min(-5)
    .max(5)
    .step(0.1)

de815f3bc69b4b9bb24aaab49fae1b6a.png

733964b1c4d54e618f819a4c4c051484.png

// 设置聚光灯的角度
spotLight.angle = Math.PI / 10

a6b7abe759924519ac441a1022eb8623.png

// 设置从光源发出光的最大距离
spotLight.distance = 0
gui
    .add(spotLight, 'distance')
    .min(0)
    .max(30)
    .step(0.01)

be586da7237d4940b808a95596f140d8.png

// 聚光锥的半影衰减百分比
spotLight.penumbra = 0
gui
    .add(spotLight, 'penumbra')
    .min(0)
    .max(1)
    .step(0.01)

e945ce2505854faea2dffd7fe60bfe89.png

// 设置沿着光照距离的衰减量
spotLight.decay = 0
......
gui
    .add(spotLight, 'decay')
    .min(0)
    .max(5)
    .step(0.01)
......
renderer.physicallyCorrectLights = true

86e74c3ed6764078bcd7fe1df06e0e3e.png

45fc82a82c6542bdb2ff4986377d8db3.png

相关文章
|
12天前
|
设计模式 前端开发 JavaScript
【JavaScript 技术专栏】JavaScript 设计模式与实战应用
【4月更文挑战第30天】本文探讨JavaScript设计模式在提升开发效率和代码质量中的关键作用。涵盖单例、工厂、观察者、装饰器和策略模式,并通过实例阐述其在全局状态管理、复杂对象创建、实时数据更新、功能扩展和算法切换的应用。理解并运用这些模式能帮助开发者应对复杂项目,提升前端开发能力。
|
15天前
|
JavaScript 前端开发
js变量的作用域、作用域链、数据类型和转换应用案例
【4月更文挑战第27天】JavaScript 中变量有全局和局部作用域,全局变量在所有地方可访问,局部变量只限其定义的代码块。作用域链允许变量在当前块未定义时向上搜索父级作用域。语言支持多种数据类型,如字符串、数字、布尔值,可通过 `typeof` 检查类型。转换数据类型用 `parseInt` 或 `parseFloat`,将字符串转为数值。
18 1
|
4天前
|
开发框架 JavaScript 中间件
中间件应用Koa.js(Node.js)
我们添加了两个中间件。第一个中间件记录请求的开始时间,并在下一个中间件执行完毕后计算并打印出请求的总时间。第二个中间件与之前的示例相同,它设置响应体为 "Hello World"
20 6
|
12天前
|
存储 JavaScript 前端开发
【JavaScript技术专栏】JavaScript基础入门:变量、数据类型与运算符
【4月更文挑战第30天】本文介绍了JavaScript的基础知识,包括变量(var、let、const)、数据类型(Number、String、Boolean、Undefined、Null及Object、Array)和运算符(算术、赋值、比较、逻辑)。通过实例展示了如何声明变量、操作数据类型以及使用运算符执行数学和逻辑运算。了解这些基础知识对初学者至关重要,是进阶学习JavaScript的关键。
|
4天前
|
JavaScript 中间件 API
中间件应用Express.js(Node.js)
我们定义了一个名为 `logger` 的中间件函数。它接受请求对象、响应对象以及下一个中间件函数作为参数。当接收到请求时,它会打印出请求的 HTTP 方法和 URL,然后调用 `next()` 函数来将控制权传递给下一个中间件或路由处理器。我们使用 `app.use()` 方法将 `logger` 中间件添加到了应用级别的中间件堆栈中,这意味着它将对所有请求生效。
12 3
|
6天前
|
JavaScript
js多维数组去重并使具有相同属性的对象数量相加
js多维数组去重并使具有相同属性的对象数量相加
10 1
|
6天前
|
数据采集 JavaScript 数据可视化
Node.js爬虫在租房信息监测与分析中的应用
Node.js爬虫在租房信息监测与分析中的应用
|
8天前
|
JavaScript 前端开发 开发者
JavaScript基础入门之浏览器控制台调试输出
本文章是对小白学习js的初级教程,也是我对自己学习经验的一种总结,文章大多采用使用案例加讲解,带动学习的方式.因为我们的天性总是喜欢有及时反馈的事物,但是学习是一个慢长的事情,而有结果的回应,才会更好的促进自己去学习,主要是对于javascript学习中的输出,有个大体上的了解,同时通过教学能够更好的使用浏览器来方便我们去学习和运行代码,也是对自己进行笔记整理,对抓住信息关键点的一种提高.
|
12天前
|
开发框架 JavaScript 前端开发
【JavaScript 与 TypeScript 技术专栏】TypeScript 在 Web 开发中的前沿应用
【4月更文挑战第30天】TypeScript在Web开发中日益重要,以其强大的类型系统提升代码质量,支持组件化开发,与React、Vue、Angular等框架良好集成。在大型项目管理中,TypeScript助于代码组织和优化,提高团队协作效率。此外,它提升开发体验,提供智能提示和错误检测。众多成功案例证明其前沿应用,未来将在Web开发领域持续发挥关键作用。
|
12天前
|
前端开发 JavaScript 网络协议
【JavaScript技术专栏】WebSockets在JavaScript中的应用
【4月更文挑战第30天】WebSocket是为解决HTTP协议在实时通信上的局限而诞生的技术,提供全双工、持久连接的通信方式,适合在线聊天、实时游戏等场景。JavaScript中的WebSocket API使浏览器与服务器能建立持久连接,通过事件处理连接、发送/接收数据及错误。相较于AJAX轮询和长轮询,WebSockets更高效、实时,是现代Web实时通信的优选。