如何用Three.js+Blender打造一个web3D展览馆vivo互联网技术

看起来像个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展览馆稿子。简单理解为,左侧是模型的层次结构,中间是模型的预览效果,右侧是模型的属性面板。

GLTF(GraphicsLanguageTransmissionFormat)是一种标准的3D模型文件格式,它以JSON的形式存储3D模型信息,例如模型的层次结构、材质、动画、纹理等。

模型中依赖的静态资源,比如图片,可以通过外部URI的方式来引入,也可以转成base64直接插入在GLTF文件中。

它包含两种形式的后缀,分别是.gltf(JSON/ASCII)和.glb(Binary)。.gltf是以JSON的形式存储信息。.glb则是.gltf的扩展格式,它以二进制的形式存储信息,因此导出的模型体积也更小一些。如果我们不需要通过JSON对.gltf模型进行直接修改,建议使用.glb模型,它更小、加载更快。

在blender中,可以直接将模型导出为GLTF/GLB格式,三种选项的差别不再赘述,我们先简单选择最高效的.glb格式。

有了模型之后,我们可以开始通过Three.js创建场景,并导入这个模型了。

怎么加载一个模型?

(1)创建一个空场景

首先创建一个空场景scene,后续所有的模型或材质都会被添加到这个场景中。

import*asTHREEfrom'three'//1.创建场景constscene=newTHREE.Scene();//2.创建镜头constcamera=newTHREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000);//3.创建Rendererconstrenderer=newTHREE.WebGLRenderer();renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(renderer.domElement);(2)导入GLTF/GLB模型

通过GLTFLoader导入.glb模型,并添加到场景中。

