前端技术

three.js 入门手册

基本使用

安装

使用 npm 方式安装(推荐)

在项目文件夹中打开终端并执行以下命令

npm install --save three

在页面中引入 es-module-shims.js ,用于让浏览器兼容映射属性

<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>

设置路径映射,映射中的路径为 three.module.js 所在文件夹的路径

<script type="importmap">
  {
    "imports": {
      "three": "./three/build/three.module.js"
    }
  }
</script>

将 three.js 导入项目,导入模块有两种形式:

// 导入整个 three 核心库
import * as THREE from 'three'

// 仅导入所需部分模块
import { Scene } from 'three'

本地导入 three.js

创建一个编写 JavaScript 的文件,导入到 HTML 中,确保导入的 script 标签中有 type=”module” 属性。

<script type="module" src="./app.js"></script>

在编写 JavaScript 文件中导入 THREE 模块

import * as THREE from './three/three.js'

创建一个场景

初始化一个场景

  1. 建立一个场景 new THREE.Scene()
  2. 添加摄像机 new THREE.PerspectiveCamera()
  3. 设置摄像机位置
  4. 添加渲染器 new THREE.WebGLRenderer()
  5. 设置渲染尺寸 renderer.setSize()
  6. 将渲染器的 dom 元素添加到 HTML 页面中 enderer.domElement
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()
renderer.setSize( window.innerWidth, window.innerHeight )
document.body.appendChild( renderer.domElement )

创建物体

在场景中添加 3d 物体

  1. 创建模型
  2. 添加材质
  3. 添加物体网格
  4. 将物体加入场景
const geometry = new THREE.BoxGeometry()
const material = new THREE.MeshBasicMaterial( { color: 0x0000ff } )
const cube = new THREE.Mesh( geometry, material )
scene.add( cube )
camera.position.z = 5

渲染场景

现在,如果将之前写好的代码复制到HTML文件中,你不会在页面中看到任何东西。这是因为我们还没有对它进行真正的渲染。为此,我们需要使用一个被叫做“渲染循环”(render loop)或者“动画循环

渲染单帧画面
renderer.render( scene, camera )
渲染动画
  1. 设置动画刷新帧率
  2. 设置动画属性
  3. 渲染场景
function animate() {
  requestAnimationFrame( animate )
  cube.rotation.x += 0.01
  cube.rotation.y += 0.01
  renderer.render( scene, camera )
}
animate()

在这里我们创建了一个使渲染器能够在每次屏幕刷新时对场景进行绘制的循环(在大多数屏幕上,刷新率一般是60次/秒)。如果你是一个浏览器游戏开发的新手,你或许会说“为什么我们不直接用setInterval来实现刷新的功能呢?”当然啦,我们的确可以用setInterval,但是,requestAnimationFrame有很多的优点。最重要的一点或许就是当用户切换到其它的标签页时,它会暂停,因此不会浪费用户宝贵的处理器资源,也不会损耗电池的使用寿命。

导入模型

在网络中的 3d 模型,推荐使用 glTF 格式,.glb .gltf 是这种格式的这两种不同版本, 都可以被很好地支持。由于glTF这种格式是专注于在程序运行时呈现三维物体的,所以它的传输效率非常高,且加载速度非常快。 功能方面则包括了网格、材质、纹理、皮肤、骨骼、变形目标、动画、灯光和摄像机。

首先加载 GLTFLoader 模块,同时需要确保包含 three.module.js 文件,并确保 GLTFLoader.js 文件里指向的 three.module.js 地址正确。

import { GLTFLoader } from './three/examples/jsm/loaders/GLTFLoader.js'
const loader = new GLTFLoader();
loader.load('./rocket/rocket-gltf.glb', function(gltf) {
  scene.add(gltf.scene)
})
完整示例
import * as THREE from './three/build/three.module.js'
import { GLTFLoader } from './three/examples/jsm/loaders/GLTFLoader.js'
import { RoomEnvironment } from './three/examples/jsm/environments/RoomEnvironment.js'
import { OrbitControls } from './three/examples/jsm/controls/OrbitControls.js'

// 初始化场景
const container = document.querySelector('.canvas-container')
const aspect = window.innerWidth / window.innerHeight

const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(75, aspect, 0.1, 1000)
camera.position.z = 4
const renderer = new THREE.WebGLRenderer({antialias: true})
renderer.setSize( window.innerWidth, window.innerHeight )
container.appendChild( renderer.domElement )

// 设置环境照明
const pmremGenerator = new THREE.PMREMGenerator( renderer )
scene.environment = pmremGenerator.fromScene( new RoomEnvironment(), 0.04 ).texture

// 添加控制交互功能
const controls = new OrbitControls( camera, renderer.domElement )
controls.target.set( 0, 0.5, 0 )
controls.update()
controls.enablePan = false
controls.enableDamping = true

// 导入模型
let mixer
const clock = new THREE.Clock()
const loader = new GLTFLoader()
loader.load('./rocket/rocket.glb', function(gltf) {
  const model = gltf.scene
  model.position.y = 0.6
  scene.add( model )
  mixer = new THREE.AnimationMixer( model )
  mixer.clipAction( gltf.animations[ 0 ] ).play()
  animate()
})

