2天赚了4个W,手把手教你用Threejs搭建一个Web3D汽车展厅!

您所在的位置:网站首页 vr展示模型怎么做出来的 2天赚了4个W,手把手教你用Threejs搭建一个Web3D汽车展厅!

2天赚了4个W,手把手教你用Threejs搭建一个Web3D汽车展厅!

2023-12-12 10:42| 来源: 网络整理| 查看: 265

本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!

前言

事情是这样的,前段时间外包工头老杨又来找我了,说某汽车大品牌要开发一个网页展厅,希望可以在网页里360度展示它家新款汽车的3d模型,还要可以让用户DIY汽车部件的颜色。

image.png

可能很多朋友看完此文后会觉得两周时间还挺充裕,但其实不是,作为丙方没什么话语权,经常要配合甲方反复修改,很多时候改来改去最后拖到上线前一晚没办法了直接上,一个campaign site的生命周期也不长,最长也就在线上待1-3个月。

嘿嘿,时间紧,预算多!

我心想报价四个W,再给他留点砍价空间,

谁知道老杨一口答应,还说完事要请我去XX人间

我猜他起码要从客户那赚10个W

image.png

互动话题

先看最终效果,你们觉得值四个W吗?

BMW在线展厅

也就是之前的文章《三种前端实现VR全景看房的方案!说不定哪天就用得上!》里提到的用threejs来实现的

3D引擎的基本知识

本文的目标是让大家看完之后可以立刻上手用起来,既然要用3d引擎,那我们理解了一些3d的基本知识后,再看threejs的API文档效率就会很高。无论什么3d引擎,都不外乎由以下几种基本元素构成

场景(scene)

一个容器,容纳着除渲染器以外的三维世界里的一切。场景的元素采用右手笛卡尔坐标系,x轴正方向向右,y轴正方向向上,z轴由屏幕从里向外

image.png

摄像机(camera)

就像人的眼睛,在一个空间里可以看向任意方向,可以通过参数调节可视角度和可视距离。

一般我们使用符合物理世界近大远小真实情况的透视相机PerspectiveCamera,还有一些特殊情况,需要远近大小是一样的,那就要用正交相机OrthographicCamera

PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number ) //构造函数参数 //fov:视场角 //aspect:视场宽高比(一般用 画布宽/画布 高即可) //near:能看多近 //far:能看多远 //这几个参数决定了哪些scene里的三维顶点会被渲染/绘制出来

image.png

渲染器(renderer)

将camera在scene里看到的内容渲染/绘制到画布上

几何体(geometry)

3D世界里的所有物体都是点组成面,面组成几何体。相信大家对以下标准的几何体比较熟悉

球体 立方体 圆锥体 圆柱体 ...

面是由点构成的,面又可以组成各式各样的几何体。以球体举例,球体面上的点越多,球就越圆。但点越多,运算量也会越大...

image.png

另外我们一般说的3d模型就是一个或多个几何体,只是有的3d模型文件里除了包含几何体还可以包含一些额外的信息,比如贴图,材质等...需要在读取模型文件时解析出来

灯光(light)

3d引擎在没有手动创建光的情况下会默认有个环境光,不然你什么都看不到。常见的灯光有以下几种类型

AmbientLight(环境光,没有方向全局打亮,不会产生明暗)

DirectionLight(平行光,参考日光来理解) image.png

PointLight(点光源,参考灯泡来理解)

image.png

SpotLight(聚光灯,参考舞台聚光灯) image.png 贴图(texture)

想象一下你手里有一个立方体,你用一张A4纸包裹上立方体的所有面,并在上面画画。你画的内容就是贴图。

image.png

有一些类型的贴图会和光照发生反应...后面我们用到的时候再说

材质(material)

延续贴图里的想象,你用白卡纸画画,还是用油纸画画,呈现出来的质感是不同的对不对,这就是材质!下面五个球的颜色都是一样的,而材质从左至右分别是

MeshBasicMaterial(基础材质,不受光照影响) MeshStandardMaterial(PBR标准材质) MeshPhongMaterial(高光材质,适用于陶瓷,烤漆类质感) MeshToonMaterial(卡通材质,俗称三渲二) MeshStandardMaterial(PBR标准材质模拟金属反射)

image.png

来实战吧!

有了这些基础知识,再来使用threejs就很容易上手了。可以说在3dmax等软件中调出来的90%的效果,用threejs都能找到对应的配置参数。

