开启Three.js之旅(会持续完善)

发布于:2024-04-19 ⋅ 阅读:(36) ⋅ 点赞:(0)

Three.js必备

官方文档

推荐文档

官方在线编辑平台

推荐免费的素材网站

官网一些说法用词对于刚接触的我有些晦涩,下面的我会追加自己的理解,欢迎来指正讨论。

构建项目

可以结合多种框架构建,也可以结合TS

首先我们先清楚一下主逻辑(我下面写的都是实例)

Camera
renderer.render(scene,camera)
Scene
renderer
appendChild(renderer.domElement)

场景Scene

场景我们可以就是理解为场景,我们可以往里面加入很多东西
就像一间屋子的场景,我们可以往里面加桌子椅子一样

THREE.Scene()是一个构造函数,返回一个实例scene

属性

  • background

    若不为空,在渲染场景的时候将其设置为背景,且背景总是首先被渲染的。

  • environment

    若该值不为null,则该纹理贴图将会被设为场景中所有物理材质的环境贴图(然而,该属性不能够覆盖已存在的、已分配给MeshStandardMaterial.envMap的贴图)

    关于这个是整个场景的环境,我可以把整个场景置地于室内,也可以置地于蓝蓝的天空之下

相机Camera

PerspectiveCamera

用来模拟人眼看到景象,也是用的最多的一种相机

const camera = new THREE.PerspectiveCameraPerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number );

参数说明

  1. fov 相机锥体垂直视野角度
  2. aspect 视锥体长宽比
  3. near 视锥体近端面
  4. far 远端面(后面我增加一个图来说明情况)

属性

  1. zoom 缩放倍数 默认值为1

渲染器

WebGLRenderer

使用WebGL渲染你的场景

WebGLRenderer是构造器

构造器生成的实例, 需要挂在到对应的元素上

  • antialias 抗锯齿

  • setSize(width:Number, height:Number, updateStyle:Boolean)

    视口从(0,0)开始调整为适合大小,updateStyle 对canvas的样式做出改变

最终步骤都是加入到对应的元素

document.getElementById("container").appendChild('renderer');

CSS3DRenderer

也叫做css 3D渲染器

通过css3的transform属性,将层级的3D变换应用到DOM元素上。

限制:

  • 不能使用three.js的材质系统
  • 不能使用几何体

CSS3DRenderer仅仅关注普通的DOM元素(因为毕竟是css)

CSS3Renderer()是一个构造函数,返回一个实例

方法:

  • getSize()
  • setSize() 调整尺寸

最终步骤都是加入到对应的元素

document.getElementById("container").appendChild('cssrenderer.domElement');

灯光

现实中物体表面的明暗是受光的影响的。

在three.js中,用Mesh网格模型来模拟现实中的物体

AmbientLight环境光
Light
PointLight点光源
SpotLight聚光灯
Direction平行光
Mesh
漫反射MeshLamberMaterial
高光MeshPhongMaterial
物理MeshStandardMaterial、MeshPhysicalMaterial
不受影响MeshBasicMaterial

Light

光源的基类

Properties

  • color
  • intensity – 光照强度

Methods

  • dispose – 释放由该实例分配的GPU资源
  • copy
  • toJSON

AmbientLight

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

构造函数

  • color
  • intensity – 光照强度

Properties

  • isAmbientLight

demo

const light = new THREE.AmbientLight( 0x404040 , 1);
scene.add( light );

DirectionalLight 平行光

平行光是沿着特定方向发射的光,常常用来模拟太阳光的效果

构造函数

  • color 可选
  • intensity 强度

demo

const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5);
scene.add( directionalLight );

PointLight

点光源

demo

const pointLight = new THREE.PointLight(0xffffff, 1.0);  // 光源颜色, 光照强度

Properties

  • decay – 光源衰减 0.0不衰减,默认2.0
  • position
    • set(x, y, z) – 设定位置

加载器

关于加载器

值得我们注意的是加载文件路径的问题

以Vue为例,应该是静态目录下public存放我们的模型, 无论你在哪一级,three都会从这个目录下拿资源, ./对应的文件就可以了(不要用相对位置去拿资源或者其它)

Cache

也是很少直接使用,一般直接配置就可以

THREE.Cache.enabled = true   // 全局生效,要在所有FileLoader的加载器上启用缓存

其大致意思就是,当 THREE.Cache.enabled 设置为 true 时,Three.js 会启用缓存机制,它会自动缓存加载的纹理、模型等资源数据。这可以提高性能和加载速度,因为在后续使用相同资源时,可以直接从缓存中获取,而不需要重新加载。

THREE.Cache.enabled 设置为 false 时,缓存机制将被禁用,每次加载资源时都会重新加载。

默认为false

Methods

  • add(key, file)
  • get(key)
  • remove(key)
  • clear() – 清除缓存中所有的值

一个简单的缓存系统,内部使用FileLoader

FileLoader

一般很少直接使用,直接使用更加高级的加载器,其会被大多数加载器内部使用

使用XMLHttpRequest来加载资源的低级类,并由大多数加载器内部使用。 它也可以直接用于加载任何没有对应加载器的文件类型。

demo

Methods

Loader

用于实现加载器的基类

Properties

  • path – 加载资源的基本路径
  • crossOrigin – 允许CROS的其他域加载url。默认为anonymous

Methods

  • load() – 要看具体的加载器的用法
  • loadAsync

