写点什么

基于 Threejs 的 web 3D 开发入门

  • 2019-08-21
  • 本文字数:3113 字

    阅读完需:约 10 分钟

基于Threejs的web 3D开发入门

随着软硬件的发展,在 PC 和移动端浏览器上进行 web 3D 开发的条件已经基本成熟了,出现了不少 js 3D 库,Threejs 是 js 3D 库中的佼佼者。国内也有企业开始做一些应用尝试,某宝 2016 年双 11 就用 ThreeJS 做了一个比较酷炫的 3D 宣传页面刷爆了朋友圈。


下图是用 Threejs 绘制的一个 3D 立方体动画的截图,在这个 demo 里,立方体会动态的旋转,threeJS 30 行代码就可以完成这么一个 demo。Threejs 让没有丰富 3D 编程经验的 web 前端开发人员,也可以快速上手开发 web 3D 应用。


Threejs 是什么

官网对 Threejs 的介绍非常简单:“Javascript 3D library”。openGL 是一个跨平台 3D/2D 的绘图标准,WebGL 则是 openGL 在浏览器上的一个实现。web 前端开发人员可以直接用 WebGL 接口进行编程,但 WebGL 只是非常基础的绘图 API,需要编程人员有很多的数学知识、绘图知识才能完成 3D 编程任务,而且代码量巨大。Threejs 对 WebGL 进行了封装,让前端开发人员在不需要掌握很多数学知识和绘图知识的情况下,也能够轻松进行 web 3D 开发,降低了门槛,同时大大提升了效率。

Threejs 应用场景举例

1、web 3D 游戏

2、3D 模型展示

下图的例子中,用户可以跟浏览器交互,通过鼠标操作 360 度查看汽车,点击车门进入到车内,查看车内立体视图,如同身临其境。


3、数据可视化

4、web vr

Threejs 的基本要素

3D 编程跟 2D 编程有较大不同,因此需要掌握一些 3D 编程的基本概念。Threejs 的基本要素包括以下几个方面:场景、相机、光、物体。


场景:是一个三维空间,所有物品的容器。可以把场景想象成一个空房间,接下来我们会往房间里面放要呈现的物体、相机、光源。



相机:Threejs 必须要有往场景中添加一个相机,相机用来确定观察位置、方向、角度,相机看到的内容,就是我们最终在屏幕上看到的内容。在程序运行过程中,可以调整相机的位置、方向、角度。想象一下,在房间里放了一个摄像机,你不在房间里面,但可以远程控制相机移动,摄像机传给远程电脑上展示出来的画面,就是 Threejs 在屏幕上呈现的画面。


光:假如没有光,摄像机看不到任何东西,因此需要往场景中添加光源。为了跟真实世界更加接近,Threejs 支持模拟不同光源,展现不同光照效果,有点光源、平行光、聚光灯、环境光等。


物体:有了场景、相机、光,就可以往场景中放物体了,在 Threejs 中,物体由形状和材质两部分组成,形状决定物品的轮廓,材质则是物体的材料和质感。

渲染

Threejs 绘制的东西,最终需要在屏幕一块矩形画布上显示出来。为了实现动画效果,我们需要有一个重绘机制。由于视神经元的反应速度问题,图像消失后仍然会在人眼残留 1/24 秒,只要一秒内绘制的帧数超过 24 就能实现流畅的动画效果。Threejs 提供了重绘接口,我们有两种方式去调用接口实现重绘。一种是 setInterval,以固定的时间间隔去调用,可以用于我们对渲染帧数要求比较高的场景,但事实上由于 Javascript 是单线程的,这种方式并不能 100%保证相同的时间间隔调用,如果浏览器繁忙可能会导致 setInterval 的延迟执行;第二种方式是 requestAnimationFrame,让浏览器自行根据当前 cpu 负载等情况决定何时重绘,达到最佳帧率。

位置

为了方便描述位置,引入了坐标系,Threejs 使用的是右手坐标系,如下图所示。坐标系的原点位于渲染画布的几何中心。我们对物体的位置的描述,也是指物体的几何中心的位置。


