博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WebGL之3D地球
阅读量:6521 次
发布时间:2019-06-24

本文共 5359 字,大约阅读时间需要 17 分钟。

看了饿了么小小倩老师的canvas作品,心血来潮,学着做了个3D地球,也算是入坑WebGL了吧。之前有用过原生的canvas画2D的图形,这次则是用了Three.js和stats.js的3D框架,边学边练手,效果还算比较满意...毕竟第一次接触WebGL

Talk is cheap show the code!

github项目源码地址:

项目演示地址:

代码还有很多不足,求大神review..

什么是Three.js

随着近几年前端的飞速发展,网页的表现能力越来越强大,浏览器提供了WebGL(Web图形处理库)接口,可以通过调用对应API进行3D图形的绘制,Three.js则是在此基础接口之上又做了一层封装。Three.js是当下最流行的网页3D渲染JS引擎。

Three.js使用方法

准备阶段

  1. 页面添加canvas元素
复制代码
  1. 引入Three.js库文件
  • 本地引入
复制代码
  • CDN远程引入
复制代码
  1. 项目中用到的变量
let canvas,  //画布标签  stats,     //性能检测器  camera,    //相机  scene,     //场景  renderer,  //渲染器  group,     //物体组  mouseX = 0,  //鼠标横向位置  mouseY = 0,  //鼠标纵向位置  windowHalfX = window.innerWidth / 2,  //视口大小的一般  windowHalfY = window.innerHeight / 2; //视口大小的一半复制代码

创建场景素材

为了让three.js显示,需要三件事情:场景、相机和渲染器

  1. 场景,可以理解为舞台。因为要绘制3D效果,必须要有一个舞台来演示效果
    创建场景 API:THREE.Scene()
scene = new THREE.Scene() //创建场景复制代码
  1. 有了场景,现在需要相机来拍摄出素材出来,所以第二步则是需要创建一个"相机"
    创建相机 API:THREE.PerspectiveCamera(fov, aspect, near, far)
    • fov 可视角度,可理解为视野,是在显示器上看到的场景的范围,以度为单位。
    • aspect 为width/height,通常设置为canvas元素的高宽比。
    • near近端距离
    • far远端距离
    • 只有离相机的距离大于near值,小于far值,且在相机的可视角度之内,才能被相机投影到。
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 2000)camera.position.z = 500  //相机的远近复制代码
  1. 场景和相机都有了,也就是能够拍摄出素材了,但素材需要经过一些PS、美颜等才能变得好看。这时候就需要渲染器。
    创建渲染器 API:THREE.WebGLRenderer({})
