尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Three.js入门指南:从零搭建3D网页开发环境与核心概念解析

Three.js入门指南:从零搭建3D网页开发环境与核心概念解析 1. 从零开始为什么选择Three.js以及它能为你带来什么如果你对在网页上创建3D内容感兴趣无论是想做一个炫酷的产品展示、一个交互式的数据可视化图表还是一个简单的3D小游戏那么Three.js几乎是你绕不开的名字。它不是一门新的编程语言而是一个基于WebGL的JavaScript 3D库。简单来说WebGL是一个底层的、非常复杂的图形接口直接用它就像用汇编语言写程序虽然强大但效率低下。Three.js则像是一个高级的图形框架它把WebGL那些晦涩难懂的API封装起来让你可以用更直观、更符合人类思维的方式去创建3D场景、添加灯光、加载模型、设置动画。我第一次接触Three.js是想给一个静态的产品官网加点“料”。当时觉得如果能把产品模型放到网页上让用户360度旋转查看体验肯定比几张静态图片强得多。但一查WebGL的文档光是初始化一个画布、设置着色器就足以劝退。直到发现了Three.js用几行代码就能让一个立方体在屏幕上旋转起来那种“原来这么简单”的惊喜感至今记忆犹新。所以这篇内容就是写给当初像我一样对3D网页开发充满好奇但又不知从何下手的你。无论你是前端开发者想拓展技能树还是设计师、创意工作者想实现自己的交互构想Three.js都是一个绝佳的起点。它降低了3D创作的门槛让你能更专注于创意本身而不是与底层API搏斗。2. 环境搭建不止是npm install那么简单很多人以为安装Three.js就是一行npm install three命令这没错但这只是开始。一个稳定、可扩展的开发环境能让你在后续的学习和项目中事半功倍。这里我会分享几种常见的环境搭建方式并详细解释每种方式的适用场景和背后的考量。2.1 方式一最纯粹的CDN引入适合快速尝鲜与原型验证当你只是想快速验证一个想法或者写一个简单的Demo时通过CDN内容分发网络直接在HTML文件中引入Three.js库是最直接的方式。你不需要安装Node.js也不需要构建工具一个文本编辑器和一个浏览器就够了。具体操作是在你的HTML文件的head或body末尾添加一个script标签指向Three.js的CDN地址。这里我推荐使用skypack.dev或esm.sh这类提供ES模块格式的CDN因为它们更现代能直接使用import语法。!DOCTYPE html html langen head meta charsetUTF-8 titleMy First Three.js Scene/title style body { margin: 0; } canvas { display: block; } /style /head body script typemodule // 直接从CDN导入Three.js的核心模块 import * as THREE from https://cdn.skypack.dev/three0.146.0; // 你的Three.js代码从这里开始写 const scene new THREE.Scene(); const camera new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer new THREE.WebGLRenderer(); renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement); // ... 添加物体、灯光等代码 /script /body /html注意使用CDN时务必注意版本号。像上面例子中的0.146.0我指定了一个具体的稳定版本。如果不加版本号默认会引入最新的主版本这可能导致你的代码因为API变更而突然无法运行。对于学习和小型项目锁定一个已知稳定的版本是更稳妥的做法。这种方式的最大优点是零配置立即可用。但缺点也很明显1) 无法方便地管理依赖比如你还想引入dat.gui做调试面板或stats.js看帧率2) 代码无法模块化拆分所有逻辑都写在一个script标签里项目稍大就会难以维护3) 缺乏代码压缩、打包等优化手段。因此它只适用于最小的原型或一次性实验。2.2 方式二现代前端工程化方案推荐用于正式项目与系统学习对于任何打算认真学习和开发的项目我都强烈建议使用Node.js和模块打包工具如Vite、Webpack来搭建环境。这听起来有点复杂但一旦配置好它将为你带来巨大的便利模块化管理、热重载修改代码后浏览器自动刷新、代码优化、以及轻松集成其他工具库。第一步安装Node.js与npm首先确保你的电脑上安装了Node.js它自带了npm包管理器。你可以去Node.js官网下载LTS长期支持版本。安装完成后在命令行输入node -v和npm -v能显示版本号即表示成功。第二步初始化项目并安装Three.js找一个空文件夹在命令行中执行以下命令# 初始化一个新的npm项目一路按回车使用默认配置即可 npm init -y # 安装Three.js库 npm install three这会在当前目录下生成一个package.json文件并在node_modules文件夹中安装Three.js及其依赖。第三步选择并配置构建工具以Vite为例在众多打包工具中我目前最推荐Vite。它速度极快配置简单对初学者非常友好。继续在命令行中执行# 安装Vite npm install vite --save-dev然后在项目根目录创建一个index.html文件作为入口和一个main.js文件作为JavaScript主逻辑。index.html内容!DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleThree.js with Vite/title /head body !-- 画布将由Three.js动态创建并插入到这里 -- div idapp/div !-- 使用typemodule引入我们的主JS文件 -- script typemodule src/main.js/script /body /htmlmain.js内容import * as THREE from three; // 创建场景、相机、渲染器 const scene new THREE.Scene(); const camera new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); const renderer new THREE.WebGLRenderer({ antialias: true }); // 开启抗锯齿 renderer.setSize(window.innerWidth, window.innerHeight); renderer.setPixelRatio(window.devicePixelRatio); // 设置像素比适配高清屏 document.getElementById(app).appendChild(renderer.domElement); // 创建一个立方体并添加到场景 const geometry new THREE.BoxGeometry(1, 1, 1); const material new THREE.MeshBasicMaterial({ color: 0x00ff00 }); const cube new THREE.Mesh(geometry, material); scene.add(cube); camera.position.z 5; // 动画循环 function animate() { requestAnimationFrame(animate); cube.rotation.x 0.01; cube.rotation.y 0.01; renderer.render(scene, camera); } animate();第四步运行开发服务器在package.json的scripts部分添加一个启动命令{ scripts: { dev: vite, build: vite build } }然后在命令行运行npm run dev。Vite会启动一个本地开发服务器并自动在浏览器中打开你的页面。现在当你修改main.js或index.html文件并保存时页面会即时刷新无需手动操作。这种工程化方案的优势是全面的你可以使用ES6模块语法清晰组织代码可以轻松安装其他辅助库npm install dat.gui stats.js可以利用Vite等工具带来的极致开发体验和构建优化。这是投入正式项目开发的唯一推荐路径。2.3 方式三使用官方示例模板最省心的起步如果你觉得上面配置Vite的步骤还是有些麻烦或者想快速得到一个包含基础场景和控件的完整示例Three.js官方在GitHub上提供了一个名为three.js的庞大仓库里面有一个/examples目录。虽然直接克隆整个仓库有点大但你可以借鉴其结构。更简单的方法是直接使用一些社区维护的Three.js项目模板。例如在GitHub上搜索“threejs-vite-template”你能找到许多开箱即用的项目它们通常已经配置好了Vite、Three.js、甚至常用的控制器OrbitControls和调试UI。直接克隆下来运行npm install和npm run dev就能获得一个功能齐全的3D开发环境。这对于想跳过配置、直接开始编码和实验的同学来说是一个非常好的选择。3. 核心概念初探理解Three.js的“舞台、演员与摄像机”安装好环境跑通第一个旋转的立方体后我们有必要停下来理解一下让这个立方体动起来的基本要素。Three.js的架构非常直观它模拟了一个真实的3D拍摄现场主要包含三大核心对象场景Scene、相机Camera和渲染器Renderer。我习惯把它们比作“舞台、摄像机和放映机”。3.1 场景Scene容纳一切的3D空间场景是一个容器所有你想要在3D世界中显示的对象——比如网格物体、灯光、甚至声音——都需要被添加到场景中。你可以把它想象成一个无限大的、空荡荡的舞台或宇宙。创建场景非常简单const scene new THREE.Scene();创建后你可以设置它的背景颜色或背景贴图scene.background new THREE.Color(0x87CEEB); // 设置为天蓝色 // 或者使用一张图片作为背景 // const textureLoader new THREE.TextureLoader(); // scene.background textureLoader.load(path/to/sky.jpg);一个常见的初学者错误是创建了物体却忘了把它add到场景中导致物体“隐身”。记住scene.add(object)是让物体出现在世界里的关键一步。3.2 相机Camera决定观众看到什么相机定义了观察3D世界的视角。Three.js提供了多种相机最常用的是透视相机PerspectiveCamera因为它模拟了人眼观察世界的方式物体近大远小看起来更自然。创建一个透视相机需要四个参数const camera new THREE.PerspectiveCamera(fov, aspect, near, far);fov视野Field of View垂直方向的视野角度单位是度。通常设置在45到75之间。值越大你能看到的范围越广类似广角镜头但边缘物体会产生更明显的变形。75是一个比较通用的值。aspect宽高比渲染输出画布的宽高比。通常设置为window.innerWidth / window.innerHeight即浏览器窗口的宽高比这样画面才不会拉伸变形。near近裁剪面距离相机多近的物体开始被渲染。比这个距离更近的物体不会被显示。通常设为一个小数如0.1。far远裁剪面距离相机多远的物体还能被渲染。比这个距离更远的物体不会被显示。这个值需要根据你的场景大小来设置如果场景很大比如一个星空这个值可能要设到1000甚至10000。实操心得near和far的设置需要谨慎。两者的比值far / near不宜过大否则在深度精度上可能会产生“Z-fighting”两个表面因深度值过于接近而闪烁的问题。在能满足场景需求的前提下尽量让这个比值小一些。相机创建后默认位于坐标原点(0,0,0)。为了让它能“看到”场景中的物体我们通常需要把它往后移动一点camera.position.z 5;相机的位置、朝向通过lookAt方法设置共同决定了最终的画面构图。3.3 渲染器Renderer将3D世界绘制到2D屏幕渲染器是真正干活的“放映机”。它获取场景和相机的信息通过WebGL API在HTML的canvas元素上绘制出最终的2D图像。最常用的是WebGLRenderer。const renderer new THREE.WebGLRenderer();创建渲染器时可以传入一个配置对象来启用一些特性const renderer new THREE.WebGLRenderer({ antialias: true, // 开启抗锯齿让边缘更平滑 alpha: true, // 允许canvas背景透明 powerPreference: high-performance // 提示浏览器优先考虑性能 });创建后你需要告诉渲染器它输出的画布应该有多大并把这个画布DOM元素添加到页面上renderer.setSize(window.innerWidth, window.innerHeight); document.body.appendChild(renderer.domElement);这里有一个非常重要的细节像素比Pixel Ratio。在高分辨率屏幕如Retina屏上一个CSS像素可能对应多个物理像素。如果不做处理图像可能会模糊。Three.js渲染器提供了setPixelRatio方法来适配renderer.setPixelRatio(window.devicePixelRatio);我强烈建议在创建渲染器后立即调用这行代码它能显著提升在高清屏上的显示质量。最后你需要调用渲染器的render方法并传入场景和相机才能生成一帧画面renderer.render(scene, camera);但静态的一帧是没意思的我们需要一个动画循环不断更新物体状态并重新渲染从而产生动画效果。这就是下一节要讲的内容。4. 第一个动态场景让立方体动起来理解了三大核心对象后我们来组装一个完整的、有动画的示例。这个例子将包含一个绿色立方体在场景中持续旋转。我们将一步步拆解代码并解释每个部分的作用。4.1 创建几何体与材质定义物体的“形状”与“外观”在Three.js中一个可视的物体称为“网格”Mesh由两部分构成几何体Geometry和材质Material。几何体定义了物体的形状即它的顶点、面和轮廓。Three.js提供了许多内置的基础几何体如立方体BoxGeometry、球体SphereGeometry、圆柱体CylinderGeometry等。我们创建一个边长为1的立方体const geometry new THREE.BoxGeometry(1, 1, 1);BoxGeometry的三个参数分别代表宽度、高度和深度。材质定义了物体的表面属性比如颜色、光泽度、透明度、是否受光照影响等。最简单的材质是MeshBasicMaterial它不受光照影响直接显示为某种颜色或贴图。我们创建一个绿色的基础材质const material new THREE.MeshBasicMaterial({ color: 0x00ff00 });这里的颜色使用十六进制表示0x前缀是JavaScript中十六进制数的写法00ff00代表绿色。4.2 组合成网格并添加到场景有了“形状”和“外观”我们就可以用它们创建一个“物体”——网格Meshconst cube new THREE.Mesh(geometry, material); scene.add(cube);现在这个绿色的立方体已经位于场景的世界坐标原点(0,0,0)。由于相机也在原点我们之后会移动它此时它们重叠在一起你是看不到立方体的。4.3 设置相机位置与动画循环为了让相机能看到立方体我们把相机沿着Z轴正方向移动5个单位camera.position.z 5;现在相机在(0,0,5)看向(0,0,0)默认看向Z轴负方向立方体就在它的视野中了。接下来是实现动画的核心——动画循环。原理是利用浏览器提供的requestAnimationFrame方法。这个方法会告诉浏览器你希望执行一个动画并要求浏览器在下次重绘之前调用你指定的回调函数来更新动画。这比用setInterval或setTimeout更高效因为它与浏览器的刷新率同步能提供更流畅的动画并且在页面不可见时会自动暂停节省资源。我们定义一个animate函数function animate() { // 请求下一帧动画形成循环 requestAnimationFrame(animate); // 更新逻辑让立方体旋转 cube.rotation.x 0.01; cube.rotation.y 0.01; // 渲染用相机拍摄当前场景绘制到画布上 renderer.render(scene, camera); } // 启动动画循环 animate();在每一帧中我们微调立方体绕X轴和Y轴的旋转角度单位是弧度然后调用renderer.render重新绘制画面。由于这个函数每秒会被调用约60次与屏幕刷新率一致立方体的角度不断变化就形成了平滑的旋转动画。4.4 处理窗口大小变化目前我们初始化渲染器时将大小设置为窗口的初始尺寸(window.innerWidth, window.innerHeight)。但当用户调整浏览器窗口大小时画布不会自动适应会导致画面拉伸或出现空白。我们需要监听窗口的resize事件并更新相机和渲染器的尺寸。window.addEventListener(resize, () { // 更新相机宽高比 camera.aspect window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); // 相机参数改变后必须调用此方法 // 更新渲染器输出尺寸 renderer.setSize(window.innerWidth, window.innerHeight); // 如果之前设置了像素比这里也需要重新设置通常不需要除非窗口拖动到不同DPI的屏幕 // renderer.setPixelRatio(window.devicePixelRatio); });关键点修改了相机的fov、aspect、near、far这些属性后必须调用camera.updateProjectionMatrix()来使更改生效。这是很多初学者容易忘记的一步会导致画面显示异常。至此一个完整的、带自适应功能的Three.js旋转立方体示例就完成了。将所有这些代码组合到你的main.js中运行开发服务器你就能看到一个在浏览器中流畅旋转的绿色立方体。5. 项目结构与代码组织从Demo到可维护项目当你的代码超过一两百行或者开始添加多个物体、灯光、交互逻辑时把所有代码都堆在main.js里会迅速变得难以管理。一个清晰的项目结构不仅能让你自己思路清晰也便于团队协作和后期维护。这里分享一种我经过多个项目实践后觉得比较合理的组织方式。假设你的项目名为threejs-project目录结构可以这样规划threejs-project/ ├── index.html # 主HTML文件 ├── package.json # 项目依赖和脚本 ├── vite.config.js # Vite配置文件可选 ├── public/ # 静态资源模型、纹理、声音等 │ ├── models/ │ ├── textures/ │ └── sounds/ └── src/ # 源代码目录 ├── main.js # 应用入口初始化场景、渲染循环 ├── core/ # 核心功能模块 │ ├── SceneManager.js # 场景管理类 │ ├── CameraManager.js # 相机管理类 │ └── RendererManager.js # 渲染器管理类 ├── objects/ # 具体的3D物体定义 │ ├── MyCustomModel.js │ └── ParticleSystem.js ├── utils/ # 工具函数 │ ├── helpers.js │ └── loaders.js # 资源加载封装 ├── controls/ # 交互控制 │ └── OrbitControls.js (从three/examples导入) └── styles/ └── main.css # 样式文件核心思想是“分离关注点”main.js作为入口职责单一导入必要的模块初始化核心管理器启动动画循环。core/目录下的管理器类分别封装场景、相机、渲染器的创建、更新逻辑。例如SceneManager.js可以负责创建场景、添加默认灯光、管理场景中所有对象的添加和移除。objects/目录存放具体的3D物体类。比如你有一个复杂的太空飞船模型它的几何体创建、材质设置、动画混合等逻辑可以封装成一个Spaceship类然后在主程序中实例化。这极大提高了代码的复用性和可读性。utils/目录放一些通用的辅助函数比如加载纹理的Promise封装、坐标转换函数、随机数生成器等。静态资源统一放在public/目录下Vite等构建工具在开发时能直接通过根路径/models/myModel.glb访问构建后也会被正确处理。让我们看一个简化的main.js示例感受一下这种结构的好处// src/main.js import { SceneManager } from ./core/SceneManager.js; import { CameraManager } from ./core/CameraManager.js; import { RendererManager } from ./core/RendererManager.js; import { createCustomCube } from ./objects/CustomCube.js; // 初始化核心管理模块 const sceneManager new SceneManager(); const cameraManager new CameraManager(); const rendererManager new RendererManager(); // 将渲染器的画布添加到页面 document.getElementById(app).appendChild(rendererManager.renderer.domElement); // 创建自定义物体并添加到场景 const myCube createCustomCube(); sceneManager.addObject(myCube); // 动画循环 function animate() { requestAnimationFrame(animate); // 更新所有需要动画的对象 myCube.update(); // 由管理器负责渲染 rendererManager.render(sceneManager.scene, cameraManager.camera); } // 启动 animate(); // 窗口大小变化响应 window.addEventListener(resize, () { cameraManager.onWindowResize(); rendererManager.onWindowResize(); });这样的代码主逻辑非常清晰各司其职。当你需要调试相机时就去CameraManager.js需要添加一个新的特效可能只需在RendererManager里加一个后处理通道。这种模块化思维是任何严肃项目开发的基石。6. 调试与性能观察开发者必备的辅助工具在3D开发中肉眼观察往往不够。一个物体为什么没显示相机视角对不对性能有没有瓶颈我们需要借助一些工具来“看见”看不见的东西。这里介绍几个Three.js生态中几乎不可或缺的调试和性能观测工具。6.1 使用Three.js自带的辅助对象Three.js提供了一系列Helper类它们是不可见的虚拟对象的可视化表示对于调试场景布局、光照、相机等极其有用。坐标轴辅助器AxesHelper显示世界坐标系的X红色、Y绿色、Z蓝色轴。在场景初始化后立刻添加一个能帮你快速理解物体的方位。const axesHelper new THREE.AxesHelper(5); // 参数代表轴的长度 scene.add(axesHelper);相机辅助器CameraHelper显示相机的视锥体即能看到的空间范围。这对于调试相机的near、far、fov参数是否设置合理非常直观。const cameraHelper new THREE.CameraHelper(camera); scene.add(cameraHelper);光源辅助器例如DirectionalLightHelper显示平行光的方向和位置。const light new THREE.DirectionalLight(0xffffff, 1); light.position.set(5, 5, 5); scene.add(light); const lightHelper new THREE.DirectionalLightHelper(light, 1); // 第二个参数是辅助器大小 scene.add(lightHelper);这些辅助器在开发阶段可以帮你快速定位问题在项目发布前记得将它们从场景中移除或通过条件编译排除。6.2 图形化控制面板lil-gui手动在代码里修改参数然后刷新页面查看效果效率极低。lil-gui原名dat.GUI是一个轻量级的图形用户界面库可以让你在网页上实时调整变量并立即看到效果。这对于调整材质颜色、光照强度、物体位置、动画速度等参数来说是神器级别的工具。首先安装它npm install lil-gui然后在你的代码中使用import GUI from lil-gui; const gui new GUI(); // 假设我们有一个配置对象 const config { cubeColor: 0x00ff00, rotationSpeed: 0.01, wireframe: false }; // 将配置对象绑定到GUI gui.addColor(config, cubeColor).onChange((value) { cube.material.color.set(value); // 颜色改变时更新立方体材质颜色 }); gui.add(config, rotationSpeed, 0, 0.1).onChange((value) { // 在动画循环里使用这个值来控制速度 }); gui.add(config, wireframe).onChange((value) { cube.material.wireframe value; // 切换线框模式 }); // 你还可以添加文件夹来组织复杂的参数 const cameraFolder gui.addFolder(Camera); cameraFolder.add(camera.position, z, 0, 20).name(Position Z);现在运行页面你会看到一个可折叠的控制面板拖动滑块或选择颜色立方体的外观和行为会实时改变。这极大地提升了开发迭代速度。6.3 性能监控stats.js3D应用很吃性能帧率FPS是衡量流畅度的关键指标。stats.js是一个简单的JavaScript性能监控库可以显示帧率、渲染时间等信息。安装npm install stats.js注意通常需要安装types/stats.js以获得类型提示如果你用TypeScript使用import Stats from stats.js; const stats new Stats(); stats.showPanel(0); // 0: fps, 1: ms, 2: mb, 3: custom document.body.appendChild(stats.dom); function animate() { stats.begin(); // 开始测量 // ... 你的动画和渲染逻辑 renderer.render(scene, camera); stats.end(); // 结束测量 requestAnimationFrame(animate); }stats.dom是一个div元素默认显示一个小的FPS计数器。你可以通过CSS调整它的位置。在开发过程中时刻关注FPS如果它经常低于60就意味着你可能需要优化了比如减少多边形数量、合并网格、使用更简单的材质等。将这些工具组合使用你的Three.js开发环境就具备了强大的实时调试和性能观测能力能帮助你更快地构建和优化3D应用。7. 常见陷阱与避坑指南在入门Three.js的路上几乎每个人都会踩一些相似的坑。提前了解这些常见问题可以节省你大量的调试时间。下面是我总结的几个高频“坑点”及其解决方案。7.1 物体“隐身”检查添加到场景、相机位置与朝向“我明明创建了物体代码也没报错为什么屏幕上什么都没有”这是最常见的问题。请按以下清单排查确认物体已添加到场景检查你是否执行了scene.add(yourMesh)。这是最容易被忽略的一步。检查相机位置和朝向物体和相机都在默认的原点(0,0,0)它们重叠了你自然看不见。确保相机已经移动到物体前面例如camera.position.z 5。同时确认相机看向哪里。默认看向Z轴负方向。你可以用camera.lookAt(0, 0, 0)让它看向原点。检查近/远裁剪面near/far如果物体距离相机的位置小于near或大于far它会被裁剪掉不会渲染。确保你的物体在[near, far]这个区间内。检查物体是否在相机视野fov内如果物体在相机的侧面或后面你也看不到。可以添加一个AxesHelper和CameraHelper来可视化坐标系和相机视锥体精确定位物体和相机的关系。7.2 材质颜色显示异常颜色格式与光照你设置材质颜色为红色(0xff0000)但物体显示为黑色或很暗。确认材质类型MeshBasicMaterial不受光照影响会直接显示你设置的颜色。但如果你使用的是受光照影响的材质如MeshStandardMaterial或MeshPhongMaterial那么场景中必须有光源否则物体就是黑的。确保你已添加了至少一个光源如AmbientLight环境光或DirectionalLight平行光。检查颜色值格式Three.js中颜色是十六进制数前面必须加0x而不是CSS中常用的#。new THREE.Color(0xff0000)是正确的new THREE.Color(#ff0000)虽然Three.js的Color构造函数也能解析但直接传入0x格式是更标准且性能稍好的做法。7.3 资源加载失败路径问题与异步处理加载外部纹理图片或3D模型时控制台报404错误或加载失败。路径问题这是前端老生常谈的问题。如果你使用Vite等构建工具静态资源通常放在public目录下并通过绝对路径以/开头引用。例如图片在public/textures/wood.jpg加载时应使用textureLoader.load(/textures/wood.jpg)。在开发服务器和生产构建中这个路径都能正确解析。避免使用复杂的相对路径../../assets/容易出错。异步加载TextureLoader.load()和GLTFLoader.load()都是异步的。你不能在加载完成前就使用纹理或模型。确保在加载完成的回调函数或Promise的.then()中进行后续操作。const textureLoader new THREE.TextureLoader(); textureLoader.load( /textures/wood.jpg, (texture) { // 加载成功在这里使用texture const material new THREE.MeshBasicMaterial({ map: texture }); cube.material material; }, undefined, // 加载进度回调可选 (error) { // 加载失败 console.error(纹理加载失败:, error); } );跨域问题CORS如果你从其他域名加载资源可能会遇到跨域限制。对于开发可以配置本地服务器允许跨域对于生产确保资源服务器设置了正确的CORS头或者将资源部署在同域名下。7.4 性能骤降几何体与绘制调用场景稍微复杂一点帧率就掉得厉害。几何体复杂度检查模型的多边形数量。一个几十万面的模型在网页上压力会很大。对于展示类应用尽量使用低多边形Low Poly模型或在3D建模软件中优化减面。材质和纹理数量每个独特的材质/纹理组合通常会导致一次“绘制调用”。过多的绘制调用是性能杀手。尽量合并使用相同材质的物体或者使用纹理图集Texture Atlas将多个小纹理合并成一张大图。实时阴影阴影计算开销很大。renderer.shadowMap.enabled true以及为灯光和物体分别设置castShadow和receiveShadow都会增加负担。如果非必需可以关闭阴影。如果必需尽量减小阴影贴图的分辨率light.shadow.mapSize.width/height和相机的阴影范围light.shadow.camera。使用Stats.js监控如前所述用stats.js实时监控FPS。当添加新功能或模型后FPS大幅下降它就是帮你定位性能瓶颈的第一工具。入门阶段先把功能做对再考虑优化。但从一开始就建立性能意识了解这些常见的“性能刺客”对于开发流畅的3D体验至关重要。记住Three.js的强大也意味着责任你需要管理好你创建的这个3D世界。
返回列表