3D沉浸式体验开发技巧【Three.js】

news2024/12/26 23:10:51

在本文中,我们将看看如何使用 Three.js 创建一个充满后期效果和微交互的迷你城市。

在这里插入图片描述

推荐:将 NSDT场景编辑器 加入你的3D开发工具链。

1、背景介绍

我是一个游戏爱好者。 我一直梦想创建一个交互式迷你城市,使用饱和的颜色,类似于 SimCity 等。 挑战在于我既没有足够的 3D 知识也没有开发库。

2021年底,我终于决定完成一个旧愿,我选修了Bruno Simon的课程——Three.js Journey。 我是一个喜欢编程的设计师。 由于这门课程,我最终发现自己是一名创意开发人员,在那里我能够使用我对已故 Macromedia Flash 的 ActionScript 2.0 的部分沉睡的知识。

整个项目是在大约 2 周内创建的,这是我在 Neotix 工作的轮班之间。 这感觉太棒了,我喜欢这样做,所以我决定分享一些关于它的有趣信息,这样我就可以以某种方式帮助那些刚开始这段旅程的人。

2、创意挑战

在不影响性能的情况下,使用游戏中存在的各种后处理效果来为这座城市提供体面的真实感至关重要。 我选择遵循的艺术道路是混合使用逼真的灯光和低多边形模型。
在这里插入图片描述

3、性能表现

我希望这个项目的部分目的是应用在不同设备(尤其是移动设备)上表现良好的技术。 它需要以可接受的帧速率(至少 30 fps)在尽可能多的设备上运行。 我还希望体验能够尽快加载,文件小于 2MB。

为了实现这一点,我不得不使用我将在下面描述的一系列技术。
在这里插入图片描述

4、在 Blender 中创建 3D 模型

我使用 Blender 制作城市模型。

我从互联网上的免费模板中导入了部分建筑物。 我修改了其中的一些以更好地匹配设置。 为了制作地形,我使用了 Blender 的雕刻模式,创建了在光影下看起来很漂亮的山谷和山峰。
在这里插入图片描述

每个模型都在导出时考虑了三角形的数量进行了优化。 我选择使用 GLB 格式是因为 Draco 的压缩效果令人难以置信——文件大小有时会小 7 倍。 此外,所有项目资源也在运行时在服务器上使用 gzip 进行压缩,以减少传输。

5、创建自然光

游戏中的光照非常迷人——阴影与地形相互作用的方式,目的是创造一个既赏心悦目又不被现实阻碍的场景。 我使用了 Blender 的全局照明系统,带有一个“world”节点,使用“Nishita”环境照明。 这允许非常自然的照明,环境设置可以快速产生令人愉悦的结果。
在这里插入图片描述

6、在 Blender 中使用几何节点分布树

树木起着重要的作用,因为它们有助于创建投射阴影,使地形具有真实感。 我使用 Blender 的 GeometryNodes 来分布模型中的树木并创建大小、形状和旋转的变化。 我还使用了材质选择器,选择树木较多或较少的区域,使用材质选择绘制密度。

在这里插入图片描述

7、烘焙照明以供导出

为了让体验在 Three.js 中发挥作用和表现良好,场景加载烘焙到纹理中的光照非常重要。 我为 2048×2048 的地板创建了一个纹理,包含所有阴影。 可以在互联网上的几个教程中找到如何进行阴影烘焙的过程。 最终结果令人印象深刻,并且对性能没有影响。

在这里插入图片描述

8、导出到 Three.js

完成烘焙并将纹理连接到地面网格中的颜色节点后,我将所有网格导出为 GLTF 格式。 使用 DRACO COMPRESSION 的整个模型为 1.2MB。 然而,我们的树有一个问题:它们不能一次全部导出,因为 GPU 完成这个过程需要很长时间。

我使用 Three.js 的 MESH SURFACE SAMPLER 创建了树,它正是用于此目的。 您可以使用模型并将其分布在表面上,创建同一模型的变体,但对每个模型进行修改。 因此,性能是令人难以置信的,即使有非常多的变化。

你可以在 Three.js 官方文档中看到这样的例子。

在这里插入图片描述

9、在 Three.js 中加载所有内容

使用我为简化事情而创建的样板文件(在文章末尾查看更多相关信息),我加载了导出的模型。 之后,我花了很多时间来调整灯光的颜色、强度和其他让一切变得不同的小细节。 对于使用默认参数的 Three.js 体验而言,3D 渲染的结果并不总是很好。
在这里插入图片描述

必须使用 DAT.GUI 才能直观地调整参数。 不可能通过猜测数字来获得正确的颜色和强度。
在这里插入图片描述

10、使用 VertexShader 制作树木的动画

给场景带来真实感的一件事是树木的流畅动画。 通过直接从 Blender 导出动画可以做到这一点,但性能会受到很大影响——尤其是考虑到大量树木。

在这些情况下,最好的方法是使用 VertexShader 制作动画,使用 GPU 处理直接处理 3D 世界中的顶点定位。 这样,性能非常好,动画也很漂亮。
在这里插入图片描述

