2️⃣threejs学习笔记(二)
2026-3-12
| 2026-3-17
字数 4773阅读时长 12 分钟
type
Post
status
Published
date
Mar 12, 2026
slug
summary
Texture Material(材质) Text
tags
Three.js
category
技术学习笔记
icon
password

Texture

即纹理,可以实现给材质添加上图片等功能
声明时要通过创建一个 TextureLoader 来加载,如:
Copy
背后的原理:
Copy
这就是材质加载出来的样子:
在这里插入图片描述
在这里插入图片描述
如果使用 textureLoader 来加载,则不需要显式地调用 texture.needsUpdate = true 来通知纹理更新,纹理会在加载完成后自动地渲染出效果

LoadingManager

可以用来监听纹理、字体等物体的加载节点,内部实现了
的回调函数
在这里插入图片描述

uvmapping(待补充)

uv坐标是一组用来定位纹理位置的坐标,掌握这个属性很重要

mipmapping

在这里插入图片描述
在这里插入图片描述
看左上角的图,一个4x4的正方形可以由4个2x2的正方形构成,一个2x2的正方形可以由4个1x1的正方形构成
mipmapping 是一种GPU的计算策略,内部会将一张纹理图不断地拆解成若干个小单元,最后叠加起来构成纹理,同时这样也使得渲染性能得以提升
mipmapping 会对纹理图进行持续的计算直到裁剪到 1*1 的像素为止,所以,使用纹理图时,要确保纹理图的宽高为2的幂次方,如256、512、1024等,否则在 threejs 内部还要额外进行处理,浪费性能
结合 mipmapping 使用的是 minFilter 属性和 magFilter 属性,一般设为 NearestFilter 性能会比较好,锐利度也够高( why?
当我们把 minFilter 设置成 NearestFilter 后,可以将 texture.generateMipmaps 设为 false 进一步提升性能
使用纹理图时,纹理图大小不要太大,以降低请求的时间

Material(材质)

要在场景中渲染几何体,需要同时给这个几何体添加相应的材质才可实现
创建
时,通过配置
属性来添加纹理,比如添加一张门的纹理:
在这里插入图片描述
几何体正常情况下会渲染成这样:
在这里插入图片描述
会发现纹理图不是想象中的大小,门的两侧有同色的拉伸效果,如果想要取消掉拉伸效果,可以提供一个
材质,比如:
在这里插入图片描述
要求提供一张黑白图,图中白色部分会被渲染,黑色部分会被省略,配置后的效果:
在这里插入图片描述
注意,同时还需要配置 transparent:true 才会生效

MeshNormalMaterial

法线材质使用纹理时可以使用带方向的纹理图
在这里插入图片描述
几何体的每个面都有n个顶点,可以通过 widthSigmentsheightSigments 来设置,每个面的顶点由相交线相交得来,有多少个顶点就有多少个方向,
这种材质可以实现打光,折射和反射;拿灯光举例,之所以能看到几何体的某个面,是因为那个面的法线恰好指向我们自己或光源的方向,而其他非正面的方向就有不同程度的阴影或看不到(背面) ,这就是 gpu 计算出 3D 物体的光形态的原理
比如配置一个默认的
,效果如下:
在这里插入图片描述
假如加上一个 flatShading 配置,如:
Copy
可以看到表面变得不光滑了:
在这里插入图片描述
可以再进一步开启
观察构成几何体的平面,可以看到它们的表面就是由若干个三角形构成的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
所以 flatShading 的意义在于仅对这些平面进行着色,忽略平滑的计算效果

MeshMatcapMaterial

这个材质会自动根据提供的纹理图选择合适的颜色进行渲染,选择的依据是基于对灯光的模拟,比如下图:
在这里插入图片描述
添加到几何体上后:
Copy
在这里插入图片描述
在这里插入图片描述
这个纹理的好处在于可以直接使用图片来模拟灯光、阴影的效果,比如再来一个例子:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
一个找 matcap 纹理的仓库: github.com/nidorx/matcaps ,商用时需要确保自己有授权
也可以自己用3d绘制软件画一个球,做好灯光投射等配置后,输出矩形的 matcap 图来使用

MeshDepthMaterial

深度材质,特点是离摄像机越近则越白,越远则越黑
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
需要注意的是,灯光不会作用于该材质上,所以使用了该材质后, ambientLightpointLight 都不会有效果

MeshLambertMaterial

对场景中使用 LambertMaterial ,需要同时加上光源:
Copy
在这里插入图片描述
在这里插入图片描述
因为有点光源的存在,当把摄像机拉到背面时,可以看到阴影
在这里插入图片描述
这是一个会受光影响的材质,表现力很强,性能好,但是当你放大到足够大时,几何体表面会有一些模糊的线条:
在这里插入图片描述
如果不添加光源,比如 ambientLight ,看到的物体就是一团黑

MeshPhongMaterial

相比于 Lamber ,他不会有模糊的问题,自带“光反射”,但是性能不好,如果项目中出现了很多物体,导致整体性能不够好时,要考虑换掉这种材质
所有可以光反射的材质都可以设置 shininess (光反射强度),( lambert 不行,因为它不会对光做出反射)
使用 Phong 时, shininess 用来控制反射强度,值越大,光反射越集中:
在这里插入图片描述
在这里插入图片描述
用来控制光反射的颜色,比如设为红色时:
在这里插入图片描述

MeshToonMaterial

拥有类似卡通效果的材质,与lambert材质有类似的效果,但是由于颜色会发生急剧的变化,所以会有类似卡通的效果出现
在这里插入图片描述
在这里插入图片描述
从点光源的方向照射过来,到阴影的位置急剧变化,所以出现了类似断层的现象,看起来就和卡通的效果相似
一般可以配置
属性来控制它颜色的效果,比如加载一张只有深灰、浅灰、白色的渐变图作为
在这里插入图片描述
代码:
Copy
效果:
在这里插入图片描述
只是简单的设置 gradientMap 后会让卡通效果消失,这是因为 gpu 会自动使用 mipmapping 进行计算, mipmapping 会把渐变色计算的非常精细,所以过渡效果就会很平滑,当像素被拆分得足够精细时,颜色急剧变化就不存在了
可以配置 minFilter、magFilterNearestFilter 来恢复急剧的变化:
Copy
在这里插入图片描述
在这里插入图片描述
这里是使用了只有3种颜色的渐变图片,当换成有5个渐变色时:
在这里插入图片描述
效果:
在这里插入图片描述
同时,因为使用了 NearestFilter ,所以可以把 generateMipmaps 设为 false 来进一步减少性能开销

MeshStandardMaterial

这个材质与 LambertPhong 类似,但是它呈现的效果就更贴近现实,因为它的算法比较”真实”,并且参数的设置上更利于我们理解
默认情况下的效果:
在这里插入图片描述
可以看到默认情况下
分别是0和1,当将他随意改变时,会发现比较神奇的效果:
在这里插入图片描述
官方文档对
的解释,
可以理解成
在这里插入图片描述
的解释:
在这里插入图片描述
去到官方文档,可以看到相关的描述:1. 基于PBR渲染,显得更真实;2. 占用、计算成本更高;3. 使用时尽可能制定envMap
在这里插入图片描述
在使用该材质的情况下同时加上之前的纹理图,会出现更逼真的效果,比如:
Copy
在这里插入图片描述
在这里插入图片描述

使用aoMap(AmbientOcclusion)

同时,为了更好地模拟阴影效果,可以引入
来实现,在官方文档中地描述:(全名:
在这里插入图片描述
比如使用下面这张
纹理图:
在这里插入图片描述
Copy
文档中要求第二组 uv 坐标,可以这么实现:
Copy
配置完成后,可以得到下面的效果,
在这里插入图片描述
调整
,可以看到更深的阴影:
在这里插入图片描述

displacementMap

位移贴图,官方文档的解释:
在这里插入图片描述
当使用下面这张图当作
时:
在这里插入图片描述
图片的黑色部分代表其高度不受影响,从黑色到白色,高度的变化程度不断增高 得到的效果:
在这里插入图片描述
位移贴图可以用来呈现”高度“的效果,而”高度“的效果由几何体的顶点数量决定,拿中间的 planeGeometry 举例,打开 wireFrame ,当配置的 widthSegmentsheightSegments 参数为10时:
Copy
它的顶点相对比较少:
在这里插入图片描述
此时如果配置上高度图,可以看到实际上就是顶点的位置发生了变化:
在这里插入图片描述
以此得到了类似高度的效果;而进一步将 widthSegmentsheightSegments 设置成更高的值时,顶点也随之增多:那么顶点突起的部分则更加精细:
Copy
在这里插入图片描述
在这里插入图片描述
关闭 wireFrame ,对比10和100的情况,会发现顶点越多,出来的效果就越好,这是合情合理的:
10的情况:
在这里插入图片描述
100的情况:
在这里插入图片描述
但是显然,我们不需要那么“高”的突起,所以可以通过 displacementScale (位移比例)来设置突起的程度,比如将 displacementScale 设为0.1时,效果就已经很好了:
Copy
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

metalnessMap与roughNessMap

两张图,分别作为
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码配置上之后:
Copy
在这里插入图片描述
在这里插入图片描述
乍看没什么变化,但是移动一下视角会发现,表面的反射和光泽更加逼真了:
在这里插入图片描述

normalMap

同样的,加上一个
纹理图:
在这里插入图片描述
Copy
在这里插入图片描述
在这里插入图片描述
乍看没什么变化,但是转换一下视角会发现,细节一下就出来了:
在这里插入图片描述
放大则看的更明显:
在这里插入图片描述
同样的,也可以配置
来调整法线纹理的比例:
在这里插入图片描述
最后,要实现一扇完美的门,再加上之前的 alphaMa 即可:
Copy
在这里插入图片描述
在这里插入图片描述

使用envMap

可以在这个网站找高清环境贴图: https://hdri-haven.com/ 然后去这个网站将图片转为 cubeMap 6张图: https://matheowis.github.io/HDRI-to-CubeMap/
使用
时,要使用具有6个方位图片的环境贴图纹理,需要使用
来加载纹理,比如加载下面这六张图:
在这里插入图片描述
Copy
加载环境贴图时,
的路径是有顺序要求的:
在这里插入图片描述
加载环境纹理后,使用下面的配置:
Copy
得到的效果:
在这里插入图片描述

Text

实际使用时可以直接复制 threejs/examples 里的 typeface 字体和 LICENSE 到自己的项目目录下使用
或者你有自定义的一套字体,将其在这个网站转换为 typeface 格式字体: https://gero3.github.io/facetype.js/
不过需要确保你有使用对应字体的授权
加载字体时,需要使用 fontLoader 加载字体,使用 TextGeometry 创建字体(拉伸)集合体
Copy
写入上面的配置后,可以得到下面的结果:
在这里插入图片描述
  1. curveSegmentsbevelSegments 会控制几何体顶点的数量,为了更好的性能,可以开着 wireFrame 来不断将它们调低,找到能满足自己需求的最小值
  1. 将视角放大,会看到在原点处,H字母的底部线是斜的,这是因为开启了 bevelEnabled 的原因
    1. 在这里插入图片描述
那如果我们想把字体“居中”,该怎么做呢?
正常来说,每个几何体都有一个固定的
来将其包裹:
在这里插入图片描述
默认情况下, threejs 的几何体是用球状框包裹的,此时无法通过 textGeometry.boundingBox 获取到它的边框值; 如果我们想获取到某个几何体的边框,需要先调用 textGeometry.computedBoundingBox() 方法,将几何体外边框转成 矩形边框 ,然后才可以获取到该 矩形边框
Copy
在这里插入图片描述
在这里插入图片描述
这一步骤是全程不可见的,没有什么办法来肉眼看到它的边框是怎样的
所以,居中实际上就是通过将几何体所有顶点沿着x轴、y轴、z轴移动其外层盒子框体最大 xyz 值的一半来实现居中,主要通过 translate 方法来实现:
Copy
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
但是移动后 box 的最大最小值貌似不太对,按理说最小值的x应该和最大值的x之和为0,但是加上会发现它们有 0.02 的差距
这个差距对应的就是上面配置的 bevelSize: 0.02 ,所以实际上精确的计算方式应该是:
Copy
当然,除了上面这种居中的方法,我们还可以使用 textGeometry.center() 方法来一步到位,不需要搞得这么麻烦:
Copy

一个移动的问题

注意,如果是自己计算,实际上有两种办法可以“居中”,但他们略有不同
一种是将几何体通过 translate 方法修改所有顶点的位置 一种是对 mesh.position 进行修改
Copy
虽然居中的效果相同,但是当要进行旋转、缩放时,结果可能就会偏离预期了
如果是移动几何体顶点的方式或 .center() 的方式,缩放、旋转都是以原点(0,0,0)进行:
在这里插入图片描述
在这里插入图片描述
但如果是通过移动 mesh 来实现的话,其几何体中心并不是(0,0,0),缩放、旋转的中心是以原本的中心位置为基点进行的:
在这里插入图片描述
在这里插入图片描述
未命名文章
  • Three.js
  • threejs学习笔记(一)threejs学习笔记(三)
    Loading...