three.js学习笔记(二)——textures纹理
什么是纹理Texture
简单来说,纹理就是覆盖几何体表面的图像。不同的纹理类型具有不同的效果。
纹理加载器TextureLoader
// 初始化一个纹理加载器,然后用.load()加载纹理贴图
const textureLoader = new THREE.TextureLoader()
const colorTexture = textureLoader.load('/textures/door/color.jpg')
// 之后使用纹理来创建材质
const material = new THREE.MeshBasicMaterial({ map:colorTexture })
注:一个纹理加载器可以加载多个纹理
在图片路径后还可以再添加三个回调函数
const colorTexture = textureLoader.load(
'/textures/door/color.jpg',
()=>{ //加载完成时将调用
console.log('load');
},
()=>{ //加载过程中进行调用(一般不会用到)
console.log('progress');
},
()=>{ //加载出错时调用
console.log('error');
}
)
加载管理器LoadingManager
刚才我们只用了一种纹理加载器加载了一个纹理,但如果后面我们再加载一些其他的纹理比如手机纹理、墙面纹理等等许多纹理,这时可能你想要知道所有这些纹理的全局加载进度或者当全部纹理加载完成时有消息提示,因此可以使用LoadingManager使这些加载事件相互关联
//初始化加载管理器
const loadingManager = new THREE.LoadingManager()
loadingManager.onStart = () => {
console.log('Started loading file');
}
loadingManager.onProgress = () =>{
console.log('onProgress');
}
loadingManager.onLoad = () => {
console.log('Loading complete!');
}
loadingManager.onError = () =>{
console.log('onError');
}
// 使用加载管理器loadingManager来跟踪 TextureLoader 的加载进度流程
const textureLoader = new THREE.TextureLoader(loadingManager)
//用.load()加载纹理贴图
const colorTexture = textureLoader.load('/textures/door/color.jpg')
const checkerboard1024Texture = textureLoader.load('/textures/checkerboard-1024x1024.png')
const checkerboard8Texture = textureLoader.load('/textures/checkerboard-8x8.png')
const minecraftTexture = textureLoader.load('/textures/minecraft.png')
观察控制台输出情况,说明共有四个纹理贴图被加载
UV贴图展开
当把立方缓冲几何体切换为其他类型几何体时可以看到,纹理以不同的方式拉伸或挤压以覆盖几何体,这就叫做UV贴图展开。就像展开折纸或糖果包装纸使其平整一样,每个顶点在平面上都有一个二维坐标(通常为正方形)
const geometry = new THREE.TorusBufferGeometry(1, 0.35, 32,100)
可以通过geometry.attributes.uv
查看几何体的二维坐标
console.log(geometry.attributes.uv)
可以看到立方几何体的uv坐标数据数组,总计2x4x6=48个数据,这些数据每俩个为一组构成了每个面每个点的坐标数据,这些坐标会帮助我们将纹理图片精确覆盖到几何体上。
纹理转换
// 纹理在表面上重复多少次
// repeat属性只是一个Vector2二维向量
colorTexture.repeat.x = 2
colorTexture.repeat.y = 3
可以看到贴图横向变为原先的二分之一,纵向变为原先的三分之一,但并未有重复
这是因为默认情况下,纹理不会重复,其最后一个像素会被拉伸。此情况可以通过设置纹理贴图的 wrapS
和 wrapT
属性,其分别定义了水平和垂直方向上纹理的包裹方式,来解决上图问题。
// 如果每个方向上的repeat属性都设置大于1
// 则相应的wrap参数也应设置包裹模式为THREE.RepeatWrapping或THREE.MirroredRepeatWrapping以实现所需的平铺影响
colorTexture.wrapS = THREE.RepeatWrapping
colorTexture.wrapT = THREE.RepeatWrapping
//纹理的偏移量(一样是Vector2二维向量)
colorTexture.offset.x = 0.5
colorTexture.offset.y = 0.5
//纹理旋转角度
colorTexture.rotation = Math.PI / 4 //纹理贴图旋转45度
默认中心点位于原点位置,是绕原点旋转
若要改为以贴图中心旋转,则需以下设置改变中心点位置
//旋转后会发现贴图是绕着原点旋转的,若要设置为绕贴图中心旋转则需如下设置
colorTexture.center.x = 0.5
colorTexture.center.y = 0.5
过滤和Mip映射
当我们以下图方式观察该立方几何体的顶部时,可以看到纹理变得模糊不清,这就是由于过滤FILTERING和mip映射MIPMAPPING造成的
mip映射(mipmapping)是一种技术,它包括一次又一次地创建半个较小版本的纹理,直到得到1x1纹理。
所有这些纹理变化都会发送到GPU,GPU将自动选择最合适的纹理版本。所有的这些都已经由THREE.js和GPU处理,但是我们可以选择不同的过滤算法
缩小滤镜(Minification Filters)
当纹理的像素小于渲染的像素时触发该滤镜,如下图。原本纹理贴图像素如上面的图片一样大,当但我们把相机往后移动,可以看到贴图被缩小挤压到一小块渲染区域里面,这时就会触发缩小滤镜,换句话说就是原纹理贴图对于几何体表面太大了,因此此时用的纹理贴图可能就是较小版本的纹理如64x64,32x32。
对于上面这种情况,我们可以通过为纹理的minFilter
属性设置下面任意一个值来更改纹理的缩小滤镜,这里我们选择NearestFilter
// 这些常量用于纹理的minFilter属性,它们定义了当被纹理化的像素映射到大于1纹理元素(texel)的区域时,将要使用的纹理缩小函数。
THREE.NearestFilter
THREE.NearestMipmapNearestFilter
THREE.NearestMipmapLinearFilter
THREE.LinearFilter
THREE.LinearMipmapNearestFilter
THREE.LinearMipmapLinearFilter //默认值
// NearestFilter返回与指定纹理坐标最接近的纹理元素的值
colorTexture.minFilter = THREE.NearestFilter
从下图可以看出当纹理的minFilter
属性设置为NearestFilter后,像素点更加锐利以及会闪烁
将纹理贴图换为一张1024x1024的效果更加明显。这种图案被叫做干涉条纹/莫尔条纹Moire Pattern
放大滤镜(Magnification Filters)
与缩小滤镜相反。当纹理的像素大于渲染的像素时触发该滤镜。我们换一张8x8的纹理贴图
原本的图片大小是这样的,当进行渲染时图片变成了上图的样子,因为像素被拉伸混合到一块
对于上面这种情况,我们可以通过为纹理的magFilter
属性设置为NearestFilter来更改纹理的放大滤镜。可以看出变得非常锐利,黑白交界处不再混合。
如果使用NearestFilter能够使你获得更加满意的结果,那就用吧。当纹理的minFilter属性使用NearestFilter时,我们可以不需要再mip映射了,可以通过以下代码为纹理停用mipmapping,使得GPU不再处理mip映射
//如果不在乎远处物品效果如失真之类的,纹理的minFilter属性使用 NearestFilter时可以停用mipmapping以获得更好性能,根据实际项目而定
colorTexture.generateMipmaps = false
纹理格式和优化
从网上找纹理文件时,需要注意三个点
纹理文件的大小
选择正确的纹理文件类型。
jpg失真压缩但更小,png无损压缩但更大
纹理文件的尺寸
不论图片有多大,纹理的每个像素都会被存储在GPU上,不能一下子传送过于庞大数量的尺寸过大的纹理给GPU,需要尽可能的缩小纹理的尺寸
纹理文件的数据
纹理支持透明度,但jpg文件不支持,因此如果需要有透明度的图片最好使用png文件。
如果使用的是普通纹理,希望得到精确的值,那就不应该用有损压缩文件,还是最好使用png文件。、
有时我们可以通过分别使用红色、绿色、蓝色和alpha通道将不同的数据组合成一个纹理。
纹理资源网站
https://www.poliigon.com/
https://3dtextures.me/
https://www.arroway-textures.ch/
更多推荐
所有评论(0)