11、鸟类动画和体验的其他元素

体验中的其他动画元素,如直升机、汽车和风力涡轮机,是通过直接在渲染循环中改变模型部件的旋转来制作动画的。 这是一种非常简单的动画制作方式。

鸟类的动画效果不同。 我希望他们有翅膀运动和分组感。 因此,我在 blender 中对整个组进行了动画处理,并将动画与 GLFT 文件一起导出。 我使用动画混合器在改变组位置的同时为翅膀设置动画。 结果非常有说服力,而且非常轻巧(只有 200kb)。

在这里插入图片描述

12、灯光、阴影和夜间模式

由于阴影是在导入的 GLB 文件中烘焙的,因此我能够通过不必在 Three.js 中使用动态生成的阴影贴图来获得一些性能。

我尝试了灯光效果,创造了夜间模式和世界末日模式。 无需修改模板即可拥有这种创作自由,这很有趣。 可能性是无止境。

世界末日模式是一个彩蛋,任何知道如何激活它的人都可以访问:)。
在这里插入图片描述

13、使用 Effect Composer 进行后期处理

我一直很喜欢游戏中的景深效果,但我认为在 Three.js 体验中使用类似的东西会非常困难。 由于库的最近更新,它变得更加容易。

使用 EffectComposer,我能够在白天模式下使用 BokehPass 效果,它会根据与相机的距离生成动态景深效果。 对于夜间模式,我使用 UnrealBlooomPass,它使灯光超级暴露,非常适合此类情况。

出于性能原因,我在夜间和白天模式之间更改效果——使用 insertPass() 和 removePass() 方法。

14、单击并选择建筑物

很多人问我如何制作可点击的建筑 UI 项目。 这是使用 Three.js 的 RayCaster 完成的,它检测相机发射的不可见光线与鼠标之间的交点。 有了这个,我可以检测到何时选择了建筑物,并根据其名称触发事件。

在这里插入图片描述

单击建筑物时发生的动画是使用 TWEEN.JS 完成的,方法是将初始相机位置动画化为单击建筑物的位置。 这样,我可以放置多个建筑物并自动生成动画。

15、响应式调整:也适用于移动设备

部分工作还涉及调整体验参数以在移动设备上正常运行。 不仅仅是对 HTML 和 CSS 的响应式调整,还有对相机参数、动画持续时间和其他一些细节的调整。

16、根据用户设备的能力动态调整性能

尽管进行了所有优化,但某些设备仍然无法运行所有效果,尤其是后处理效果。 所以我创建了一个脚本来测量实验开始时的 FPS(在加载过程中)。 这样,当实验开始时,Three.js 知道是否激活某些效果以节省处理并确保性能在该设备可能的范围内。
在这里插入图片描述

17、研究智能手表

作为概念证明,我想证明在 Three.js 中完成的实验即使在智能手表上处理和运行也不繁重。 在此过程中,我发现模型中的顶点数量对这些设备的性能影响最大。 因此,我创建了一个模型的“超低多边形”模式,以便在移动设备上使用。 准备好! 代码中的其他任何内容都不需要更改。
在这里插入图片描述


原文链接:Three开发沉浸式体验 — BimAnt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/358091.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android自动化测试(UiAutomator)——UiObject

本文主要讲解使用UiAutomator的一些技巧,希望对于初学者有一定的帮助 UiObject 1、首先要声明对象 UiObject XXX new UiObject(new Selector) ; 2、其次对对象进行操作 操作类型包括: 执行类:文本输入与清除、点击/长按、拖动/滑动、 …

JAVA JDK 常用工具类和工具方法

