1. 引言

Three.js是著名的JavaScript 3D图形库,用于浏览器中开发 3D 交互场景的 JS 引擎,可以快速的搭建三维场景

Three.js官网为:创建一个场景 – three.js docs (threejs.org)

GitHub站点为:mrdoob/three.js: JavaScript 3D Library. (github.com)

本文描述Three.js的基础使用与搭建一个场景

2. 基础使用

2.1 基础场景

使用Three.js构建一个场景,大致步骤如下:

graph LR
材质Material --> Mesh
几何体Geometry --> Mesh --> 场景Scene --> 渲染器Renderer
相机Camera --> 渲染器Renderer

按照上述流程,简要设置几个参数,就可以构建出一个简单的场景:

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html,
body,
canvas {
height: 100%;
width: 100%;
margin: 0;
}
</style>
</head> <body>
<canvas id="canvas"></canvas>
<script type="module">
import * as THREE from 'https://cdn.bootcdn.net/ajax/libs/three.js/0.151.3/three.module.js'; const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5; const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#canvas')
});
renderer.setSize(window.innerWidth, window.innerHeight, false) 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); function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
</script>
</body> </html>

结果如下:

2.2 光照

添加光照并修改一下材质(使其可以反光):

graph LR
材质Material --> Mesh
几何体Geometry --> Mesh --> 场景Scene
光照Light --> 场景Scene --> 渲染器Renderer
相机Camera --> 渲染器Renderer
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html,
body,
canvas {
height: 100%;
width: 100%;
margin: 0;
}
</style>
</head> <body>
<canvas id="canvas"></canvas>
<script type="module">
import * as THREE from 'https://cdn.bootcdn.net/ajax/libs/three.js/0.151.3/three.module.js'; const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5; const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#canvas')
});
renderer.setSize(window.innerWidth, window.innerHeight, false) const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshPhongMaterial({
color: 0x00ff00
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube); const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0, 0, 5);
scene.add(light); function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
</script>
</body> </html>

结果如下:

2.3 多个Mesh

添加两个Mesh到场景中,并共用一个Geometry:

graph LR
材质Material --> Mesh1
几何体Geometry --> Mesh1 --> 场景Scene
材质Material2 --> Mesh2
几何体Geometry --> Mesh2 --> 场景Scene
光照Light --> 场景Scene --> 渲染器Renderer
相机Camera --> 渲染器Renderer
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html,
body,
canvas {
height: 100%;
width: 100%;
margin: 0;
}
</style>
</head> <body>
<canvas id="canvas"></canvas>
<script type="module">
import * as THREE from 'https://cdn.bootcdn.net/ajax/libs/three.js/0.151.3/three.module.js'; const scene = new THREE.Scene(); const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5; const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#canvas')
});
renderer.setSize(window.innerWidth, window.innerHeight, false) const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshPhongMaterial({
color: 0x00ff00
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube); const material2 = new THREE.MeshPhongMaterial({
color: 0x0000ff
});
const cube2 = new THREE.Mesh(geometry, material2);
cube2.position.x = 2;
scene.add(cube2); const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0, 0, 5);
scene.add(light); function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
</script>
</body> </html>

结果如下:

2.4 控制器

加入轨道控制器OrbitControls实现场景拖动:

graph LR
材质Material --> Mesh
几何体Geometry --> Mesh --> 场景Scene
光照Light --> 场景Scene --> 渲染器Renderer
相机Camera --> 渲染器Renderer
相机Camera --> 控制器Controls
<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html,
body,
canvas {
height: 100%;
width: 100%;
margin: 0;
}
</style> </head> <body>
<canvas id="canvas"></canvas> <script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three/build/three.module.js",
"three/addons/": "https://unpkg.com/three/examples/jsm/"
}
}
</script> <script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; const scene = new THREE.Scene(); const canvas = document.querySelector('#canvas');
const camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight , 0.1, 1000);
camera.position.z = 5; const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#canvas')
});
renderer.setSize(window.innerWidth, window.innerHeight, false) const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshPhongMaterial({
color: 0x00ff00
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube); const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0, 0, 5);
scene.add(light); const controls = new OrbitControls( camera, renderer.domElement ); function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
</script>
</body> </html>
  • 注意这里的CDN地址、加载方式有变动

结果如下:

2.5 模型加载

加入GLTFLoader加载GLTF模型:

graph LR
材质Material --> Mesh
几何体Geometry --> Mesh --> 场景Scene
加载器Loader -->模型Model --> 场景Scene
光照Light --> 场景Scene --> 渲染器Renderer
相机Camera --> 渲染器Renderer
相机Camera --> 控制器Controls

模型下载自:three.js/Xbot.glb at dev · mrdoob/three.js · GitHub

<!DOCTYPE html>
<html lang="en"> <head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html,
body,
canvas {
height: 100%;
width: 100%;
margin: 0;
}
</style> </head> <body>
<canvas id="canvas"></canvas> <script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three/build/three.module.js",
"three/addons/": "https://unpkg.com/three/examples/jsm/"
}
}
</script> <script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'; const scene = new THREE.Scene(); const canvas = document.querySelector('#canvas');
const camera = new THREE.PerspectiveCamera(75, canvas.clientWidth / canvas.clientHeight , 0.1, 1000);
camera.position.z = 5; const renderer = new THREE.WebGLRenderer({
canvas: document.querySelector('#canvas')
});
renderer.setSize(window.innerWidth, window.innerHeight, false) const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshPhongMaterial({
color: 0x00ff00
});
const cube = new THREE.Mesh(geometry, material);
scene.add(cube); const gltfLoader = new GLTFLoader();
gltfLoader.load('./models/Xbot.glb', (gltf) => {
scene.add(gltf.scene)
gltf.scene.position.z = 2
}) const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(0, 0, 5);
scene.add(light); const controls = new OrbitControls( camera, renderer.domElement ); function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
</script>
</body> </html>

