13.设置粗糙度与粗糙度贴图
.roughness :材质的粗糙程度。0.0表示平滑的镜面反射。1.0表示完全漫反射。默认值为1.0,如果还提供roughnessMap,则两个值相乘。
.roughnessMap :该纹理的绿色通道用于改变材质的粗糙度。
//材质
const standardMaterial = new THREE.MeshStandardMaterial({
roughness: 0,
})
这样会看到一个非常光滑的镜面反射。
那么这样的,改变的是整个的材质的光滑程度。当然如果我们只想要部分区域光滑的话,我们可以设置我们的粗糙度贴图。一样是黑白图片,那么越黑就越粗糙,越白呢就越光滑。
//导入粗糙度贴图
const roughnessTexture = textureLoader.load("./textures/ao.jpg")
//材质
const standardMaterial = new THREE.MeshStandardMaterial({
roughness: 1,
roughnessMap: roughnessTexture,
})
14.设置金属度与金属贴图
.metalness :材质与金属的相似度。非金属材质,如木材或石材,则使用0.0。金属使用1.0。通常没有中间值。默认值为0.0。中间值可用于生锈金属的外观。如果还提供metalnessMap(金属贴图),则两个值相乘。
.metalnessMap :金属贴图,还是一张黑白图,那么这里面呢,越白的部分越接近金属,越黑呢就越不是金属。
//材质
const standardMaterial = new THREE.MeshStandardMaterial({
metalness: 1,
})
这样会看到一个非常金属材质的一个物体。
那么同样的我们可以加上我们的金属贴图,来只让部分位置金属化。
//导入金属贴图
const metalnessTexture = textureLoader.load("./textures/ao.jpg")
//材质
const standardMaterial = new THREE.MeshStandardMaterial({
metalness: 1,
metalnessMap: metalnessTexture,
})
但是呢,我们会发现一个问题,我们的物体在反射光线的时候,都是直接反射了,并没有凸显出凹凸不平的感觉。因此呢就需要我们下面的法线贴图来帮助我们。
15.法线贴图应用
法线贴图有各种的颜色,而颜色代表着方向的向量。那么光通过跟这个向量的计算呢,就会知道自己要怎么去折射。
//导入法线贴图
const normalTexture = textureLoader.load("./textures/ao.jpg")
//材质
const standardMaterial = new THREE.MeshStandardMaterial({
normalMap: normalTexture,
})
16.如何获取各种类型纹理贴图
介绍几个网站:
poliigon.com
3dtextures.me
arroway-textures.ch
可以注册一个虚幻引擎的账号,然后在软件Quixel Bridge中登录就可以全部免费使用。
17.纹理加载进度情况
像我们在玩游戏的时候,通常都会有一个加载的时间,等他把纹理都加载完了,再进行一个统一的实现。那我们要如何知道它的加载情况呢,这里就要用到three.js的TextureLoader(之前学导入纹理的时候用的纹理加载器)了。
我们之前用的它的一个方法是:
.load(url:String,onLoad:Function,onProgress:Function,onError:Function) :
url - 文件的URL或者路径,也可以为Data URL。之前只导入了图片,所以只是用了这个参数
onLoad - 加载完成时将调用。回调参数为将要加载的texture。
onProgress - 将在加载过程中进行调用。参数为XMLHttpRequest实例,实例包含total和loaded字节。
onError - 在加载错误时被调用。
那我们这里先演示单张图片的加载进度:
//先分别设置一下三种方法
const onLoad = (e) => {
console.log(e, '加载完毕');
}
const onProgress = (e) => {
console.log(e, '加载进度');
}
const onError = (e) => {
console.log(e, '加载错误');
}
//导入纹理
const textureLoader = new THREE.TextureLoader()
const stoneColorTexture = textureLoader.load("./textures/stone.jpg", onLoad, onProgress, onError)
如果没有显示进度的话,是因为就一张小图片,加载非常地快,所以不会有onProgress。
但是呢,单张的管理一般是不会的,一般来说都是多张的图我们需要管理。那么three.js有这么一个专门的管理控制器。
LoadingManager :其功能是处理并跟踪已加载和待处理的数据。如果未手动设置加强管理器,则会为加载器创建和使用默认全局实例加载器管理器。
它呢与上面的 .load的后三个回调函数。但有区别。这样打比方:
这下面我导入了四张图片:
const stoneColorTexture = textureLoader.load("./textures/stone.jpg")
const stoneAoTexture = textureLoader.load("./textures/ao.jpg")
//导入金属贴图
const metalnessTexture = textureLoader.load("./textures/ao.jpg")
//导入法线贴图
const normalTexture = textureLoader.load("./textures/ao.jpg")
那么每加载好一张图片,就会调用一次LoadingManager.onProgress( ) 。直到所有图片都加载完了才会调用LoadingManager.onLoad( ) 。但是,它是怎么知道加载了多少图片的呢,因为在onProgress中我们是可以读到的。它拥有三个参数,这个很重要:
- 文件的路径url。
- 现在加载到第几张图片
- 一共有多少张图片
那么我们同样写好三个函数
const onLoad = () => {
console.log('全部加载完毕');
}
const onProgress = (url, num, total) => {
console.log('正在加载图片', url);
console.log('现在是第 ', num, ' 张图片');
console.log('总共有', total, '张图片');
console.log('总进度为:', `${(num/total*100).toFixed(2)}%`);
}
const onError = (e) => {
console.log(e, '加载错误');
}
然后在设置纹理加载器的时候加到里头去:
//导入纹理
const textureLoader = new THREE.TextureLoader(loadingManager)
这样后面导入的图片就都会被加入到这个管理控制器里面去,也就是上面load的那四张图。
这样执行后的效果就如下图所示:
如果放到游戏的加载界面,搞个进度条,是不是就有内味了QAQ。