1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > threejs 绘制球体_3D可视化库-Threejs调研及简单示例

threejs 绘制球体_3D可视化库-Threejs调研及简单示例

时间:2020-09-11 17:16:47

相关推荐

threejs 绘制球体_3D可视化库-Threejs调研及简单示例

0 背景

WebGL是一种3D绘图协议,其允许JavaScript和OpenGL ES2.0结合在一起,为H5 Canvas提供硬件3D加速渲染,可以借助系统显卡在浏览器里更流畅地显示3D场景和模型。Threejs是一款webGL框架,由于其易用性被广泛应用。Threejs在WebGL的api接口基础上,又进行了一层封装。

WebGL原生的api是一种非常低层的接口,需要一些数学和图形学的相关技术。其解决是如何在画布上画图的问题,怎么画点、线、面,怎么上色,怎么贴图,怎么处理光线,视角转动之后怎么换算绘制等等。对于没有相关基础的人来说,入门很难,Three.js将入门的门槛降低了一大截,其解决底层的渲染细节和复杂的数据结构,将复杂的底层细节抽象出来,简化我们创建三维动画场景的过程。

1 Threejs核心概念

为快速入手,在使用threejs之前,需要了解场景、照相机、对象、光、渲染器等核心概念。

1.1 场景-Scene

场景是所有物体的容器,对应着现实生活中三维世界,所有的可视化对象及相关的动作均发生在场景中。

1.2照相机-Camera

Camera是三维世界中观察者,类似与眼睛。为了观察这个世界,需要描述空间中的位置,three.js采用右手坐标系。

Threejs中的Camera有两种,分别是正交投影相机THREE.OrthographicCamera和透视投影相机THREE.PerspectiveCamera。

正交投影与透视投影的区别如上图所示,左图是正交投影,物体发出的光平行地投射到屏幕上,远近的方块都是一样大的;右图是透视投影,近大远小,符合我们平时看东西的感觉。

1.3 对象-Objects

对象则是场景中被观察的物体,Threejs中供显示的物体有很多,它们都继承自Object3D类,主要的对象有两种Mesh和Points。

我们都知道,计算机的世界里,一条弧线是由有限个点构成的有限条线段连接得到的。线段很多时,看起来就是一条平滑的弧线了。计算机中的三维模型也是类似的,普遍的做法是用三角形组成的网格来描述,我们把这种模型称之为Mesh模型。

这是著名的斯坦福兔子,随着三角形数量的增加,它的表面越来越平滑准确。

在Three中,Mesh的构造函数是这样的:Mesh( geometry, material )。geometry是它的形状,material是它的材质。不止是Mesh,创建很多物体都要用到这两个属性。下面我们来看看这两个重要的属性。

Geometry--形状,它通过存储模型用到的点集和点间关系(哪些点构成一个三角形)来达到描述物体形状的目的。Three提供了立方体(其实是长方体)、平面(其实是长方形)、球体、圆形、圆柱、圆台等6种基本形状;你也可以通过自己定义每个点的位置来构造形状;对于比较复杂的形状,我们还可以通过外部的模型文件导入。

Material--材质,材质其实是物体表面除了形状以为所有可视属性的集合,例如色彩、纹理、光滑度、透明度、反射率、折射率、发光度。Threejs里需要知道材质(Material)、贴图(Map)和纹理(Texture)的关系。材质包括了贴图以及其它。贴图其实是‘贴’和‘图’,它包括了图片和图片应当贴到什么位置。纹理其实就是‘图’。对于复杂的材质,可以通过Threejs提供的贴图和纹理api实现。同时,Threejs提供了多种材质可供选择,能够自由地选择漫反射/镜面反射等材质。

Points是另一种对象,其实就是一堆点的集合,它在之前很长时间都被称为ParticleSystem(粒子系统),而Three中的Points简单得多。因此最终这个类被命名为Points。

1.4Light-光

同现实世界一样,我们要看到物体需要光,光影效果是让画面丰富的重要因素。Three提供了包括环境光AmbientLight、点光源PointLight、 聚光灯SpotLight、方向光DirectionalLight、半球光HemisphereLight等多种光源。只要在场景中添加需要的光源,即可实现相应得光效果。

1.5 Renderer-渲染器

在场景中建立了各种物体,也有了光,还有观察物体的相机,Renderer则负责将物体渲染到场景中。Renderer绑定一个canvas对象,并可以设置大小,默认背景颜色等属性。

调用Renderer的render函数,传入scene和camera,就可以把图像渲染到canvas中了。

2 举例-画一个简易草坪

2.1 初始化场景和相机

通过new THREE.Scene()实例化一个场景,new THREE.PerspectiveCamera()实例化透视相机,并设置相机位置和观察方向。

//初始化场景

this.scene=newTHREE.Scene()

//初始化相机

this.camera=newTHREE.PerspectiveCamera(45,this.width/this.height,1,5000)

this.camera.position.set(330,330,330)

this.camera.lookAt(this.scene.position)

2.2 初始化渲染器