结果如下:

3. 参考资料

[1] 创建一个场景 – three.js docs (threejs.org)

[2] mrdoob/three.js: JavaScript 3D Library. (github.com)

[3] three.js manual (threejs.org)

Three.js的基础使用的更多相关文章

  1. node.js学习(二)--Node.js控制台(REPL)&&Node.js的基础和语法

    1.1.2 Node.js控制台(REPL) Node.js也有自己的虚拟的运行环境:REPL. 我们可以使用它来执行任何的Node.js或者javascript代码.还可以引入模块和使用文件系统. ...

  2. Node.js系列基础学习----安装,实现Hello World, REPL

    Node.js基础学习 简介 简单的说 Node.js 就是运行在服务端的 JavaScript.Node.js 是一个基于Chrome JavaScript 运行时建立的一个平台.Node.js是一 ...

  3. css+js+html基础知识总结

    css+js+html基础知识总结 一.CSS相关 1.css的盒子模型:IE盒子模型.标准W3C盒子模型: 2.CSS优先级机制: 选择器的优先权:!important>style(内联样式) ...

  4. JavaScript基础精华02(函数声明,arguments对象,匿名函数,JS面向对象基础)

    函数声明 JavaScript中声明函数的方式:(无需声明返回值类型) function add(i1, i2) {             return i1 + i2;//如果不写return返回 ...

  5. JavaScript--我发现,原来你是这样的JS(基础概念--灵魂篇,一起来学js吧)

    介绍 这是红宝书(JavaScript高级程序设计 3版)的读书笔记第三篇(灵魂篇介绍),有着剩下的第三章的知识内容,当然其中还有我个人的理解.红宝书这本书可以说是难啃的,要看完不容易,挺厚的,要看懂 ...

  6. js复习--基础

    最近工作遇到了一些小困难,基础真的很重要,漫天高楼起于地. 一,script元素 包括type=“text/Javascript”,defer延迟到html加载完解析,src=“../../test. ...

  7. 第八节 JS运动基础

    运动基础 让Div运动起来 速度——物体运动的快慢 运动中的Bug 不会停止 速度取某些值会无法停止 到达位置后再点击还会运动 重复点击速度加快 匀速运动(速度不变) 运动框架及应用: 运动框架: 在 ...

  8. JS零基础一步一步做应用全记录

    1.起因 作为几个外卖重度依赖癌晚期患者,呆宿舍的时候几个人一起叫外卖已经是常事.偶然看到隔壁宿舍在饿了么订餐的时候,看到在饿了么的首页上有一个谁去拿外卖的一个小游戏/工具,感觉这个小细节,饿了么把握 ...

  9. 认识JS的基础对象,定义对象的方法

    JS的基础对象: 1.window       //窗口对象 2.document   //文档对象 3.document.documentElement      //html对象 4.docume ...

  10. 贰、js的基础(一)

    1.js的语法 a.区分大小写 b.弱类型变量:变量无特定类型 c.每行结尾的分号可有可无 d.括号用于代码块 e.注释的方法与c语言和java相同 2.变量 注意事项: a.通过关键字var来声明. ...

随机推荐

  1. Linux-查看文本中第m行到n行的内容

    如何查看文件第6749行到6758行? 方式一:使用sed命令 不显示行号:sed -n 'M,Np'  fileName 例如:sed -n '6749,6758p'  hive-default.x ...

  2. Linux 中hdparm命令参数说明

    hdparm命令提供了一个命令行的接口用于读取和设置IDE或SCSI硬盘参数. 语法 hdparm(选项)(参数) 选项 -a:设定读取文件时,预先存入块区的分区数,若不加上选项,则显示目前的设定: ...

  3. Js捕获异常的方法

    Js捕获异常的方法 JavaScript的异常主要使用try catch finally语句以及窗口对象window的onerror事件来捕获. try catch finally try catch ...

  4. win32 - 从dll中导出api并使用

    从User32.dll中导出MessageBoxW 代码: #include <Windows.h> #include <iostream> #include <func ...

  5. 具备有效期的localStorage存储

    具备有效期的localStorage存储 类方式 // 具备有效期的localStorage存储-类方式. class LocalStorageWrapper { // 存储数据到localStora ...

  6. 进度条模块之tqdm

    导入模块 from tqdm import tqdm import time ''' desc 描述 ncols 进度条总长度 可修改 range(1000) 封装迭代器 ''' for i in t ...

  7. c# 4.8 实现Windows 定时任务计划(Task Scheduler)

    分享一个我自己写的 Windows 定时任务计划(Task Scheduler) 动态创建代码,没做太多封装,留个实现笔记 首先封装一个简单配置项的类 1 public class TaskSched ...

  8. 【Azure App Service for Linux】NodeJS镜像应用启动失败,遇见 RangeError: Incorrect locale information provided

    问题描述 在App Service For Linux 中,部署NodeJS应用,应用启动失败. 报错信息为: 2023-08-29T11:21:36.329731566Z RangeError: I ...

  9. python执行JavaScript代码出现编码问题的解决方案

    当我们安装好nodejs环境,想在python代码中去调用JavaScript代码,常常会出现编码的问题. 举个例子: python代码如下: 点击查看代码 import execjs f = ope ...

  10. C++ //类模板与继承 //类模板与继承 //注意: //1.当子类继承父类是一个类模板时,子类在声名的时候,要指定出父类中T的类型 //2.如果不指定,编译器无法给子类分配内存 //3.如果想灵活指定出父类中的T的类型,子类也需要变为类模板

    1 #include <iostream> 2 #include <string> 3 #include<fstream> 4 using namespace st ...