GLTFLoader

GLTF,用于更高效地传输、加载3D内容。该文件以JSON(.gltf)格式或者二进制(.glb)格式提供。

一个glTF组件可传输一个或多个场景, 包括网格、材质、贴图、蒙皮、骨架、变形目标、动画、灯光以及摄像机

RGBELoader

用来加载高动态范围(HDR)环境贴图。

HDR环境贴图以.hdr格式存储,表示更广泛的亮度范围

TextureLoader

加载texture的一个类。 内部使用ImageLoader来加载文件。

demo

// 立即使用纹理进行材质创建
const texture = new THREE.TextureLoader().load('textures/land_ocean_ice_cloud_2048.jpg' );
const material = new THREE.MeshBasicMaterial( { map: texture } );

TextureLoader

加载texture的一个类。 内部使用ImageLoader来加载文件

我们可以用它来加载图片,去做纹理

const texture = new THREE.TextureLoader().load( 'textures/land_ocean_ice_cloud_2048.jpg' );

创建材料时可以用到这个纹理

const material = new THREE.MeshBasicMaterial( { map: texture } );

就是一个可以把图片加工成纹理,可以生成material使用

Methods

  • load( url, onLoad, onProgress, onError )

    url – 文件路径

    onLoadonProgressonError – 字如其意,Function

材质

顾名思义就是材质的意思

Metarial

材质的抽象基类

就只是材质,与渲染器无关

Constructor

Properities

Methods

  • clone – 返回相同的材质
  • copy – copy材质

MeshBasicMaterial

基础网格材质,不会受到光照(light)的影响

MeshLambertMaterial

对于光照(light)会有漫反射的效果

漫反射是投射在粗糙表面上的光向各个方向反射的现象。当一束平行的入射光线射到粗糙的表面时,由于各点的法线方向不一致,反射光线会向不同的方向无规则地反射,这种反射称为“漫反射”或“漫射”。

MeshPhysicalMaterial

MeshStandardMaterial

基于物理的渲染(PBR), 在实践中,该材质提供了比MeshLambertMaterialMeshPhongMaterial 更精确和逼真的结果,代价是计算成本更高。

这个应该是材质中最逼真的,最好看的(个人认为),能够写出金属光泽

Properties

  • alphaMap – 贴图是一张灰度纹理,用于控制整个表面的不透明度
  • aoMap
  • aoMapIntensity
  • color – 材质的颜色
  • envMap – 环境贴图
  • fog – 材质是否受雾的影响
  • map – 贴图,可以结合纹理(texture)
  • metalness – 材质与金属的相似度。金属1.0 ~ 非金属0.0
  • roughness – 材质的粗糙程度。 平滑的镜面反射0.0 ~ 完全漫反射1.0

metalness 金属度越高,材料表面会越暗(因为更像金属)

Methods(见Material)

SpriteMaterial

控制

OrbitControls

Orbit controls(轨道控制器)可以使得相机围绕目标进行轨道运动。
OrbitControls本质就是改变相机得参数,比如相机得位置属性,

const controls = new OrbitControls( camera, renderer.domElement );

Evenets

  • change
    – 当摄像机被组件改变时触发
  • start
    – 初始化交互时触发
  • end
    – 当交互结束时触发

Attributes

  • maxDistance 相机最多向外移动多少
  • minDistance 相机最多向内移动多少
  • target
    控制器的焦点,object的轨道围绕它运行,可以更改其焦点

Methods

  • update 更新控制器。必须在摄像机的变换发生任何手动改变后调用

几何体

BoxGeometry

BoxGeometry(width, height, depth, widthSegments, heightSegments, depthSegments)

Params

  1. width
  2. height
  3. depth
  4. widthSegments 可选宽度的分段数
  5. heightSegments 可选深度的分段数
  6. depthSegments 可选的深度的分段数

Properties

物体

Mesh 网格

常量

Texture

纹理常量

动画系统

requestAnimationFrame
利用window.requestAnimationFrame实现渲染

旋转动画

推荐参考文章

矩阵变换

Three.js使用matrix编码3D变换

解决方案

给模型绑定click函数

其实什么函数都可以,判断点击

鼠标放模型上变小手

优化方案

优化模型体积之神 – DRACOLoader

这个优化真的很厉害,模型一般比较大,用这个基本可以优化自身的一半,甚至更多

尽量复用,使用一个DRACOLoader的实例即可

我们来封装一个函数(结合Vue,模型都是glb, 其实这个功能很强大,能优化很多种格式的)

initDracoLoader(){
  this.dracollLoader = new DRACOLoader();  // 属于拓展,需要显式引入
  this.dracollLoader.setDecoderPath('./draco/');
  this.dracollLoader.preload();
}

使用

const loader = new GLTFLoader();
loader.setDRACOLoader(this.dracollLoader)
loader.load(element, (gltf) =>{
    ...
})

有几个需要注意的点:

  1. setDecoderPath(‘/draco/’)的路径,是自定义的。这里需要一个操作就是把对应的文件夹copy到public目录下(其它也可以)

    关键是在threejs包中找到,版本不同,可能文件的位置不同,

image.png

  1. 别忘记了对你原本的glb文件,分别进行处理
gltf-pipeline -i old.glb -o new.glb -d

这个工具需要全局下载

npm install -g gltf-pipeline

推荐文章

Three——glb模型压缩

github-draco