搭建基础场景 // var scene, camera, renderer; function init(){ scene = new THREE.Scene(); //这里参数不懂的同学回去看基本知识里的camera部分 camera = new THREE.PerspectiveCamera(90, document.body.clientWidth / document.body.clientHeight, 0.1, 100); //camera的位置在x0,y0,z3,还记得迪尔卡右手坐标系吗? camera.position.set(0, 0, 3); renderer = new THREE.WebGLRenderer(); renderer.setSize(document.body.clientWidth, document.body.clientHeight); document.getElementById("container").appendChild(renderer.domElement); var controls = new THREE.OrbitControls(camera, renderer.domElement); //等待添加模型 loop(); } function loop() { requestAnimationFrame(loop); renderer.render(scene, camera); } window.onload = init;

现在我们可以先添加一个标准几何体来试试看,比如我们添加一个立方体来试试看

const geometry = new THREE.BoxGeometry( 1, 1, 1 ); const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} ); const cube = new THREE.Mesh( geometry, material ); scene.add( cube );

2021-06-28 14_14_45.gif

很显然,场景是生效的...大家注意看源码块中的注释

汽车模型

回到咱们的项目上来,品牌方给的是一个非常精细的模型,文件量有好几百兆,数百万面(triangles)。

Snipaste_2021-07-01_11-02-49.jpg

我说这可用不了,你得减面还得给我转成引擎能支持的格式gltf或obj

根据我的评估,要想在移动端网页里流畅运行,最多不能超过10万面

外包工头老杨说,你也别让客户给你弄了,他们都不会

我知道你懂,你就给弄了算了,我给你加【5K】

加5K你让我怎么好意思拒绝呢...

image.png

然后,我花25美刀巨资在sketchfab上购买了一个模型

再稍微改改就能满足要求,当然sketchfab也有免费模型

但毕竟收了老杨5K,不花点钱我心里略感不安呐 :p

优化模型结构

image.png

根据实际的需求,比如车窗要透明可以看到内饰,所以车窗就得单独给有透明属性的材质。车轮,灯罩,车网,车架,车身等等都要拆成独立的几何体才能独立配置材质。

image.png

梳理好模型结构后,我们就要准备模型文件了

加载模型

3d模型的文件格式有很多,但threejs里常用的基本是

OBJ格式

老牌通用3d模型文件,不包含贴图,材质,动画等信息。

GLTF格式(图形语言传输格式)

由OpenGL官方维护团队推出的现代3d模型通用格式,可以包含几何体、材质、动画及场景、摄影机等信息,并且文件量还小。有3D模型界的JPEG之称。

原项目中我使用的是OBJ格式,本文里我们使用GLTF格式。利用threejs提供的editor,我们可以将模型的格式进行转换并导出。

image.png

通过GLTFLoader,我们可以加载一个.gltf格式的3d模型文件。需要注意的是,这些Loader都以插件的形式存在,需要引入相应的XXXLoader.js才能使用

// //放到之前添加立方体的代码处 const loader = new THREE.GLTFLoader(); loader.load( 'images/model.gltf', function ( gltf ) { scene.add( gltf.scene ); }, function ( xhr ) { //侦听模型加载进度 console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' ); }, function ( error ) { //加载出错时的回调 console.log( 'An error happened' ); } );

2021-07-01 14_22_13.gif

通过这个代码可以遍历查看模型里的几何体列表

console.log(gltf.scene.children); //可以用for,也可以用traverse api //gltf.scene.children.traverse((child){}); 贴图和材质

现在我们来给几何体添加贴图,贴图怎么做是设计师的专业。这里不过多的说,我们只需要知道,这些贴图如何使用即可。

image.png

普通贴图(_col)

material.map,替代颜色

法线贴图(_nor)

material.normalMap,让细节程度较低的表面生成高细节程度的精确光照方向和反射效果

环境光遮蔽贴图(_occ)

material.aoMap,用来描绘物体和物体相交或靠近的时候遮挡周围漫反射光线的效果

环境反射贴图

material.envMap,用于模拟材质反射周围环境的效果

我们现在先把这些贴图文件统一加载到内存里

var allTexture; function loadAllTexture(cb){ allTexture = {}; var loadIndex = 0; var textures = [ "skymap", "shache_occ", "shache_nor", "shache_col", "neishi_occ", "neishi_nor", "mennei_col", "luntai_nor", "luntai_col", "lungu_occ", "lungu_nor", "lungu_col", "linjian_occ", "linjian_nor", "linjian_col", "floor", "deng_occ", "deng_nor", "deng_col", "cheshen_occ", "cheshen_nor", "chejia_occ", "chejia_nor", "chedengzhao_nor" ]; function loadNextTexture(){ var textureName = textures[loadIndex]; loadTexture("images/textures/"+textureName+".jpg",function(texture){ if(loadIndex


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3