定义:纹理图片(或canvas/video等)映射到物体表面,或者作为反射、折射贴图,也就是物体的皮肤。
1、纹理贴图分类
map
:颜色贴图,存储颜色信息bumpMap
:凹凸贴图,性能贴图,也称为高度贴图,性能开销比较大,会移动表面纹理的可见区域,从而实现表面遮挡效果mormalMap
:法线贴图,通过RGB三个分量分别表示向量的xyz三个方向,并且通过图片保留几何体表面的几何细节aoMap
:环境贴图,AO贴图,模拟物体之间所产生的阴影,在不打光的时候增加体积感roughnessMap
:光滑度贴图,该纹理的绿色通道用于改变材质的粗糙度。alphaMap
:透明度贴图,是一张灰度纹理,用于控制整个表面的不透明度。(黑色:完全透明;白色:完全不透明)lightMap
:光照贴图- …
2、纹理贴图原理
在光栅化过程中使用双线性插值计算每个像素的纹理坐标(UV)
在纹素数组中查找纹理坐标(使用最近的或四个最近的线性插值)
使用纹理的颜色作为像素的颜色,或者组合纹理和像素的颜色
3、加载贴图
3.1 使用image加载
const img = new Image();
const texture = new THREE.Texture(img);
img.src =
'/public/textures/Wood_Ceiling_Coffers_003/Wood_Ceiling_Coffers_003_basecolor.jpg';
img.onload = () => {
console.log('loaded texture', texture);
texture.needsUpdate = true; // 加载前纹理为空,加载成功之后需要告诉js更新,下次tick就会重新读取对象
};
3.2 使用load加载
支持成功失败的回调、但是不支持加载中的回调
// 跨域 setCrossOrigin('anonymous')
this.texture = loader.setCrossOrigin('anonymous').load(
// 资源URL
'/public/textures/Wood_Ceiling_Coffers_003/Wood_Ceiling_Coffers_003_basecolor.jpg',
// onLoad回调
(texture) => {
texture.needsUpdate = true;
},
// 目前暂不支持onProgress的回调
undefined,
// onError回调
function (err) {
console.error('An error happened.');
}
);
3.3 支持加载中回调
const texture = new THREE.TextureLoader()
.setCrossOrigin('Anonymous') // 设置允许跨域
.load('/public/textures/Material_1741/basecolor.jpg', // 这里换成了绝对路径
// onLoad回调
() => {
console.log('load');
},
// process 回调, r84+ 被弃用
() => {
console.log('process');
},
// onError回调
(error) => {
console.log('error', error);
},
);
// 使用 loadingManager 监控加载情况
const loadingManager = new THREE.LoadingManager();
loadingManager.onStart = (url, itemsLoaded: Index, itemsTotal: Number) => {
console.log('start', url, itemsLoaded, itemsTotal);
};
loadingManager.onLoad = () => {
console.log('loaded');
};
loadingManager.onProgress = (url, itemsLoaded: Index, itemsTotal: Number) => {
console.log('process', url, itemsLoaded, itemsTotal);
};
loadingManager.onError = (url) => {
console.log('error', url);
};
const textureLoader = new THREE.TextureLoader(loadingManager);
const texture = textureLoader.load('/public/textures/Material_1741/basecolor.jpg',
() => {
console.log('load');
},
// process 回调, r84+ 被弃用
undefined,
// onError回调
(error) => {
console.log('error', error);
},
);
console.log(texture);
4、物体添加纹理
其他属性都会影响纹理的渲染效果
const material = new THREE.MeshLambertMaterial({
color: 0x1890ff,
map: this.texture, //纹理
transparent: true,
opacity: 0.5,
wireframe: true,
});
每个面设置不同的贴图
// 每个面设置不同的贴图
const materials = [];
for (let i = 0; i < boxGeometry.groups.length; i++) {
// 纹理贴图
const texture = this.textureLoader.setCrossOrigin('anonymous').load(
// 资源URL
`/public/textures/fullscreen/0${i + 1}.jpg`
);
materials.push(
new THREE.MeshBasicMaterial({
map: texture,
})
);
}
const box = new THREE.Mesh(boxGeometry, materials);
一个物体设置多个贴图纹理
const material = new THREE.MeshLambertMaterial({
map: colorTexture,
aoMap: aoTexture,
bumpTMap: bumpTexture,
displacementMap: bumpTexture,
normalMap: normalTexture,
roughnessMap: roughnessTexture,
});
mipmap:多级渐远纹理 texture.magFilter = THREE.NearestFilter;
优点:
1.质里高:避免了在远距离情况下的采样频率低和数据频率高造成的失真和摩尔纹
2.性能好: 避免了不使用Mipmap下距离远时采样频率低和数据频率高而照成 texture cache命中率不高(相邻pixel采样Texel时uv相差比较大)使性能下降。
缺点:
占用显存,可使用ue的纹理流缓存优化(IO换显存)。
5、不同的纹理贴图
5.1 AO贴图
const boxMaterial = new THREE.MeshBasicMaterial({
map: this.texture,
aoMap: this.aoTexture, //在纹理较暗的地方添加阴影
aoMapIntensity: 1, //环境遮挡效果的强度。默认值为1。零是不遮挡效果
});
gui.add(this.box.material, 'aoMapIntensity', 0, 1, 0.1);
5.2 凹凸贴图
const boxMaterial = new THREE.MeshLambertMaterial({
map: this.texture,
// aoMap: this.aoTexture, //在纹理较暗的地方添加阴影
// aoMapIntensity: 1,
bumpMap: this.bumpTexture,
bumpScale: 10,
});
5.3 位移贴图
const boxMaterial = new THREE.MeshLambertMaterial({
map: this.texture,
aoMap: this.aoTexture, //在纹理较暗的地方添加阴影
aoMapIntensity: 1,
// bumpMap: this.bumpTexture,
// bumpScale: 10,
displacementMap: this.bumpTexture,
displacementBias: 0, //位移贴图在网格顶点上的便宜量
displacementScale: 0, //位移贴图对网格的影响成都(黑色无位移,白色是最大的位移)
});
5.4 法线贴图
对于有高光材质的效果比较明显,不会改变曲面的实际形状,只会改变光照
normalMap: this.normalTexture,
gui.add(this.box.material.normalScale, 'x', 0, 1, 0.1);
gui.add(this.box.material.normalScale, 'y', 0, 1, 0.1);
5.5 光滑度贴图
0表示平滑的镜面反射,1表示完的漫反射
roughnessMap: this.roughnessTexture,
gui.add(this.box.material, 'roughness', 0, 1, 0.1);
5.6 金属贴图
非金属材质使用0.0,金属材质使用1,中间值经常代表表面生锈
metalnessMap: this.metalTexture,
gui.add(this.box.material, 'metalness', 0, 1, 0.1);