材质
三维场景中,可以 放置很多三维模型,一个三维模型Mesh是由一个几何体加上材质所构成的,几何体决定了模型的几何形状,材质决定了模型的外观属性,一个简单的理解就是一个西瓜的瓤决定了它的大小和圆扁,而西瓜皮决定了它外表啥样。
材质分为点、线、面(网格)、特殊、自定义材质
三维模型创建:
1.创建一个几何体
2.几何体指定相应材质
3.Mesh()方法,对三维模型进行构建
4.将三维模型加入到场景
# Material (opens new window)
材质基类
# 属性
# transparent (opens new window)
定义材质是否透明
# opacity (opens new window)
材质透明度
# side (opens new window)
定义将要渲染哪一面 - 正面,背面或两者
# vertexColors (opens new window)
是否启用顶点着色,如果修改顶点颜色的话,必须开启这个属性
# 方法
# onBeforeCompile (opens new window)
在编译shader程序之前立即执行的可选回调。此函数使用shader源码作为参数。用于修改内置材质。
# MeshBasicMaterial (opens new window)
基础网格材质(可以看作皮肤)
特点: 不反光,永远显示本身颜色
# 属性
# wireframe (opens new window)
将几何体渲染为线框
# color (opens new window)
材质的颜色
# map (opens new window)
颜色贴图,注意值类型是Texture (opens new window)
# alphaMap (opens new window)
alpha贴图是一张灰度纹理,用于控制整个表面的不透明度。(黑色:完全透明;白色:完全不透明)。 默认值为null。
// 导入纹理
const textureLoader = new THREE.TextureLoader();
const doorColorTexture = textureLoader.load("./textures/door/color.jpg");
// console.log(doorColorTexture);
//
// 添加物体
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1);
// 材质
const basicMaterial = new THREE.MeshBasicMaterial({
color: "#ffff00",
map: doorColorTexture,
});
2
3
4
5
6
7
8
9
10
11
12
13
14
# aoMap (opens new window)
环境遮挡,把环境的光挡住。注意:aoMap需要第二组UV
# aoMapIntensity (opens new window)
环境遮挡强度
// 导入纹理
const textureLoader = new THREE.TextureLoader();
const doorColorTexture = textureLoader.load("./textures/door/color.jpg");
const doorAplhaTexture = textureLoader.load("./textures/door/alpha.jpg");
const doorAoTexture = textureLoader.load(
"./textures/door/ambientOcclusion.jpg"
);
// 添加物体
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1);
// 材质
const basicMaterial = new THREE.MeshBasicMaterial({
color: "#ffff00",
map: doorColorTexture,
alphaMap: doorAplhaTexture,
transparent: true,
aoMap: doorAoTexture,
aoMapIntensity: 1,
// opacity: 0.3,
// side: THREE.DoubleSide,
});
basicMaterial.side = THREE.DoubleSide;
const cube = new THREE.Mesh(cubeGeometry, basicMaterial);
scene.add(cube);
// 给cube添加第二组uv
cubeGeometry.setAttribute(
"uv2",
new THREE.BufferAttribute(cubeGeometry.attributes.uv.array, 2)
);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
比如我们用这张图来进行环境遮挡
实现的效果,可以看到黑色线条遮挡部分,明显变黑了,这个门也更真实了
# MeshStandardMaterial (opens new window)
标准网格材质,基于PBR标准实现的材质,必须有灯光
# 属性
# displacementMap (opens new window)
置换贴图, 会影响网格顶点的位置,通过识别贴图的颜色,让顶点进行突出,所以顶点越多,突出效果会越细致。
// 导入纹理
const textureLoader = new THREE.TextureLoader();
const doorColorTexture = textureLoader.load("./textures/door/color.jpg");
const doorAplhaTexture = textureLoader.load("./textures/door/alpha.jpg");
const doorAoTexture = textureLoader.load(
"./textures/door/ambientOcclusion.jpg"
);
//导入置换贴图
const doorHeightTexture = textureLoader.load("./textures/door/height.jpg");
// 添加物体,注意后面三个参数,因为置换贴图实际是在位移顶点,增加顶点数量很重要,顶点越多越细腻,不加的话,顶点少也就没啥突出效果,
const cubeGeometry = new THREE.BoxBufferGeometry(1, 1, 1, 100, 100, 100);
// 材质
const material = new THREE.MeshStandardMaterial({
color: "#ffff00",
map: doorColorTexture,
alphaMap: doorAplhaTexture,
transparent: true,
aoMap: doorAoTexture,
aoMapIntensity: 1,
displacementMap: doorHeightTexture,
displacementScale: 0.1,
});
material.side = THREE.DoubleSide;
const cube = new THREE.Mesh(cubeGeometry, material);
scene.add(cube);
// 给cube添加第二组uv
cubeGeometry.setAttribute(
"uv2",
new THREE.BufferAttribute(cubeGeometry.attributes.uv.array, 2)
);
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
最后实现的这个门,根据置换贴图中,白色程度不同,突出程度也不同,整体看起来更加真实了。
# displacementScale (opens new window)
配合置换贴图,规定顶点最大位移程度,默认突出程度是1(可以看作长度)。一般都要修改这个突出程度
# roughness (opens new window)
修改材质粗糙程度,也就决定了漫反射的程度。如果还提供roughnessMap,则两个值相乘。
# roughnessMap (opens new window)
贴图方式,通过识别贴图的 去改变材质粗糙程度,贴图上越灰色的地方越粗糙,这样就可以随意设置哪部分粗糙,哪部分光滑了。
// 导入粗糙度贴图
const roughnessTexture = textureLoader.load("./textures/door/roughness.jpg");
// 材质
const material = new THREE.MeshStandardMaterial({
// ...
roughness: 1,
roughnessMap: roughnessTexture,
// ...
});
2
3
4
5
6
7
8
9
可以看到金属部分已经比较粗糙了
# metalness (opens new window)
材质与金属的相似度,如果还提供了metalnessMap,则两个值相乘。
# metalnessMap (opens new window)
金属度贴图,越白金属度越强
// 导入金属贴图
const metalnessTexture = textureLoader.load("./textures/door/metalness.jpg");
// 材质
const material = new THREE.MeshStandardMaterial({
// ...
metalness: 1,
metalnessMap: metalnessTexture,
// ...
});
2
3
4
5
6
7
8
9
可以看到金属部分,与金属更相似了
# normalMap (opens new window)
法线贴图,上面各种贴图完成以后,有一点不足之处,都是一个镜面,没有凹凸不平的感觉,这时候就要用到法线贴图,改变反射方向,让反射更真实。
贴图中每种颜色都代表不同的反射方向。
// 导入法线贴图
const normalTexture = textureLoader.load("./textures/door/normal.jpg");
// 材质
const material = new THREE.MeshStandardMaterial({
// ...
normalMap: normalTexture,
// ...
});
2
3
4
5
6
7
8
此时就有这种凹凸不平的感觉了
# PointsMaterial (opens new window)
点材质
# 属性
可以设置点样式、点大小、点颜色、透明度等
# sizeAttenuation (opens new window)
点的大小是否因相机深度而衰减,相机越远看到的越小,相机越近看到的越大,如果为false,相机近远,看到的大小都是一样的。(仅限透视相机)
# map (opens new window)
给点设置贴图
# alphaMap (opens new window)
开启透明度,像下面这张图,如果导入贴图不开透明度的话,四周黑色部分会对后面产生遮挡。
# transparent (opens new window)
定义材质是否透明,想开启alphaMap,必须先开这个属性,材质透明是前提。
# depthWrite (opens new window)
深度写入,如果开了深度写入,前面的会遮挡后面的,不管透不透明。 可以看到,导入这样一张纹理贴图,也设置了透明,黑色部分虽然透明了,但还是遮挡住了后面的渲染。 禁止掉深度写入后,可以看到,后面不再被遮挡,都渲染出来了。但现在重合之后,渲染看起来很别扭,这时候我们就要修改blending (opens new window)混合模式了
# blending (opens new window)
比如上面开启深度写入后,两个重合的点怎么去混合。我们将混合模式改为THREE.AdditiveBlending
叠加效果,这样就完美了