new THREE.WebGLRenderer()实例化渲染器,参数canvas为绑定的标签为canvas的dom元素。

//初始化渲染器,绑定导canvas的dom元素上

this.renderer=newTHREE.WebGLRenderer({

antialias:true,

canvas:document.querySelector('canvas')

});

//设置渲染器的大小及背景设置

this.renderer.setSize(this.width,this.height)

this.renderer.setClearColor(this.config.background)

this.renderer.shadowMap.enabled=true//是否有阴影

this.renderer.shadowMap.type=THREE.PCFSoftShadowMap

2.3构建光系统

buildLightSystem()函数实现平行光的创建及添加到初始化的场景中,包括平行光的位置,及照射方向等。

buildLightSystem(){

//平行光

letdirectionalLight=newTHREE.DirectionalLight(0xffffff,1.1);

directionalLight.position.set(300,1000,500);

directionalLight.target.position.set(0,0,0);

directionalLight.castShadow=true;

letd=300;

directionalLight.shadow.camera=newTHREE.OrthographicCamera(-d,d,d,-d,500,1600)

directionalLight.shadow.bias=0.0001;

directionalLight.shadow.mapSize.width=directionalLight.shadow.mapSize.height=1024;

//将光添加到场景中

this.scene.add(directionalLight)

},

2.4 绘制模型对象

Buildbuilding()函数实现场景中核心对象的创建及添加场景功能。addPlane()创建地面,addFense()创建围墙。

addPlane()函数中new THREE.BoxBufferGeometry(320,6,320)创建x=320,y=6,z=320的长方体,utils.makeMesh()工具类为该长方体对象增加表面材质。plane.positon.y设置长方体对象在场景中y轴的位置。this.scene.add(plane)增加该长方体面板到场景中。

Buildbuilding(){

//添加地板

this.addPlane();

//添加围墙

this.addFense();

},

function addPlane(){

letplaneGeometry=newTHREE.BoxBufferGeometry(320,6,320)

letplane=utils.makeMesh('lambert',planeGeometry,0x6f5f6a)

plane.position.y=-3

this.scene.add(plane)

}

addFense()函数实现不规则3维围墙,fenseCoords定义了二维围墙各个拐点的坐标集合,makeShape方法通过拐点集合划线,实现由点到面的二维不规则平面。makeExtrudeGeometry方法将二维图形拉伸为3为图形,拉伸高度为第二个参数所决定。同样由makeMesh函数实现物体材质的实现并最后添加到场景中。

functionaddFense(){

//12条边,12个点,首尾点相同,转一圈。

letfenseCoords=[

[-130,-130],

[-130,130],

[130,130],

[130,-130],

[20,-130],

[20,-120],

[120,-120],

[120,120],

[-120,120],

[-120,-120],

[-20,-120],

[-20,-130],

[-130,-130]

]

letfenseShape=utils.makeShape(fenseCoords)

//将二维图形拉伸为三维图形,高度为3

letfenseGeometry=utils.makeExtrudeGeometry(fenseShape,3)

letfense=utils.makeMesh('lambert',fenseGeometry,0xe5cabf)

_this.scene.add(fense)

}

2.5 页面初始化挂载执行

浏览器dom渲染时,依次执行上述函数,实现初始化场景、相机、渲染器、光系统、物体构建及挂载渲染器上,实现整个三维物体的可视化。

mounted(){

//初始化场景

this.scene=newTHREE.Scene()

//初始化相机

this.camera=newTHREE.PerspectiveCamera(45,this.width/this.height,1,5000)

this.camera.position.set(330,330,330)

this.camera.lookAt(this.scene.position)

//初始化渲染器,绑定导canvas的dom元素上

this.renderer=newTHREE.WebGLRenderer({

antialias:true,

canvas:document.querySelector('canvas')

});

this.renderer.setSize(this.width,this.height)

this.renderer.setClearColor(this.config.background)

this.renderer.shadowMap.enabled=true//是否有阴影

this.renderer.shadowMap.type=THREE.PCFSoftShadowMap

//构建光系统

this.buildLightSystem()

//构建建筑

this.buildbuilding()

//场景、相机挂载到渲染器上

this.renderer.render(this.scene,this.camera)

}

3 总结

构建一个三维空间,Three中称之为场景(Scene)

选择一个观察点,并确定观察方向/角度等(Camera)

构建光系统,用于观察物体(light)

在场景中添加供观察的物体,Three中的物体有很多种,包括Mesh,Line,Points等,它们都继承自Object3D类

将观察到的场景渲染到屏幕上的指定区域;Three中使用Renderer完成这一工

辅助开源库,dat.GUI是一个一个轻量级的图形用户界面库,或者说GUI组件,只有几十KB,可以用于创建操作控制三维场景的菜单栏;stats.min用来进行性能监控的插件;OrbitControls辅助进行旋转缩放拖动等控制;

对于物体的建模,简单的物体可以通过Three提供的api编程实现,对于复杂的物体可以借助建模工具先建模,然后引入到程序中,实现物体的渲染和控制。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。