// 监听窗口尺寸变化
window.addEventListener(
  "resize",
  () => {
    camera.aspect = window.innerWidth / window.innerHeight
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth, window.innerHeight)
  },
  false
);

// 动画循环
function animate() {
  requestAnimationFrame( animate )
  const delta = clock.getDelta()
  mixer.update( delta )
  controls.update()
  renderer.render( scene, camera )
}

工作平面

AxesHelper()

用于简单模拟3个坐标轴的对象。红色代表 X 轴,绿色代表 Y 轴,蓝色代表 Z 轴。括号中的数值表示轴的长度。

AxesHelper(num)

摄像机

Camera

摄像机的抽象基类。在构建新摄像机时,应始终继承此类。

PerspectiveCamera

透视相机

PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )

const camera = new THREE.PerspectiveCamera( 45, width / height, 1, 1000 )
scene.add( camera )
  • fov —— 摄像机视锥体垂直视野角度
  • aspect —— 摄像机视锥体长宽比
  • near —— 摄像机视锥体近端面
  • far —— 摄像机视锥体远端面

OrthographicCamera

StereoCamera

CubeCamera

ArrayCamera

摄像机阵列 ArrayCamera 用于更加高效地使用一组已经预定义的摄像机来渲染一个场景。这将能够更好地提升VR场景的渲染性能。
一个 ArrayCamera 的实例中总是包含着一组子摄像机,应当为每一个子摄像机定义viewport(视口)这个属性,这一属性决定了由该子摄像机所渲染的视口区域的大小。

lookAt()

http://www.yanhuangxueyuan.com/doc/three.js/lookat.html

设置摄像机对准的坐标

// 将摄像机对准到场景中心
camera.lookAt( scene.position )

绘制物体

BufferGeometry()

是面片、线或点几何体的有效表述。包括顶点位置,面片索引、法相量、颜色值、UV 坐标和自定义缓存属性值。使用 BufferGeometry 可以有效减少向 GPU 传输上述数据所需的开销。

BoxGeometry()

四边形的原始几何类,它通常使用构造函数所提供的“width”、“height”、“depth”参数来创建立方体或者不规则四边形。

CircleGeometry()

圆形

ConeGeometry()

锥体

CylinderGeometry()

圆柱

DodecahedronGeometry()

十二面体

EdgesGeometry()

边缘几何体

ExtrudeGeometry()

挤压缓冲几何体

IcosahedronGeometry()

二十面缓冲几何体

LatheGeometry()

车削缓冲几何体

OctahedronGeometry()

八面缓冲几何体

PlaneGeometry()

平面缓冲几何体

PolyhedronGeometry

多面缓冲几何体

RingGeometry

圆环缓冲几何体

ShapeGeometry

形状缓冲几何体

SphereGeometry

球缓冲几何体

TetrahedronGeometry

四面缓冲几何体

TorusGeometry

圆环缓冲几何体

TorusKnotGeometry

圆环缓冲扭结几何体

TubeGeometry

管道缓冲几何体

WireframeGeometry

网格几何体

外观

position

坐标位置

rotation

其他

setColor()

set()

setSize()

setPixelRatio()

环境纹理

参考资料:https://blog.csdn.net/moxiaomomo/article/details/107612292

PMREMGenerator

灯光

AmbientLight

环境光会均匀的照亮场景中的所有物体。环境光不能用来投射阴影,因为它没有方向。

AmbientLightProbe

光照探针是一种在3D场景中添加光源的另一种方法。 AmbientLightProbe 是场景中单个环境光的光照估算数据。 

DirectionalLight

平行光是沿着特定方向发射的光。这种光的表现像是无限远,从它发出的光线都是平行的。常常用平行光来模拟太阳光 的效果; 太阳足够远,因此我们可以认为太阳的位置是无限远,所以我们认为从太阳发出的光线也都是平行的。

HemisphereLight

光源直接放置于场景之上,光照颜色从天空光线颜色渐变到地面光线颜色。

HemisphereLightProbe

光照探针是一种在3D场景中添加光源的另一种方法。 HemisphereLightProbe 是场景中单个半球光的光照估算数据。

Light

光源的基类 – 所有其他的光类型都继承了该类描述的属性和方法。

LightProbe

光照探针是一种在3D场景中添加光源的另一种方法。与经典光源(平行光、点光、聚光)不同, 光照探针不发光。相反,光照探针存储着有关穿过3D空间的光线的信息。 渲染过程中,通过使用来自光照探针的数据,来逼近打到3D物体上的光线。

PointLight

从一个点向各个方向发射的光源。一个常见的例子是模拟一个灯泡发出的光。

RectAreaLight

平面光光源

SpotLight

灯光 / 阴影

LightShadow

PointLightShadow

DirectionalLightShadow

SpotLightShadow

渲染器

WebGLRenderer

WebGL1Renderer

WebGLRenderTarget

WebGLCubeRenderTarget

WebGLMultipleRenderTarget

着色器

ShaderChunk

动画

requestAnimationFrame()

参考链接

官网
https://threejs.org

中文文档
http://www.yanhuangxueyuan.com/threejs/docs/index.html

Bilibili 视频教程
https://www.bilibili.com/video/BV1g44y1L7np

http://www.yanhuangxueyuan.com/doc/Three.js/removeDispose.html

内容目录

PUJI Design 朴及设计 (c) 2024. 沪ICP备17052229号