直接回答:Three.js 的最小骨架是场景、相机、渲染器三件套,再加一个 requestAnimationFrame 循环不断 render;相机选透视的还是正交的,取决于要不要近大远小的效果。

场景、相机和渲染器,基础的三大对象

最常用的一种物体就是网格(Mesh),网格是由顶点、边、面等组成的物体;其他物体包括线段(Line)、骨骼(Bone)、粒子系统(ParticleSystem)等

1
2
3
1.创建物体(定点,面信息)
2.创建材质
3.Mesh(物体,材质)或者Line(物体,材质)给组合到一起

***.obj** 是最常用的模型格式,导入 *.obj 文件需要 OBJLoader.js ;导入带 .mtl 材质的.obj 文件需要 MTLLoader.js 以及 OBJMTLLoader.js 。

在 Three.js 中,能形成阴影的光源只有平行光 THREE.DirectionalLight 与聚光灯 THREE.SpotLight ;而相对地,能表现阴影效果的材质只有 THREE.LambertMaterial 与 THREE.PhongMaterial 。

动作渲染两种方法 setInterval 方法和requestAnimationFrame 方法

canvas元素有两个尺寸。一个是canvas在页面上的显示尺寸, 是我们用CSS来设置的。另一个尺寸是canvas本身像素的数量。这和图片一样。 比如我们有一个128x64像素的图片然后我们可以通过CSS让它显示为 400x200像素。

在three.js中我们可以通过调用renderer.setSize来设置canvas的绘图缓冲区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function resizeRendererToDisplaySize(renderer) {
const canvas = renderer.domElement;
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
renderer.setSize(width, height, false);
}
return needResize;
}
//注意如果我们的canvas大小被调整了那函数会返回true。我们可以利用 这个来检查是否有其他的东西应该更新。我们修改渲染循环 来使用我们的新函数
// 下面是伪代码
function render(time) {
time *= 0.001;

if (resizeRendererToDisplaySize(renderer)) {
const canvas = renderer.domElement;
camera.aspect = canvas.clientWidth / canvas.clientHeight;
camera.updateProjectionMatrix();
}
。。。。。。。。
}

摄像机

1
camera*.up.set(0,-1,0)//设置摄像机的上方向,这里代表是y轴负方向,默认是Y轴正方向

材质

我们就来看看three.js的几个材质。

MeshBasicMaterial不受光照的影响。MeshLambertMaterial 只在顶点计算光照,而MeshPhongMaterial则在每个像素计算光照。MeshPhongMaterial还支持镜面高光。

image-20230202163020574

  1. MeshPhongMaterial

MeshPhongMaterial 的shininess 设置决定了镜面高光的光泽度。它的默认值是30

image-20230202163124243

  1. MeshLambertMaterial

请注意,将 MeshLambertMaterial 或 MeshPhongMaterial 的 emissive 属性设置为颜色,并将颜色设置为黑色(phong的 shininess 为0),最终看起来就像 MeshBasicMaterial 一样。

image-20230202163249677

  1. MeshToonMaterial

MeshToonMaterial 与 MeshPhongMaterial 类似,但有一个很大的不同。它不是平滑地着色,而是使用一个渐变图(一个X乘1的纹理(X by 1 texture))来决定如何着色。默认使用的渐变图是前70%的部分使用70%的亮度,之后的部分使用100%的亮度,当然,你可以定义你自己的渐变图。这最终会给人一种2色调的感觉,看起来就像卡通一样。

物理材质

接下来是2种基于物理渲染(Physically Based Rendering)的材质。Physically Based Rendering通常简称为PBR。

之前提到的材质使用简单的数学来制作,看起来是3D的,但它们并不是现实世界中实际存在的东西。2种PBR材质使用更复杂的数学来接近现实世界中的实际情况。

  1. MeshStandardMaterial

