three.js学习(8)

315 阅读4分钟

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实例,实例包含totalloaded字节。

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中我们是可以读到的。它拥有三个参数,这个很重要

  1. 文件的路径url。
  2. 现在加载到第几张图片
  3. 一共有多少张图片

那么我们同样写好三个函数

 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的那四张图。

这样执行后的效果就如下图所示:

LoadingManager演示图.png

如果放到游戏的加载界面,搞个进度条,是不是就有内味了QAQ。