相机

相机有正交投影相机和透视投影相机两种。透视投影跟人眼看到的世界是一样的,近大远小;正交投影则远近都是一样的大小,三维空间中平行的线,投影到二维空间也一定是平行的。大部分场景都适合使用透视投影相机,因为跟真实世界的观测效果一样;在制图、建模等场景适合使用正交投影相机,方便观察模型之间的大小比例。


Threejs 中的相机跟真实世界的相机不完全一样,这里相机的可见区域是一个立方体,称为相机的示景体。

正交投影相机

示景体是一个长方体,由 6 个参数确定:THREE.OrthographicCamera(left, right, top, bottom, near, far),这 6 个参数规定了相机示景体的左、右、上、下、前、后六个面的位置。


透视投影相机

示景体是一个梯形体,由四个参数确定:THREE.PerspectiveCamera(fov, aspect, near, far)



fov 是相机在竖直方向的张角,aspect 则是宽高比,即 width/height,通常设为画布的宽高比,near 和 far 分别是近平面和远平面与相机的距离。

投影的大小

考虑一种比较简单的场景,相机示景体的远近平面和坐标系中的 xy 平面平行,从而示景体远近平面上的内容刚好可以垂直投影到画布上,并且示景体中与 xy 平面平行的任何一个平面,投影到画布上刚好等于画布大小。假如透视投影相机的近平面的大小为 axb,远平面大小为 2ax2b,则一张 axb 大小的纸放在近平面上,投影到画布时刚好铺满整张画布;放到远平面上则只能占据画布面积的 1/4(远平面的面积是近平面的 4 倍)。正是因为透视投影相机的示景体近小远大,才会导致同样一个物品放在不同位置显示出近大远小的效果。而正交投影相机因为远近平面大小一样,所以同一个物品距离相机的远近不影响物体在画布上投影展示的大小。

物体

物体由几何形状(Geometry)和材质(Material)组成。同样的几何形状,不同材质构成了不同物体,比如球状,有篮球、玻璃球、水晶球等。

形状

Threejs 提供了一些常见的几何形状,有三维的也有二维的,三维的比如长方体、球体、圆柱体、环等,二维的比如长方形、圆形、扇形等。如果默认提供的形状不能满足需求,也可以自定义,通过定义顶点和顶点之间的连线绘制自定义几何形状,更复杂的模型还可以用建模软件建模后导入。


计算机是如何绘制几何形状的呢?我们知道,计算机只能绘制直线,那么曲线和 3D 形状如何绘制出来呢?


1、绘制圆形。如下图所示,通过绘制多边形实现近似的圆形效果,当多边形的边数足够多的时候,两条边之间的过渡就显得平滑,多边形看起来就足够圆了。



2、绘制 3D 模型。常用的做法是用三角形组成的网格来模拟,如下图所示,用足够多的三角形时,兔子的身体看起来就足够平滑,跟真实兔子比较接近。著名的斯坦福兔子模型用了 69451 个三角形。


材质

Threejs 提供了几种比较有代表性的材质,常用的有漫反射、镜面反射两种材质,还可以引入外部图片,贴到物体表面,称为纹理贴图。

外部模型

现实世界丰富多彩,不是 Threejs 的几种默认几何形状和材质所能表达的,实际运用中,很多时候需要用到外部模型,通过 3D 建模软件构建物体的三维模型并导出模型文件,Threejs 导入模型文件进行使用。


光照

光源主要是以下几种:1)环境光,所有角度看到的亮度一样,通常用来为整个场景指定一个基础亮度,没有明确光源位置;2)点光源,一个点发出的光源,照到不同物体表面的亮度线性递减;3)平行光,亮度与光源和物体之间的距离无关,只与平行光的角度和物体所在平面有关;4)聚光灯,投射出的是类似圆锥形的光线。

小结