第一个是 MeshStandardMaterial。MeshPhongMaterial 和 MeshStandardMaterial 最大的区别是它们使用的参数不同。MeshPhongMaterial 有一个参数用来设置 shininess 属性。MeshStandardMaterial 有2个参数用来分别设置 roughness 和 metalness 属性。 在基本层面,roughness 是 shininess 的对立面。粗糙度(roughness)高的东西,比如棒球,就不会有很强烈的反光,而不粗糙的东西,比如台球,就很有光泽。粗糙度的范围从0到1。

另一个设定,metalness,说的是材质的金属度。金属与非金属的表现不同。0代表非金属,1代表金属。

这里是 MeshStandardMaterial 的一个快速示例,从左至右看,粗糙度从0到1,从上至下看,金属度从0到1。

image-20230202163543876

  1. MeshPhysicalMaterial

    MeshPhysicalMaterial 与 MeshStandardMaterial 相同,但它增加了一个clearcoat 参数,该参数从0到1,决定了要涂抹的清漆光亮层的程度,还有一个 clearCoatRoughness 参数,指定光泽层的粗糙程度。

这里是和上面一样的按 metalness 划分的 roughness 网格,但可以设置 clearcoat 和 clearCoatRoughness 。

image-20230202163948431

构建速度

各种标准材质的构建速度从最快到最慢:MeshBasicMaterial ➡ MeshLambertMaterial ➡ MeshPhongMaterial ➡ MeshStandardMaterial ➡ MeshPhysicalMaterial。构建速度越慢的材质,做出的场景越逼真,但在低功率或移动设备上,你可能需要思考代码的设计,使用构建速度较快的材质。

3种材质有特殊用途

  1. ShadowMaterial

    用于获取阴影创建的数据。我们还没有介绍过阴影。等到我们介绍的时候,我们会使用这个材质来看看其背后的原理。

  2. MeshDepthMaterial

    染每个像素的深度,其中处在摄像机负近端面的像素其深度为0,处在摄像机负远端面的像素其深度为1。使用这个属性可以实现一些特殊效果,这在之后我们会再讨论

  3. MeshNormalMaterial

    会绘制视图空间法线(相对于摄像机的法线)。x 是红色, y 是绿色, 以及 z 是蓝色,所以朝向右边的东西是粉红色,朝向左边的是水蓝色,朝上的是浅绿色,朝下的是紫色,朝向屏幕的是淡紫色。

RawShaderMaterial 则是可以用来制作完全自定义的着色器,不需要three.js的帮助。

大多数材质都共享一堆由 Material 定义的设置。所有的设置都可以在文档中找到,但我们先来看看两个最常用的属性。

  1. flatShading:对象是否使用平面着色,默认为false。 image-20230202165309446

  2. side:要显示三角形的哪个面。默认值是 THREE.FrontSide,其他选项有 THREE.BackSide 和 THREE.DoubleSide(正反两面)。Three.js中,大多数3D对象可能都是不透明的实体,所以不需要绘制反面(面向实体内部的面)。设置 side 的最常见的原因是用于绘制平面或其他非实体对象,在这些对象中通常会看到三角形的反面。 image-20230202165417307

  3. material.needsUpdate 这个话题很少影响大多数three.js应用,但仅供参考......three.js会在使用材质时应用材质设置,其中 "使用 "意味着 "使用该材质的东西被渲染"。有些材质设置只应用一次,因为改变它们需要three.js做很多工作。在这种情况下,你需要设置 material.needsUpdate = true 来告诉 three.js 应用你的材质变化。当你在使用材质后再去更改设置,需要你去设置 needsUpdate的最常见的几种设置是:

    . flatShading . 添加或删除纹理 改变纹理是可以的,但是如果想从使用无纹理切换到使用纹理,或者从使用纹理切换到无纹理,那么你需要设置 needsUpdate = true。

    在从有纹理到无纹理的情况下,往往是使用1x1像素的白色纹理更好。

translateX 是沿着世界坐标还是局部坐标


这篇笔记整理自我自己的实践记录,如果做法有出入,或者你踩过别的坑,欢迎到留言板一起聊聊。

站内搜索

没有找到内容!