加载纹理
请注意three.js r84遗弃了TextureLoader进度事件。对于支持进度事件的TextureLoader , 请参考this thread。
// 纹理
loadTextures () {
// -----------------方法一
// const img = new Image()
// // 创建纹理
// const texture = new THREE.Texture(img)
// img.onload = function () {
// console.log(texture);
// // 更新纹理
// texture.needsUpdate = true
// }
// img.src = '/src/assets/textures/Wood_Ceiling_Coffers_003_basecolor.Cu38ry6v.jpg';
// this.texture = texture;
// ------------------方法二
// setCrossOrigin('anonymous') 跨域方法
// const textLoader = new THREE.TextureLoader()
// this.texture = textLoader.setCrossOrigin('anonymous').load(
// // this.texture = textLoader.load(
// // 'https://3dbooks.netlify.app/assets/Wood_Ceiling_Coffers_003_basecolor.Cu38ry6v.jpg',
// '/src/assets/textures/Wood_Ceiling_Coffers_003_basecolor.Cu38ry6v.jpg',
// // onLoad回调
// function (texture) {},
// null,
// // onError回调
// (error) => {
// console.log('error', error);
// }
// )
// 方法三
const manager = new THREE.LoadingManager()
manager.onStart = function( url, itemsLoaded, itemsTotal) {
console.log( 'Start loading file: '+url +'.\nLoaded' + itemsLoaded+'of '+ itemsTotal+'files.');
}
manager.onLoad = function() {
console.log('Loading complete !');
}
manager.onProgress = function( url, itemsLoaded, itemsTotal ){
console.log('Loading file: '+ url+ '.\Loaded ' +itemsLoaded+ ' of '+itemsTotal+' files. ');
}
manager.onError = (url) =>{
console.log('There was an error loading '+ url);
}
const textureLoader = new THREE.TextureLoader(manager)
const texture = textureLoader.load('/src/assets/textures/Wood_Ceiling_Coffers_003_basecolor.Cu38ry6v.jpg')
this.texture = texture
},
// 创建立方体材质
const material = new THREE.MeshLambertMaterial({
// color: 0x1890ff,
map: this.texture
})
加载6个面的纹理图
const cubeTextureLoader = new THREE.CubeTextureLoader().load([
'1.jpg', '2.jpg', '3.jpg', '4.jpg', '5.jpg', '6.jpg',
])
- 不是纹理图片尺寸越大越好,必要时对图片进行压缩,如,图片尺寸,图片1M->500kb。
- 纹理占用计算: 宽度 * 高度 * 4 * 1.33字节的内存,需要考虑压缩。
- 添加几何体的分段数(即一个面上的添加三角形密度),可在物体上,展现纹理的高度、深度、坡度等细节。
利用mipmap解决纹素问题
mipmap优缺点:
- 优点:
- 质量高;避免在远距离情况下,采样频率低+数据频率高,造成失真和摩尔纹。
- 性能好:避免不使用Mimap下,距离远时,采样频率低+数据频率高,造成 texture cache 命中率不高(相邻Pixel 采样 Texel时,uv相差比较大),让性能下降。
- 缺点:
- 占用显存,可使用ue 的纹理流 缓存优化(IO换显存)。
Texture纹理对象中,magFilter 属性,可解决纹理图像素极小,呈现出模糊失真的情况。配置代码:texture.magFilter = THREE.NearestFilter;
附加AO贴图
ao贴图在不打光时,模拟体积感;ao贴图不受任何光照影响,仅计算物体间的距离。计算球体的AO贴图时,每个像素根据物体的法线,发射出光线,这个光碰触到物体时,就会产生反馈,标记附近有物体,即呈现黑色。
- 在纹理较暗的地方添加阴影,必须设置第二组UV才生效。
boxGeometry.setAttribute('uv2', new THREE.BufferAttribute(geometry.attributes.uv.array, 2))
bumpMap凹凸贴图只影响光照效果,不影响几何模型。displacementMap位移贴图取代bumpMap凹凸贴图。
颜色纹理+AO+位移贴图呈现立体感
// 添加全局光照
const ambientLight = new THREE.AmbientLight(0xffffff, 0.7)
// 创建立方体对象
createObjects () {
// 加载纹理
const colorTexture = this.textureLoader.load('/src/assets/textures/1.jpg') // 颜色纹理
const aoTexture = this.textureLoader.load('/src/assets/textures/2.jpg') // ao纹理
// 凹凸贴图只影响光照效果,不影响几何模型
const bumpTexture = this.textureLoader.load('/src/assets/textures/3.jpg') // 凹凸纹理
// 创建立方体的几何体
const geometry = new THREE.BoxGeometry(2, 2, 2)
// 创建立方体材质
const material = new THREE.MeshLambertMaterial({
map: colorTexture,
})
// 创建3D物体对象
const mesh = new THREE.Mesh(geometry, material);
mesh.position.x = -2;
// 立方体
const boxGeometry = new THREE.BoxGeometry(2, 2, 2, 64, 64, 64)
const boxMaterial = new THREE.MeshLambertMaterial({
map: colorTexture,
aoMap: aoTexture,
aoMapIntensity: 0.8,
displacementMap: bumpTexture,
// displacementBias: 0, // 位移贴图在网格顶点上的偏移量
// displacementScale: 0, // 位移贴图对网格的影响度(黑色无位移,白色是最大位移)
})
const box = new THREE.Mesh(boxGeometry, boxMaterial)
// 手动添加第二个 uv属性
box.position.x = 1;
this.scene.add(mesh, box)
this.mesh = mesh;
this.box = box
},
// datGui调试器
gui.add(_this.box.material, 'aoMapIntensity', 0, 1, 0.1)
gui.add(_this.box.material, 'displacementBias', 0, 1, 0.1)
gui.add(_this.box.material, 'displacementScale', 0, 1, 0.1)
法线贴图(需要光照)
法线贴图不会改变曲面的形状,只会改变光照的效果。阴影细节,使纹理更有立体质感。
// 创建光照
createLights () {
// 添加全局光照
const ambientLight = new THREE.AmbientLight(0xffffff, 0.7)
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.7)
// 改变光照方向
directionalLight.position.set(1, 2, 4)
this.scene.add(ambientLight, directionalLight);
},
// 创建立方体对象
createObjects () {
// 加载纹理
const colorTexture = this.textureLoader.load('/src/assets/textures/1.jpg') // 颜色纹理
const normalTexture = this.textureLoader.load('/src/assets/textures/4.jpg') // 法线纹理
// 创建立方体的几何体
const geometry = new THREE.SphereGeometry(2, 64, 64)
// 创建立方体材质
const material = new THREE.MeshPhongMaterial({
map: colorTexture,
})
// 创建3D物体对象
const mesh = new THREE.Mesh(geometry, material);
mesh.position.x = -3;
// 立方体
const boxGeometry = new THREE.SphereGeometry(2, 64, 64)
const boxMaterial = new THREE.MeshPhongMaterial({
map: colorTexture,
normalMap: normalTexture, // 法线贴图
})
const box = new THREE.Mesh(boxGeometry, boxMaterial)
box.position.x = 3;
this.scene.add(mesh, box)
this.mesh = mesh;
this.box = box
},
gui.add(_this.box.material.normalScale, 'x', 0, 1, 0.1).onChange(val =>{
_this.box.material.normalScale = new THREE.Vector2(val, _this.box.material.normalScale.y)
})
gui.add(_this.box.material.normalScale, 'y', 0, 1, 0.1).onChange(val => {
_this.box.material.normalScale = new THREE.Vector2(_this.box.material.normalScale.x, val)
})
光滑度贴图
反映材质的光滑程度,可模拟漫反射、镜面反射。roughness属性值越大,光点涣散,材质更粗糙(漫反射);越小,材质更光滑(镜面反射)。使用的是MeshStandardMaterial材质。
纹理属性
在css中有repeat平铺属性,在three.js中叫纹理回环。
请注意:纹理中图像的平铺,仅有当图像大小(以像素为单位)为2的幂(2、4、8、16、32、64、128、256、512、1024、2048、……)时才起作用。 宽度、高度无需相等,但每个维度的长度必须都是2的幂。 这是WebGL中的限制,不是由three.js所限制的。
colorTexture.repeat.set(2, 2) // 纹理回环
// RepeatWrapping 阵列 ClampToEdgeWrapping 默认值 MirroredRepeatWrapping 镜像
colorTexture.wrapS = THREE.RepeatWrapping // 水平方向上的纹理效果
colorTexture.wrapT = THREE.RepeatWrapping // 垂直方向上的纹理效果
colorTexture.offset = new THREE.Vector2(0.5, 0.5) // 纹理偏移
colorTexture.rotation = Math.PI / 12 // 旋转 正值=逆时针 负值=顺时针
colorTexture.center.set(0.5, 0.5) // 设置纹理的旋转中心,默认(0,0), (0.5, 0.5)是纹理的中心