本文对 Threejs 编程做了一下简单介绍,目的是让读者对 Threejs 编程有个基本认识。纸上得来终觉浅,绝知此事要躬行!建议到 Threejs 官网首页看看那些有趣的 demo,着手写一些简单的 demo 进行实践。目前 web 3D 应用因为浏览器渲染性能、模型体积过大等原因,并没有大规模使用起来,只限于在品牌宣传等部分领域尝试使用。我刚好经历过浏览器 2D 数据可视化绘图由 flash 向 JS 转变的过程(2012 年前后),相信随着软硬件性能的提升和网络速度的提升,web 3D 应用也会慢慢的推广使用起来。


作者介绍:


朱海洋,高级工程师,增值产品部 QQ 会员营收团队负责人,目前团队负责 QQ 会员、靓号、SVIP+、大王超会等项目,有丰富的 Web 前端架构经验。


本文转载自公众号小时光茶舍(ID:gh_7322a0f167b5)。


原文链接:


https://mp.weixin.qq.com/s/-8DtRxuFYpH1gKezVlhjDw


2019-08-21 10:3210558

评论

发布
暂无评论
发现更多内容

SpringBoot-技术专题-Caffeine用法

码界西柚

血亏!阿里P8轻易把总结了近一年的java高级特性笔记送人了

996小迁

Java 学习 架构 笔记 Java高级特性

干掉PPT!现场编码的职级晋升答辩你参加过么?

华为云开发者联盟

软件 开发者 API

区块链的浪潮开始涌动了

CECBC

区块链 期货

CloudQuery,数据库管理用它就够了!

BinTools图尔兹

数据库 sql 安全 工具软件

蚂蚁金服架构师分享一套内部Java并发编程进阶笔记,白嫖太香了

Java架构追梦

Java 学习 架构 面试 并发编程

十年Java开发经验,走了五年弯路,整理了一份Java架构师进阶路线及进阶资料!

Java架构之路

Java 程序员 面试 程序人生 编程语言

多种方式实现 LazyMan

局外人

大前端 队列 Promise

风雨边城

满天星

美食 旅行

区块链应用众多难题“卡脖子”

CECBC

区块链 金融 供应链融资

Java之父都需要的一本能够更深入地了解Java编程语言的书

Java架构之路

Java 程序员 面试 编程语言

比MySQL快839倍!揭开分析型数据库JCHDB的神秘面纱

京东科技开发者

数据库 JCHDB

重新学习面向对象设计之开放-封闭原则

IT老兵重开始

面向对象设计 OCP 开闭原则

一文带你了解文字识别

华为云开发者联盟

技术 识别 文字

基于Flink+ClickHouse打造轻量级点击流实时数仓

Apache Flink

flink

动态代理玩不明白?别紧张,你只是缺少这个demo

小Q

Java 编程 程序员 开发 动态代理

spring-boot-route(十六)使用logback生产日志文件

Java旅途

Java Spring Boot logback

高难度对话读书笔记——表达自我

wo是一棵草

工作流引擎,企业运作加速器

Marilyn

敏捷开发 工作流 快速开发

区块链来了 职业教育这么干

CECBC

区块链 职业教育

C++函数模板的偏特化

Qing Wang

c++

Hive UDF/UDAF 总结

windism

anyRTC直播带货解决方案

anyRTC开发者

音视频 WebRTC 直播 RTC

如何获得工作成就感

滴滴普惠出行

是的,你没看错,自己的APP也能运行微信小程序了

FinClip

小程序flutter, 跨平台 小程序生态 移动开发

Pulsar 社区周报|09-19 ~ 09-25

Apache Pulsar

大数据 开源 Apache Pulsar 消息中间件

通过MapReduce降低服务响应时间

万俊峰Kevin

mapreduce Go 语言

媒介狂想曲

善宝橘

媒介 想象

技术解读丨GaussDB数仓高可用容灾利器之逻辑备份

华为云开发者联盟

数据 容灾 备份

软件测试人员的职业发展之路

BY林子

软件测试 QA 职业发展

基于Threejs的web 3D开发入门_大前端_朱海洋_InfoQ精选文章