importGLTFLoaderfrom'GLTFLoader'constloader=newGLTFLoader()loader.load('path/to/gallery.glb',gltf=>{scene.add(gltf.scene)//添加到场景中}}(3)开始渲染

通过requestAnimationFrame来调用renderer.render方法,开始实时渲染场景。

functionanimate(){requestAnimationFrame(animate);renderer.render(scene,camera);}animate();ok,这样我们就完成了3D模型的导入,但是发现整个场景一片漆黑。

试试加个环境光。

constambientLight=newTHREE.AmbientLight(0xffffff,1)scene.add(ambientLight)

ok,亮起来了,但是效果依然很差,很劣质。

原因是模型中的材质效果、光源、阴影、环境纹理,这些全都丢失了,所以当我们导入模型时,看到的就是一堆简陋的纯色形状。

所以我们要一步步将这些丢失东西找回,还原设计稿。

接下来一步步还原设计稿。

(1)加上光源

查看Blender模型,看到设计稿中添加了一堆点光源、平行光源。

点光源可以理解为房间中的灯泡,光线强弱随着距离衰减;

平行光源可以理解为太阳的直射光,它和点光源不同,光线强弱不随着距离衰减。

于是我们也增加一些光源:

//一些灯光选项//如果是平行光则没有distance、decay选项constlightOptions=[{type:'point',//灯光类型:1.point点光源、2.directional平行光源color:0xfff0bf,//灯光颜色intensity:0.4,//灯光强度distance:30,//光照距离decay:2,//衰减速度position:{//光源位置x:2,y:6,z:0}},...]functioncreateLights(){pointLightOptions.forEach(option=>{constlight=option.type==='point'newTHREE.PointLight(option.color,option.intensity,option.distance,option.decay):newTHREE.DirectionalLight(option.color,option.intensity)constposition=option.positionlight.position.set(position.x,position.y,position.z)scene.add(light)})}createLights()可以看到场景比之前好了一些,有了光源后,模型变得立体和真实了,多了一些反色的光泽。

但是我们注意到,画面中的logo、长椅的两侧都是黑色的,并且旁边的球体、椅子等都显得不够真实。

所以,我们需要进行下一步调整:调整模型材质、增加环境纹理。

(2)调整模型材质,增加环境纹理

先简单了解一下材质和环境纹理。

材质就像物体的皮肤,我们可以调整皮肤的光泽、金属度、粗糙度、透明与否等属性,让物体有不同的视觉效果。

一般从blender导出的模型中,已经包含了一些材质属性,但是Three.js中的材质属性和Blender中的属性并非完全的映射关系,模型在导入到Three.js后,效果和设计稿会有差异。这时候我们需要手动调整材质的属性,来达到和设计稿近似的效果。

环境纹理就是让模型映射周围的环境,让场景或物体更真实。例如我们要渲染一个立方体,把立方体放进一个屋子里,这个屋子的环境就会影响立方体的渲染效果。

比如镜面的物体被贴上环境纹理后,就可以实时反射周围的环境镜像,看起来很real。

设计稿中也是将一个大厅作为了环境纹理,让场景更真实。

环境纹理分为:球形纹理和立方体形纹理。两者都可以,这里我们采用一张大厅的球形纹理作为环境贴图。

以画面中的vivo游戏节logo为例,我们通过调整它的材质和环境纹理,让它变得更真实。

constloader=newGLTFLoader()loader.load('path/to/gallery.glb',gltf=>{//1.根据Blender中物体的名字,找到logo模型gltf.scene.traverse(child=>{if(isLogo(child)){initLogo(child)//2.调整材质setEnvMap(child)//3.设置环境纹理}})scene.add(gltf.scene)}}//判断是否为LogoconstisLogo=object.name==='logo'functioninitLogo(object){object.material.roughness=0//调整表面粗糙度object.material.metalness=1//调整金属度}//加载环境纹理letenvMapconstenvmaploader=newTHREE.PMREMGenerator(renderer)constsetEnvMap=(object)=>{if(envMap){object.material.envMap=envMap.texture}else{textureLoader.load('path/to/envMap.jpg',texture=>{texture.encoding=THREE.sRGBEncodingenvMap=envmaploader.fromCubemap(texture)object.material.envMap=envMap.texture})}}经过上面的处理后,可以看到原先黑色的logo有了金属光泽,并且会反射周围的环境纹理。

其它物体经过类似的处理后,也变得更真实一些。

现在整个场景更接近了设计稿一些,但场景中少了阴影,显得很干瘪。

加上阴影。

(3)增加阴影

增加阴影分四步:

//1.rendererconstrenderer=newTHREE.WebGLRenderer()renderer.shadowMap.enabled=true;renderer.shadowMap.type=THREE.PCFSoftShadowMap;//2.lightconstlight=newTHREE.DirectionalLight()light.castShadow=true;//3.objectgltf.scene.traverse(function(child){if(child.isMesh){child.castShadow=true;}});//4.floorfloor.receiveShadow=true

添加阴影后,有质的提升,发现整个场景立体了很多,此时还原度已经很高。

如果不考虑性能损耗,这个场景的样式已经可以投入使用了。(后续会提到性能优化)

小结一下,刚刚做的几件事:

现在3D展览馆场景已经还原的差不多了,接下来要构造一个虚拟移动摇杆,控制第一人称镜头的移动和转向,实现沉浸式逛展的效果。

要实现通过虚拟移动摇杆控制镜头的移动和转向,我们需要三个东西:

有人会问为什么需要一个player,通过摇杆直接控制镜头不就行了吗?其实player的作用是用于做碰撞检测,当player遇到凳子、墙壁等障碍物时,需要停止镜头移动。直接控制镜头,是无法做碰撞检测的。

所以,实际上镜头移动的逻辑是:

用户操纵摇杆→更新player位置和朝向→从而同步更新camera位置和朝向

(1)创建移动摇杆

移动摇杆的实现原理很简单,这里仅做简述。

核心在于创建一个圆盘,监听触摸手势,并根据手势的方向来实时更新move参数,控制镜头的移动和转向。

constspeed=8//移动速度constturnSpeed=3//转向速度//moveoption,用于调整第一人称镜头的移动和转向constmove={turn:0,//旋转角度forward:0//前进距离}//创建一个handler,并监听手势,调整moveoptionconsthandler=newHandler()handler.onTouchMove=()=>{//updatemoveoption}(2)创建player

首先创建一个player对象,它是一个1.221的透明长方体。

functioncreatePlayer(){constbox=newTHREE.BoxGeometry(1.2,2,1)constmat=newTHREE.MeshBasicMaterial({color:0x000000,wireframe:true})constmesh=newTHREE.Mesh(box,mat)box.translate(0,1,0)returnmesh}constplayer=createPlayer()//创建playerplayer.position.set(4.5,2,12)//设置player的初始位置(3)updatePlayer&updateCamera

每次渲染(render)时,更新player的位置和朝向,并同步更新镜头的位置和朝向。

完成上述步骤后,我们就可以通过控制虚拟移动摇杆,来让镜头移动和转向了。

接下来加入碰撞检测,对镜头移动加点限制。

碰撞检测的步骤也很简单:

(1)收集障碍物

模型加载完成后,遍历所有的child,如果child是一个物体(mesh),则把它加入到障碍物队列(colliders)中。

constcolliders=[]loader.load('path/to/gallery.glb',gltf=>{gltf.scene.traverse(child=>{//收集障碍物if(isMesh(child)){colliders.push(child)}})}})(2)检测碰撞

调整刚刚的updatePlayer方法,在其中插入检测碰撞的逻辑。

碰撞检测逻辑基于THREE.Raycaster来实现,racaster可以理解为一个射线,当射线穿过了某个物体,我们就认为射线和物体相交了。

我们让射线的方向和player的朝向保持一致,并且在移动过程中不断判断射线前方/后面是否有相交的物体,如果有相交的物体,且和射线顶点距离distance<2.5则认为遇到了障碍物,不能再继续前进。

functionupdatePlayer(dt){constpos=player.position.clone()pos.y-=1.5//降低高度,用于计算collisionconstdir=newTHREE.Vector3()//获取当前player的朝向player.getWorldDirection(dir)dir.negate()//如果是向后退,需要对朝向取反if(move.forward<0)dir.negate()//利用Raycaster判断player是否和colliders有碰撞行为constraycaster=newTHREE.Raycaster(pos,dir)letblocked=falseif(colliders.length>0){constintersect=raycaster.intersectObjects(colliders)if(intersect.length>0){//如果相交距离<2.5,表示前方或后面有障碍物if(intersect[0].distance<2.5){blocked=true}}}//如果遇到障碍物,则停滞移动if(!blocked){//调整镜头前进or后退if(move.forward!==0){player.translateZ(move.forward>0-dt*speed:dt*speed*0.5)}}//调整镜头朝向if(move.turn!==0){player.rotateY(move.turn*1.2*dt)}}这样镜头的移动和碰撞检测就完成了。

当我们移动到椅子、墙壁等障碍物附近时,镜头会停止移动。镜头的移动范围也被我们限制在房间里,不会穿到房间外部。

3D展览馆的基本功能已经完成了,但还没有做任何的性能调优。当我们把项目运行在手机上,会发现设备发热发烫,帧率很低,低端机型甚至无法运行。

经过分析,实时的光影渲染是罪魁祸首。

页面中有10+个光源,每个光源都在实时投射阴影(尤其是点光源十分消耗资源,引起卡顿)。但实际,场景中的光源和物体位置都没有发生改变,这意味着我们不需要计算实时阴影,只需要固定的阴影。

这点可以通过纹理烘焙来实现。并且在移动端,经过纹理烘焙的光影效果实际上要优于设备计算的实时光影效果。

纹理烘焙,是指通过将场景效果预渲染到指定纹理上,生成一个模型贴图。在Blender中,我们可以选中任意对象进行烘焙。

以3D展览馆的地板为例,我们可以通过纹理烘焙,将光影效果直接渲染到贴图上。

左图是原本的棋盘格纹理,右图是结合了光影效果的烘焙贴图。烘焙完成后,地板上的光影效果就被固定下来了,我们也不需要再做实时的光影渲染。

用同样的方式,将地板、墙壁、天花板等物体,一一进行烘焙处理,导出一个新的模型。由于光影效果已经被渲染到贴图上,我们可以将大部分光源去掉,只保留2-3个必要的点、平行光源和全局光。再次运行后,发现卡顿、发烫的问题已经不再明显。并且效果其实比实时渲染更精细一些。

这里没有对烘焙做过多介绍,要生成精致的烘焙结果还需要依赖对UVMap、烘焙参数的了解,虽然这些偏向于设计同学的工作,一般由他们来输出烘焙纹理。但是作为开发者,了解了这些后才能和UI更好地沟通和配合。

模型大小约为23M,首次加载模型需要9s左右。(尤其是在做完纹理烘焙后,由于贴图变得复杂,模型更大了)

以下是几个优化模型大小的建议:

(左图为优化前,右图为优化后)

现在,我们基本完成了整个3D展览馆的开发。虽然有一些细节没有在文中涉及到,但开发过程大致如此。

THE END
1.vr企业云展馆将展厅的主题内容生动展现给每一位参观者虚拟现实深圳华锐视点打造的VR企业展馆,将展厅的主题内容生动展现给每一位参观者,并且能提供更新维护和售后服务,让企业能省心省力打造专属的VR企业展馆,降低企业成本和投入。https://www.163.com/dy/article/JJI0SCC70538H7NJ.html
2.云展馆:3D模型展示与虚拟现实技术腾讯云开发者社区总之,云展馆设计要实现展品的三维模型展示,需要从数据采集与处理、三维模型展示技术、交互设计与虚拟现实技术以及云端存储与管理等方面进行综合考虑。通过这些技术手段,云展馆可以为观众提供更加丰富、便捷、高效的参观体验。https://cloud.tencent.com/developer/news/1210991
3.渔业虚拟现实博览厅,VR农牧业展馆设计模型交互式种植业展馆解决方案,数字互动多媒体农牧业展会展厅建设公司一笔一画立于西安,服务网络遍及北京市、天津市、上海市、重庆市、河北省、山西省、辽宁省、吉林省、黑龙江省、江苏省、浙江省、安徽省、福建省、江西省、山东省、河南省、湖北省、湖南省、广东省、海南省、四川省、贵州省、云南省、陕西省、甘肃省http://xian0168337.11467.com/m/product/9668881.asp
4.展厅展馆多媒体沙盘设计模型设计 动态演示 模型制作 工业机械 建筑模型 地形地貌 联系电话:18618150215 13146136409 ? ? 展厅展馆多媒体沙盘设计 如今,多媒体互动投影技术发展得越来越成熟,在各种行业中的运用也是非常的广泛,通过独特的展示方式,加上趣味性的互动展示,使得参与者对所展示的内容能够更容易地理解。 http://tianjimx.com/newsinfo/2352861.html
5.太原:打造“全景+线上+体验”新模式第五届山西文化产业博览交易会(云上文博会)太原3D展馆,运用3D和VR等技术,设置了六大板块248个展点,全方位展示太原近年来的文化产业发展现状。 太原3D展馆以四大创意为核心,打造特色鲜明、振翅欲飞的3D展厅模型。 整个展馆突出“文”的概念,从各个角度来看,展馆整体造型为一个艺术化的“文”字形,和文博会的Logohttps://wlj.taiyuan.gov.cn/p198/lyzx/20221230/30011362.html
6.unityvr展馆代码用unity做一个vr博物馆unityvr展馆代码 用unity做一个vr博物馆 长久以来,我们总是不断被初学者问到类似这样的问题:如何从头到尾做一个VR项目?本套课程尝试对这个问题进行解答,从模型准备开始,到项目最终导出结束,从设计到开发,演示了一个VR项目的制作经过。 课程介绍视频 【谁适合学习这门课】https://blog.51cto.com/u_16213721/11896167
7.vr体验馆建筑su模型草图大师vr体验馆建筑模型图片3D溜溜网su模型库,汇集多类型vr体验馆建筑su模型素材,帮设计师根据不同场景,寻找免费下载的草图大师建模的模型图片素材,找草图大师vr体验馆建筑模型素材就来3D溜溜网。https://su.3d66.com/sketchup_relation/relation_139013.html
8.vr全景虚拟展厅设计网上虚拟展厅展馆搭建方案VR全景虚拟展厅设计是近年来备受关注的数字化展示方式之一,它通过虚拟现实技术将展馆的物理空间搬到线上,让参观者足不出户就能获得沉浸式的展览体验。以下是一个关于网上虚拟展厅展馆搭建方案的详细设计思路: 1.展厅定位与主题设计 在设计VR全景虚拟展厅时,首先需要明确展厅的定位和主题。无论是企业展厅、博物馆展览、https://www.cdhannuo.com/news/2184.html
9.步进漫游蛙色3DVR元宇宙官网3D虚拟展厅3D模型文化展馆 商业空间 现代装饰 3D模型展示现代装饰,突破传统平面展示,运用720°VR手段,还原物理空间,使用户精确感知空间大小,构建全新营销场景。 3D实景展示家具,精确感知空间大小 合理设计科学配置,装潢空间和谐互补 热点嵌入丰富内容,进阶展示优势信息 查看案例 -> https://hongyun.720think.com/Wasee/VRHome/panospace
10.用H5技术打造新颖的互联网展馆—Web3D网上虚拟展厅(原创)网上3D虚拟展厅展馆(Web3D展厅)特点: 1)采用H5 WebGL技术标准开发,仅用浏览器输入网址即可,无需安装任何插件! 2)VR 3D场景互动,异步动态加载; 3)结合文字、图片、视频、解说等展示; 4)模型优化,加载时间短; 5)支持较新浏览器访问,如IE11+、谷歌、火狐、百度、QQ、360、Safari等; https://www.dhznkj.com/news/1010863.html
11.沙盘模型的意义和作用有哪些沙盘模型是一种用沙子、小道具和图符等材料搭建的模拟环境,用来表示现实世界中的景象、场景或者问题。它http://www.mansitine.com/ask/533385.html
12.科技范+未来感第21届投洽会特色展馆抢“鲜”看鹭岛聚焦巡逻机器人、送货机器人、社交机器人……在位于智慧城市暨人工智能展区的AI机器人科普区,一群“新物种”云端机器人正面对面“切磋较量”,有的可以握手、跳舞、聊天,有的默默巡视周边。不远处,华为、美亚柏科等企业打造的“智慧城市运营中心”项目,正紧锣密鼓地布置出一个智慧城市的未来模型。 http://m.taihainet.com/news/xmnews/ldjj/2021-09-07/t_2550029.html
13.彝族展馆全景模型VR模型下载ID:930631471彝族展馆全景模型VR模型下载 ID:930631471复制 上传作者 冷锋8888 上传时间2018-11-21 文件大小266.41M 风格:其它 材质贴图:有 VR/CR:无 灯光详情:VR灯光 MAX版本:2012 授权普通 价格:100知币 官方补贴价 100知币 VIP专享价 80知币 立即下载 收藏 收藏 分享 纠错https://vr.znzmo.com/qjmx/930631471.html
14.3D广交会展品企业三维建模VR线上展馆展品建模3D广交会展品企业三维建模VR线上展馆运用先进网络信息化技术,参展客户只需要通过点击展品3D模型的展示方式,即可线上观看1:1展示还原展品,了解展品的需求。广交会全面建立3D建模、VR线上企业展馆。商迪3D为企业提供更加个性化、虚拟化、可视化、数字化、更高质量的企业展示内容,每件展品都准备好产品描述、多角度外观展示图https://blog.csdn.net/weixin_48262930/article/details/114941828
15.山东沙盘模型制作济南沙盘模型制作山东三维动画制作工业模型、规划模型、展馆模型和方案模型等领域的探索和实践中所积累的成功经验。 01 济南尚境数字科技有限公司是一家专注于沙盘模型制作、三维动画制作、VR体验制作、机械设备模型制作、LED大屏、液晶拼接屏设计安装等多领域数字科技技术设计与制作为主的专业机构公司。 http://www.jn-sjszkj.com/
16.空战模拟3D模型地震小屋VR校车沙盘游戏这个区的公共交通安全体验展区以交通和急救知识为两大主题,运用大型VR校车、沙盘游戏、红绿灯抓拍、自行车及各类触摸式抢答机,可进行多角度深入体验和学习。 交通标识学习与识别 路口通行摆拍体验互动 模拟骑行互动体验 大型车辆盲区体验互动 原标题:《空战模拟、3D模型、地震小屋、VR校车、沙盘游戏这个区的公共安全教育馆寓教https://m.thepaper.cn/newsDetail_forward_14329932