最近一有空就在学Threejs,上一篇机器人主要是熟悉了一下一些几何体的使用,而最近则是在学习如何加载纹理与gltf模型,网上虽然有不少博主已经介绍了相关部分的知识点,但是真正到上手去写的时候,还是遇到了一些困难,主要还是因为刚开始学,一些基础知识不熟悉,不过最终还是都解决了,做了一个在水球里面加载鲸鱼模型的demo,有兴趣的可以一起来看下
加载gltf模型
这个demo使用create-react-app命令创建,在生成的项目中,删除App.tsx
文件中的示例代码,添加三要素,渲染器,相机,场景
再给场景中添加上光源,这里使用环境光和平行光
这些准备工作完成之后,我们去网上找点模型的素材,目前我收藏的下载gltf模型的网站有两个,分别是
两个地方都是需要登录后才能下载模型,所以没账号的话得先注册一个,其中第一个是国内的,都可以免费下载,第二个是国外的,有免费的也有收费的,这个得仔细看清楚,我在sketchfab上找了个蓝鲸的模型
把gltf压缩包下载到本地之后,解压出来就得到如下几个文件
踩坑之路现在开始,由于之前在网上看了好几篇gltf模型加载的文章,里面清一色加载模型的时候都是使用的"./xxx/xxx/xxx.gltf"这样的路径,那个时候就感觉应该是在从项目的根目录开始读取路径的,所以当即就在项目中也创建了一个文件夹models,并且将解压出来的scene.gltf文件导入进来,目录结构如下所示
加载gltf模型我们使用GLTFLoader
模型加载器,并且创建一个Object3D
对象用来存放加载出来的模型
加载器的load
函数接受四个参数,第一个就是模型的路径,第二个是onLoad
回调函数,当模型加载成功之后就可以在这个函数中获取结果,第三个是onProgress
回调函数,可以获取一些加载的进度,第四个是onError
函数,如果加载失败了可以在这个函数中得到失败原因,我们这里在onError
函数中将失败原因打印出来,当这些代码敲完之后,我揣着激动的心情想去浏览器里面看下加载出来的模型,结果得到的却是一片漆黑,啥也没加载出来,去控制台看下,果然,喜提一坨error日志
这个报错是什么意思呢?网上查了一下果然有大佬已经遇到过了,并且给出了解决方案,原因就是加载器加载的路径是在public
目录下,所以开始我的猜想是错的,应该把models
文件夹创建在public
下面,更改下项目结构如下所示
现在该没问题了吧,结果去浏览器里面看了下后发现,居然还是黑屏,倔强的刷新了几次后依然还是黑的,难道还不对?再去浏览器里面看下,果然又报错了
好消息是刚刚那个找不到json的报错没了,坏消息是来了一堆新的报错,不过这个日志还是能看得懂的,说是加载不到对应的图片,看到这些信息后我才想起来,刚才解压的包里面貌似也有个texture
的文件夹,里面刚好都是日志里描述的没加载出来的图片
那把这个textures
文件夹也放到项目中,与scene.gltf
同级,结构如下
现在再去浏览器里面看下,然后发现还是黑屏,加载个模型也太难了吧,这次又是啥原因呢,我们看下日志
这个又看不懂了,报了个RangeError
,不正确的数组长度,根据之前两个报错的经验,这个应该依然是要加载啥但是没加载到,我们解压出来的文件夹里面只剩下一个bin文件和一个txt文件了,估计那个bin文件也得放到项目中,我们试下,大不了继续报错呗,现在的目录结构如下
到了这里,才意识到,从网上下下来的模型,给你的东西都是用得到的,不能因为你要加载gltf模型就只导入gltf文件,可能这个文件也依赖着其他文件,这些文件也是要一起导入到项目中去的,现在我们的浏览器里面已经成功把模型加载出来了,但是这个加载出来的模型有点大,我们缩小的大小比例
现在浏览器里面就能清晰的展现出一只蓝鲸了
现在加入轨道控制器和刷新函数,让页面可以交互起来,这样我们就能360度无死角的观察这只鲸鱼了
做个水球
光有鲸鱼不行,我们得把它放在水里面,所以这里再给鲸鱼外面做个水球,主要用到了一些纹理加载方面的知识,那么必不可少的就是纹理加载器TextureLoader
水球我们用到的几何体是球形,所以再新建一个球形几何体,半径弄的大一些,因为要把大鲸鱼装在里面
然后就是我们需要加载的纹理,纹理也就是贴图,一张图片,从网上随便找了一张水波纹的图片如下所示
把它放到工程的public
目录底下,路径随意,我这里是放在了public/models/textures
里面,用纹理加载器加载这张图片得到一个THREE.Texture
纹理对象
现在就可以去生成一个物体了,材质使用的是基础材质MeshBasicMaterial
,将刚才得到的纹理对象作为材质map
属性的值
我们的加载纹理图部分就算做好了,看下浏览器里面的效果
虽然说纹理是加载成功了,但是我们的鲸鱼看不见了,它在球的里面,得把纹理图稍微设置点透明度才可以看见鲸鱼,设置透明度很简单,添加transparent
和opacity
属性就好了,前者相当于一个透明设置的开关,后者是具体需要设置多少透明度,这俩必须同时设置才行
现在再来看下能不能看见鲸鱼
的确是可以看到了,但感觉还是有点别扭,这个球有点偏暗了,造成这个效果的原因主要是我们纹理图默认只加载几何体的正面,也就是THREE.FrontSide
,背面是不加载的,从这个透明球的正面看过去,看到的里面自然是黑色的,解决办法就是将纹理同时也加载到背面去,也就是使用THREE.DoubleSide
通过设置了THREE.DoubleSide
之后,现在球形几何体已经可以正面背面都能看见纹理了,接下来我们需要给纹理设置个重复渲染,这样纹理多加载几次,水波纹也就多一些,为此需要先设置个repeat
,这个函数接受两个number
参数,分别表示水平方向重复次数以及垂直方向重复次数,另外还需要设置下重复渲染模式wrapS
和wrapT
,默认都是平铺模式THREE.ClampToEdgeWrapping
,也有普通重复模式THREE.RepeatWrapping
和镜像重复模式THREE.MirroredRepeatWrapping
,我们这里使用普通重复模式就好,代码如下
现在我们的水波纹就多了好多了
到这里我们整个水球的外观已经开发完毕了,接下来就是让水球上面的水可以流动起来,如何流动呢?这里就依靠纹理对象内的偏移属性offset
,可以分别在x
和y
轴方向上设置偏移量,这部分操作我们就放在刷新函数update
里面进行,让每次浏览器刷新偏移量就能改变一下
设置好纹理偏移量后,我们水球上面的水就能'流动'起来,看下效果咋样
总结
这篇文章主要学会了如何加载一个gltf模型,并且了解了一些加载纹理的知识点,美中不足的是这个鲸鱼要是能在水球里面游动就好了,那么下一篇Threejs我们就来学习一下如何让模型动起来