如何用Three.js + Blender打造一个web 3D展览馆

如何用Three.js + Blender打造一个web 3D展览馆,3D展览馆是什么,先来预览下效果:,图片,看起来像个3D冒险类手游,用户可以操纵屏幕中央的虚拟摇杆,以第一人称视角在房间内自由移动、看展览。,首先介绍一个背景,我们的工作内容是做游戏中心的用户运营活动,会做些好玩的活动让用户参与,并get一些福利。,当时的活动背景是我司一年一度的vivo游戏节,并且元宇宙是大热词。所以做它的原因有几个:,用到的组合方案:Three.js + Blender。,开源的3D框架有很多,但最常用的有两种:Three.js、Babylon.js,我们只需要从中二选一。分析后发现两者各有优势:,图片,考虑到3D展览馆的几个基本特性:,Three.js包体更小、有更多参考案例、上手更快,所以虽然Babylon.js有它的优势,但Three.js更适合这个项目。,Blender是一款轻量的开源3D建模软件,有很多好用的免费插件,而且Blender能导出GLTF / GLB模型(后面会对GLTF / GLB模型做简介),匹配Three.js的使用方式,整体更简单好用一些。,所以,就是它了。,在进入开发之前,先简单了解Blender和GLTF / GLB模型。,首先,Blender大概长这样,图中是设计师交付的3D展览馆稿子。简单理解为,左侧是模型的层次结构,中间是模型的预览效果,右侧是模型的属性面板。,一般来说,作为开发者我们不需要掌握太多Blender相关知识,只需知道如何看懂模型结构、导出GLTF / GLB模型以及烘焙的基本原理即可。,图片,GLTF(Graphics Language Transmission Format)是一种标准的3D模型文件格式,它以JSON的形式存储3D模型信息,例如模型的层次结构、材质、动画、纹理等。,模型中依赖的静态资源,比如图片,可以通过外部URI的方式来引入,也可以转成base64直接插入在GLTF文件中。,它包含两种形式的后缀,分别是.gltf(JSON/ASCII).glb(Binary)。.gltf是以JSON的形式存储信息。.glb则是.gltf的扩展格式,它以二进制的形式存储信息,因此导出的模型体积也更小一些。如果我们不需要通过JSON对.gltf模型进行直接修改,建议使用.glb模型,它更小、加载更快。,在blender中,可以直接将模型导出为GLTF / GLB格式,三种选项的差别不再赘述,我们先简单选择最高效的.glb格式。,图片,有了模型之后,我们可以开始通过Three.js创建场景,并导入这个模型了。,为了防止篇幅过长,这里假设大家已经掌握了Three.js的一些基本语法。文章重点放在如何加载模型,并一步步进行调优和实现最终的3D展览馆效果。,怎么加载一个模型?,(1)创建一个空场景,首先创建一个空场景scene,后续所有的模型或材质都会被添加到这个场景中。,(2)导入GLTF / GLB模型,通过GLTFLoader导入.glb模型,并添加到场景中。,(3)开始渲染,通过requestAnimationFrame来调用renderer.render方法,开始实时渲染场景。,ok,这样我们就完成了3D模型的导入,但是发现整个场景一片漆黑。,图片图片,试试加个环境光。,图片,ok,亮起来了,但是效果依然很差,很劣质。,原因是模型中的材质效果、光源、阴影、环境纹理,这些全都丢失了,所以当我们导入模型时,看到的就是一堆简陋的纯色形状。,所以我们要一步步将这些丢失东西找回,还原设计稿。,接下来一步步还原设计稿。,(1)加上光源,查看Blender模型,看到设计稿中添加了一堆点光源、平行光源。,图片,点光源可以理解为房间中的灯泡,光线强弱随着距离衰减;,平行光源可以理解为太阳的直射光,它和点光源不同,光线强弱不随着距离衰减。,于是我们也增加一些光源:,可以看到场景比之前好了一些,有了光源后,模型变得立体和真实了,多了一些反色的光泽。,图片图片,图片图片,但是我们注意到,画面中的logo、长椅的两侧都是黑色的,并且旁边的球体、椅子等都显得不够真实。,所以,我们需要进行下一步调整:调整模型材质、增加环境纹理。,(2)调整模型材质,增加环境纹理,先简单了解一下材质和环境纹理。,材质就像物体的皮肤,我们可以调整皮肤的光泽、金属度、粗糙度、透明与否等属性,让物体有不同的视觉效果。,一般从blender导出的模型中,已经包含了一些材质属性,但是Three.js中的材质属性和Blender中的属性并非完全的映射关系,模型在导入到Three.js后,效果和设计稿会有差异。这时候我们需要手动调整材质的属性,来达到和设计稿近似的效果。,环境纹理就是让模型映射周围的环境,让场景或物体更真实。例如我们要渲染一个立方体,把立方体放进一个屋子里,这个屋子的环境就会影响立方体的渲染效果。,比如镜面的物体被贴上环境纹理后,就可以实时反射周围的环境镜像,看起来很real。,设计稿中也是将一个大厅作为了环境纹理,让场景更真实。,图片,环境纹理分为:球形纹理和立方体形纹理。两者都可以,这里我们采用一张大厅的球形纹理作为环境贴图。,图片,以画面中的vivo游戏节logo为例,我们通过调整它的材质和环境纹理,让它变得更真实。,图片,经过上面的处理后,可以看到原先黑色的logo有了金属光泽,并且会反射周围的环境纹理。,其它物体经过类似的处理后,也变得更真实一些。,图片图片,图片图片,图片图片,图片图片,现在整个场景更接近了设计稿一些,但场景中少了阴影,显得很干瘪。,加上阴影。,(3)增加阴影,增加阴影分四步:,图片,添加阴影后,有质的提升,发现整个场景立体了很多,此时还原度已经很高。,如果不考虑性能损耗,这个场景的样式已经可以投入使用了。(后续会提到性能优化),小结一下,刚刚做的几件事:,现在3D展览馆场景已经还原的差不多了,接下来要构造一个虚拟移动摇杆,控制第一人称镜头的移动和转向,实现沉浸式逛展的效果。,要实现通过虚拟移动摇杆控制镜头的移动和转向,我们需要三个东西:,有人会问为什么需要一个player,通过摇杆直接控制镜头不就行了吗?其实player的作用是用于做碰撞检测,当player遇到凳子、墙壁等障碍物时,需要停止镜头移动。直接控制镜头,是无法做碰撞检测的。,所以,实际上镜头移动的逻辑是:,用户操纵摇杆 → 更新player位置和朝向 →从而同步更新camera位置和朝向,(1)创建移动摇杆,移动摇杆的实现原理很简单,这里仅做简述。,核心在于创建一个圆盘,监听触摸手势,并根据手势的方向来实时更新move参数,控制镜头的移动和转向。,(2)创建player,首先创建一个player对象,它是一个1.2 * 2 * 1的透明长方体。,(3)updatePlayer & updateCamera,每次渲染(render)时,更新player的位置和朝向,并同步更新镜头的位置和朝向。,注意:render方法中使用clock.delta()来计算每次渲染之间的时间间隔,并使用这个时间间隔来更新player和camera。因为在理想的60帧率情况下,两帧时间间隔为16.67ms,但实际上该数值会有波动,因此我们要根据实际的渲染时间间隔来更新player和camera,让镜头的移动和转向幅度更自然一些。,完成上述步骤后,我们就可以通过控制虚拟移动摇杆,来让镜头移动和转向了。,接下来加入碰撞检测,对镜头移动加点限制。,碰撞检测的步骤也很简单:,(1)收集障碍物,模型加载完成后,遍历所有的child,如果child是一个物体(mesh),则把它加入到障碍物队列(colliders)中。,(2)检测碰撞,调整刚刚的updatePlayer方法,在其中插入检测碰撞的逻辑。,碰撞检测逻辑基于THREE.Raycaster来实现,racaster可以理解为一个射线,当射线穿过了某个物体,我们就认为射线和物体相交了。,我们让射线的方向和player的朝向保持一致,并且在移动过程中不断判断射线前方/后面是否有相交的物体,如果有相交的物体,且和射线顶点距离distance < 2.5则认为遇到了障碍物,不能再继续前进。,这样镜头的移动和碰撞检测就完成了。,当我们移动到椅子、墙壁等障碍物附近时,镜头会停止移动。镜头的移动范围也被我们限制在房间里,不会穿到房间外部。,图片,3D展览馆的基本功能已经完成了,但还没有做任何的性能调优。当我们把项目运行在手机上,会发现设备发热发烫,帧率很低,低端机型甚至无法运行。,经过分析,实时的光影渲染是罪魁祸首。,页面中有10+个光源,每个光源都在实时投射阴影(尤其是点光源十分消耗资源,引起卡顿)。但实际,场景中的光源和物体位置都没有发生改变,这意味着我们不需要计算实时阴影,只需要固定的阴影。,这点可以通过纹理烘焙来实现。并且在移动端,经过纹理烘焙的光影效果实际上要优于设备计算的实时光影效果。,纹理烘焙,是指通过将场景效果预渲染到指定纹理上,生成一个模型贴图。在Blender中,我们可以选中任意对象进行烘焙。,图片,以3D展览馆的地板为例,我们可以通过纹理烘焙,将光影效果直接渲染到贴图上。,左图是原本的棋盘格纹理,右图是结合了光影效果的烘焙贴图。烘焙完成后,地板上的光影效果就被固定下来了,我们也不需要再做实时的光影渲染。,图片图片,图片图片,用同样的方式,将地板、墙壁、天花板等物体,一一进行烘焙处理,导出一个新的模型。由于光影效果已经被渲染到贴图上,我们可以将大部分光源去掉,只保留2-3个必要的点、平行光源和全局光。再次运行后,发现卡顿、发烫的问题已经不再明显。并且效果其实比实时渲染更精细一些。,图片图片,图片图片,这里没有对烘焙做过多介绍,要生成精致的烘焙结果还需要依赖对UV Map、烘焙参数的了解,虽然这些偏向于设计同学的工作,一般由他们来输出烘焙纹理。但是作为开发者,了解了这些后才能和UI更好地沟通和配合。,模型大小约为23M,首次加载模型需要9s左右。(尤其是在做完纹理烘焙后,由于贴图变得复杂,模型更大了),以下是几个优化模型大小的建议:,经过优化,初始模型大小由23M缩小为1.2M,首次加载时间由9s缩短到3s以内。,(左图为优化前,右图为优化后),图片图片,图片图片,现在,我们基本完成了整个3D展览馆的开发。虽然有一些细节没有在文中涉及到,但开发过程大致如此。,(1)了解Blender、GLTF / GLB模型,(2)js导入GLTF / GLB模型,(3)还原设计稿,(4)实现虚拟移动摇杆,控制镜头移动,(5)增加碰撞检测,(6)性能调优:,一些建议:

文章版权声明

 1 原创文章作者:cmcc,如若转载,请注明出处: https://www.52hwl.com/29548.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年6月23日
下一篇 2023年7月15日