目录 Pair与Triple Lists.partition-将一个大集合分成若干 List集合操作的轮子 对象工具Objects 与ObjectUtils 字符串工具 MapUtils Assert断言 switch语句 三目表达式 IOUtils MultiValueMap MultiMap JAVA各个时间类型的转换(LocalDate与Date类型&a…

开源软件AirByte:入湖入仓,数据集成管道

从ETL到ELT就传统的 ETL而言,当我们开始构建数据仓库时,都要先去了解业务流程,明晰业务是如何运转的,数据是如何留痕的。通过收集用户的相关需求,从而去规划设计报表。企业需要进行数仓分域、分层、逻辑建模等一系列操…

Linux下程序调试的方法【GDB】GDB相关命令和基础操作(命令收藏)

目录 1、编译 2、启动gdb调试 2.1 直接运行 2.2 运行gdb后使用run命令 2.3 调试已运行的程序 3、图形界面提示 4、调试命令 1、查看源码 2、运⾏程序/查看运⾏信息 3、设置断点 5、单步/跳步执⾏ 6、分割窗口 7、其他命令 8、相关参数 1、编译 在编译时要加上-g选…

stm32f407探索者开发板(十七)——串口寄存器库函数配置方法

文章目录一、STM32串口常用寄存器和库函数1.1 常用的串口寄存器1.2 串口相关的库函数1.3 状态寄存器(USART_ SR)1.4 数据寄存器(USART_ DR)1.5 波特率寄存器(USART_BRR)二、串口配置一般步骤一、STM32串口常…

java static关键字 万字详解

目录 一、为什么需要static关键字: 二、static关键字概述 : 1.作用 : 2.使用 : 三、static修饰成员变量详解 : 1.特点 : 2.细节 : ①什么时候考虑使用static关键字? ②静态变量和非静态变量的区别? ③关于静态变量的初始化问题 : ④关于静态变…

基于springboot+vue的器官捐献系统

基于springbootvue的器官捐献系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项目背景介绍&…

内网渗透(四十一)之横向移动篇-PsExec工具远程命令执行横向移动

系列文章第一章节之基础知识篇 内网渗透(一)之基础知识-内网渗透介绍和概述 内网渗透(二)之基础知识-工作组介绍 内网渗透(三)之基础知识-域环境的介绍和优点 内网渗透(四)之基础知识-搭建域环境 内网渗透(五)之基础知识-Active Directory活动目录介绍和使用 内网渗透(六)之基…

CCNP350-401学习笔记(201-250题)

201、An engineer attempts to configure a trunk between switch SW1 and switch SW2 using DTP, but the trunk does not form. Which command should the engineer apply to switch SW2 to resolve this issue? A. switchport mode dynamic desirable B. switchport mode a…

GNU make 中文手册 第一二章 概述与介绍

一、第一章:概述 准备知识 在开始我们关于 make 的讨论之前,首先需要明确一些基本概念: 编译:把高级语言书写的代码,转换为机器可识别的机器指令。编译高级语言后生成的指令虽然可被机器识别,但是还不能…

小程序 npm sill idealTree buildDeps 安装一直没反应

目录 一、问题 二、解决 1、删除.npmsrc 、清除缓存 2、更换镜像源 3、最终检测 一、问题 记录:今天npm 一直安装不成功 显示:sill idealTree buildDeps 我的版本: 我百度到换镜像源安装方法,但我尝试后,依然…

CUDA性能指南

CUDA性能指南 文章目录CUDA性能指南5.1 整体性能优化策略5.2 最大化利用率5.2.1 应用程序层次5.2.2 设备层次5.2.3 多处理器层次5.2.3.1 占用率计算5.3 最大化存储吞吐量5.3.1 设备与主机之间的数据传输5.3.2 设备内存访问5.4最大化指令吞吐量5.4.1 算数指令5.4.2 控制流指令5.…

前端 ES6 环境下 require 动态引入图片以及问题

前端 ES6 环境下 require 动态引入图片以及问题require 引入图片方式打包体积对比总结ES6 环境中,通过 require 的方式引入图片很方便,一直以来也没有出过什么问题,后来项目中,需要动态引入图片。 require 动态引入也容易实现&am…

第一章 Kafka快速实战与基本原理

第一章 Kafka快速实战与基本原理 1、介绍 Kafka 是最初由 Linkedin 公司开发的,是一个分布式、支持分区的(partition)、多副本的(replica),基于 zookeeper 协调的分布式消息系统,它最大的特性就…

分布式(四)

五、分布式锁 1. 概念 1.1 本地锁 使用ReetrantLock类和synchronized关键字JDK自带的本地锁来控制一个JVM进程内的多个线程对本地共享资源的访问。 1.2 分布式锁 分布式系统下,不同的服务器/客户端通常运行在独立的JVM进程上。 多个JVM进程共享一份资源的话&…

leetcode 1~10 学习经历

LeetCode 习题 1 - 101. 两数之和2. 两数相加3. 无重复字符的最长子串4. 寻找两个正序数组的中位数5. 最长回文子串6. N 字形变换7. 整数反转8. 字符串转换整数 (atoi)9. 回文数10. 正则表达式匹配1. 两数之和 给定一个整数数组 nums 和一个整数目标值 target,请你在…

大数据处理学习笔记1.5 掌握Scala内建控制结构

文章目录零、本讲学习目标一、条件表达式(一)语法格式(二)执行情况(三)案例演示任务1、根据输入值的不同进行判断任务2、编写Scala程序,判断奇偶性二、块表达式(一)语法格…

科学推理~

科学推理 【物理】 1、力学 重力 重力并不是指向地心的,只有赤道可以 弹力 【重点】判断弹力方向 相互作用力 摩擦力 静摩擦力 滑动摩擦力 注意:最大静摩擦力默认等于滑动摩擦力 压强 固体压强 液体压强 连通器 气体压强 气体对外做功,T 下…

1 月份 NFT 行业报告

Jan.2023, DanielData Source: NFT Monthly Report1 月是近一年来代币价格最好的一个月,ETH、BTC 和 altcoins 的涨幅是 7 月以来最猛的。自然,这导致了 NFT 行业的交易量和市值增加。一些指标是可以预测的,比如已完成的投资轮数继…

BI知识全解,值得收藏

2021年度,中国商业软件市场的增长趋势是快速增长的,达到7.8亿美元,同比增长34.9%。商业智能BI在企业应用中具有巨大的价值,并逐渐成为现代企业信息化和数字化转型的基础。所以,全面了解BI,对于企业管理是非…