renderer = new THREE.WebGLRenderer({    canvas: canvas,    antialias: true, // true/false表示是否开启反锯齿,    /*    alpha: false,              // true/false 表示是否可以设置背景色透明,    precision: 'highp',        // highp/mediump/lowp 表示着色精度选择,    premultipliedAlpha: false, // true/false 表示是否可以设置像素深度(用来度量图像的分辨率),    maxLights: 3,              // 最大灯光数,    stencil: false             // false/true 表示是否使用模板字体或图案    */  })复制代码

指定渲染器宽高 API:renderer.setSize(window.innerWidth, window.innerHeight) 参数分别为宽和高

创建3D图形

我们已经用相机在场景中拍摄出了素材,但这些素在毕竟还只是2D,现在我们要将该素材由2D变为3D,这时这就需要用一个3D图形作为2D素材的载体。用个吃货的简单理解,就是鸡肉卷外面的卷,开始卷是2D的平面的,把鸡肉到卷面上,用卷包裹起鸡肉,则就由2D的卷变成了3D的鸡肉卷对吧。emmm...解释的好尬。

API:

  • 图形形状THREE.SphereGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength)
    • radius:球体半径
    • widthSegments, heightSegments:水平方向和垂直方向上分段数。widthSegments最小值为3,默认值为8。heightSegments最小值为2,默认值为6。
    • phiStart:水平方向上的起始角,默认值0
    • phiLenght:水平方向上球体曲面覆盖的弧度,默认Math.PI * 2
    • thetaStart : 垂直方向上的起始角, 默认0
    • thetaLength: 垂直方向是球体曲面覆盖的弧度,默认值为Math.PI
  • 图形材质THREE.MeshBasicMaterial({})
    图形材质有很多种,网上查了查资料,觉得这个总结的挺好,大家可以看一看
  • 图形构成THREE.Mesh(geometry, material)
    • geometry 物体形状
    • material 物体材质
let geometry = new THREE.SphereGeometry(200, 20, 20)  //形状let material = new THREE.MeshBasicMaterial({ map: texture })  //材质let mesh = new THREE.Mesh(geometry, material)  //物体复制代码
  • 加载图形new THREE.TextureLoader().load(img, callback)
    将上面的图形加载出来
loader.load('./img/land_ocean_ice_cloud_2048.jpg', function (texture) {    let geometry = new THREE.SphereGeometry(200, 20, 20)  //形状    let material = new THREE.MeshBasicMaterial({ map: texture })  //材质    let mesh = new THREE.Mesh(geometry, material)  //物体})复制代码

创建组合

我们有了3D图形,接下来就是将这些图形组合在一起,变成多样的3D界面

创建组合 API:THREE.Group()

//创建一个组合group = new THREE.Group()scene.add(group)  //将组合添加进场景中渲染复制代码

将创建好的3D图形添加进组合中

API:group.add(mesh)

  • mesh 3D物体

运动起来

3D图形已经在场景中渲染出来了,现在,则需要让它们动起来!

function animate() {  // 请求运动帧  requestAnimationFrame(animate)  render()}// 地球旋转逻辑函数function render() {  // 更新性能监视器  stats.update();  camera.position.x += (mouseX - camera.position.x) * 0.05  camera.position.y += (mouseX - camera.position.y) * 0.05  // 拍摄角度, 可改变地球视角  camera.lookAt(scene.position)  // 地球自转速度  group.rotation.y -= 0.005  // 运动核心 递归调用  renderer.render(scene, camera)}复制代码

现在已经基本完成了3D地球的自转

什么是stats.js

说了Three.js,现在聊聊什么是stats.js吧。stats.js 是一个 Three.js 开发的辅助库,通过检测动画运行时的帧数,来测试WebGL代码的运行性能

stats.js使用

准备阶段

类似于Three.js,stats.js也需要引入框架库,并由div来渲染显示性能测试界面

复制代码

开始使用

首先需要初始化stats

// stats性能检测器初始化stats = initStats();function initStats() {  stats = new Stats();  //设置统计模式  stats.setMode(0); // 0: fps, 1: ms  //统计信息显示在左上角  stats.domElement.style.position = 'absolute';  stats.domElement.style.left = '10px';  stats.domElement.style.top = '10px';  //将统计对象添加到对应的
元素中 document.getElementById("stats-output").appendChild(stats.domElement); return stats;}复制代码

当场景变换时,也就是3D运动时,需要实时更新stats检测器 API:stats.update(); 用于地球旋转时,动态更新检测情况

// 地球旋转逻辑函数function render() {  // 更新性能监视器  stats.update();    camera.position.x += (mouseX - camera.position.x) * 0.05  camera.position.y += (mouseX - camera.position.y) * 0.05  // 拍摄角度, 可改变地球视角  camera.lookAt(scene.position)  // 地球自转速度  group.rotation.y -= 0.005  // 核心 递归调用  renderer.render(scene, camera)}复制代码

可以看到两种检测情况 stats.setMode(0); // 0: fps, 1: ms

参数0 显示FPS

stats.setMode(1); // 0: fps, 1: ms
参数1 显示MS

最后优化

1.通过鼠标可控制地球角度

// 绑定鼠标移动事件document.addEventListener('mousemove', onDocumentMouseMove, false)// 监听鼠标移动方向, 从而确定地球南北半球function onDocumentMouseMove(ev) {  ev = ev || event  mouseX = ev.clientX - windowHalfX  mouseY = ev.clientY - windowHalfY}复制代码

2.响应式

可根据窗口大小自动改变渲染图形大小

// 窗口大小改变监听window.addEventListener('resize', onWindowResize, false)// 监听窗口大小, 从而根据窗口大小改变地球大小, 类似响应式function onWindowResize() {  windowHalfX = window.innerWidth / 2  windowHalfY = window.innerHeight / 2  camera.aspect = window.innerWidth / window.innerHeight  camera.updateProjectionMatrix()  renderer.setSize(window.innerWidth, window.innerHeight)}复制代码

好了,现在3D地球就基本上完成了~

完整代码

  
WebGL之3D地球
复制代码

图片素材和js库可以到我的github上下载:

第一次在掘金上发文章,希望大家可以点点赞哈哈~

转载地址:http://pprfo.baihongyu.com/

你可能感兴趣的文章
《SEO的艺术(原书第2版)》——1.5 人们如何搜索
查看>>
经验贴 | 电梯监控的布线技巧
查看>>
研究显示:广告拦截应用正在破坏互联网
查看>>
优云·小课堂 第八期:运维自动化的魅力
查看>>
写个软件来防止服务器网站CPU百分百
查看>>
智能城市里,“公共电话亭”的存在意味着什么?
查看>>
JVM分代垃圾回收策略的基础概念
查看>>
《交互式程序设计 第2版》一3.5 捕获简单用户交互行为
查看>>
安装操作系统需要注意的事项
查看>>
5G技术的5大猜想
查看>>
MongoDB 3.0(1):CentOS7 安装MongoDB 3.0服务
查看>>
别随便安装 Pokemon GO被曝藏恶意后门
查看>>
让数据会思考会说话,为出海企业提供多样化数据智能解决方案
查看>>
我眼中的自动化测试框架设计要点
查看>>
FLIF:自由的无损图像格式
查看>>
Google开源Inception-ResNet-v2,提升图像分类水准
查看>>
Opera 出售细节曝光:昆仑出资1.68亿美元
查看>>
CentOS 5.3 下快速安装配置 PPTP ××× 服务器
查看>>
产品经理学习总结之技术和设计篇
查看>>
23种设计模式(15):备忘录模式
查看>>