之前讲的都是几何体 Geometry 的相关知识,本文说一说"材质 Material "。
通过之前的代码可以知道,对于一些封装好的模型,three 提供了专门的方法。比如点模型的材质方法:
javascript
const material = new THREE.PointsMaterial({
color: new THREE.Color('orange'),
size: 10
});
线模型的材质方法:
javascript
const material = new THREE.LineBasicMaterial({
color: new THREE.Color('orange')
});
还有网格模型的材质方法(不受光照影响):
javascript
const material = new THREE.MeshBasicMaterial(({
color: new THREE.Color('orange'),
wireframe: true,
}));
同一种几何体,加上不同的材质,就可以渲染出不同的效果。
下面我们依旧是学一下 Material 的通用属性:color 颜色、map 颜色贴图 。
javascript
import * as THREE from 'three';
const geometry = new THREE.PlaneGeometry(100, 100);
const material = new THREE.MeshBasicMaterial(({
color: new THREE.Color('orange')
}));
const mesh = new THREE.Mesh(geometry, material);
console.log(mesh);
export default mesh;
这是一个经典的网格模型,设置了color。我们再来看下控制台打印:

mesh 除了 geometry 属性,也有 material 属性。
material.color 是一个 Color 对象,我们可以用各种 get 方法拿到它的颜色值:
javascript
console.log(color.getHSL());
console.log(color.getHex());
console.log(color.getRGB());
console.log(color.getHexString());
console.log(color.getStyle());
还可以用各种 set 方法修改颜色值:
javascript
color.setStyle('blue');

如果我们希望材质有一定透明度,也可以用 transparent :
javascript
constmaterial =newTHREE.MeshBasicMaterial(({
color:newTHREE.Color('orange'),
transparent:true,
opacity:0.5
}));
但也有一些时候,我们不是要设置颜色,而是要设置一张图片。这时候可以用 map 属性:
javascript
import * as THREE from 'three';
const loader = new THREE.TextureLoader();
const texture = loader.load('./haha.png');
const geometry = new THREE.SphereGeometry(100);
const material = new THREE.MeshBasicMaterial({
map: texture
});
const mesh =new THREE.Mesh(geometry, material);
export default mesh;
SphereGeometry 是球体:

如果这时候我们再在 MeshBasicMaterial 中加入:
javascript
color:newTHREE.Color('orange'),

设置平面物体 PlaneGeometry 效果也是一样:
javascript
import * as THREE from 'three';
const loader = new THREE.TextureLoader();
const texture = loader.load('./haha.png');
texture.wrapS=THREE.RepeatWrapping
texture.wrapT=THREE.RepeatWrapping
texture.repeat.set(3,3);
const geometry = new THREE.PlaneGeometry(1000, 1000);
const material = new THREE.MeshBasicMaterial({
map: texture
});
const mesh =new THREE.Mesh(geometry, material);
export default mesh;
不过在设置平面物体时一定要考虑一点:相机视角!
如果你在调用上面这个代码后相机那里还按之前的这么写:
javascript
const camera = new THREE.PerspectiveCamera(60, width / height, 1, 1000);
根据上上一片文章中说到的"近截面远截面"的知识,你得到的大概率是一个很有倾斜角度、展示不完全的图片,但是如果我们让物体远一点:
javascript
const camera = new THREE.PerspectiveCamera(60, width / height, 1, 10000);
这样就不会被裁剪了。所以你经常看到代码里近裁截面设置了 0.1,远裁截面设置了好几万,就是为了让视椎体的范围能覆盖全部场景。
我们还可以修改相机的位置达到效果:
javascript
camera.position.set(90, 200, 1000);
那如果我们想让图片在水平/垂直方向重复呢?直接设置在水平(wrapS)和竖直(wrapT)方向重复,然后设置重复次数就可以了:
javascript
const texture = loader.load('./haha.png');
texture.wrapS=THREE.RepeatWrapping
texture.wrapT=THREE.RepeatWrapping
texture.repeat.set(3,3);

写到这我发现一件事,这贴图怎么这么泛白,原图是有很深的颜色的。于是我找到了这个方法:
javascript
texture.colorSpace=THREE.SRGBColorSpace;
修改图片对象的颜色空间。
但是直到这里,图片依然"失真",这里说的不是图片本身和原图的真假,而是和现实的真假。因为我们是有"光照"的,如果是模型线条本身也是可以的,但这里是贴图, map 只是把贴图的颜色加上去了,没有做进一步的处理,如果你想要那种受环境光影响的凹凸感,需要设置 aoMap 属性:
javascript
const material = new THREE.MeshBasicMaterial({
map: texture,
aoMap: texture // 重点!!!
});