利用javascript和WebGL绘制地球 【翻译】
利用javascript和WebGL绘制地球 【翻译】
原翻译:利用javascript和WebGL绘制地球 【翻译】
在我们所有已知的HTML5API中,WebGL可能是最有意思的一个,利用这个API我们能够在浏览器中创造出炫酷3D场景的能力。本文将完整的向你展示一些炫酷是如何实现的。
需要特别指出的是,这篇教程我们将会构建一个地球行星模型,这个模型可以像一个兴奋的人一样环绕的旋转,另外,它可能使我们可以获得一些其他程序员的称赞,好吧,就这么多了。
准备
这篇教程我们将会用到一个令人着迷的WebGL插件:three.js. 这个插件跟JQuery有点像,不过它是针对WebGL的,它将很多复杂的原生API访问接口进行了抽象,从而让我们可以更轻易的利用WebGL的特性。
在HTML中,我们的可以通过正常的script标签引入这个插件,如下:
<script src="//cdnjs.cloudflare.com/ajax/libs/three.js/r63/three.min.js"></script>
此处我们引用的是CDN版本,如果你有必要,可以使用本地的方法引入。然后我们需要确保WebGL有东西可以在上面进行渲染。这里我们有个灵活的做法:我们可以直接将一般的Div或者Canvas写到HTML中,或者我们可以另外用JS创建并且追加canvas元素到Dom里后再去渲染。这里我们采用第一种容易点的方法,如下:
<body>
<div id="container"></div>
<script src="earth.js"></script>
</body>
添加完script标签连接到Dom中后,我们的HTML部分差不多就完成了。
下一步
Tree.js本身是趋向把东西做的非常接近真实的3D桌面程序的。我们拥有一个场景,有一些东西现场直播,然后通过摄像机去浏览,然后有些灯光,特效,渲染在整场景上面,当然他们自身也全都是3D对象。这个场景的元素列表似乎有点吓人,在我们的earth.js文件里,所有的这些元素都可以当成形状变量,Javascript文件如下:
var scene,
camera,
light,
renderer,
earthObject;
var WIDTH = window.innerWidth - 30,
HEIGHT = window.innerHeight - 30;
var angle = 45,
aspect = WIDTH / HEIGHT,
near = 0.1,
far = 3000;
有些额外的变量也定义在这里了,WIDTH,HEIGHT 变量用来获取我们画布的宽与高,下面的其他变量之后将会用来设置我们相机的位置。对于几乎所有的3D对象来说,所有这些元素都是共通的,无论是平台还是环境,所以在这里我们习惯性的将这些家伙写到一起。然而利用Three.js我们可以轻松的实现,我们将看看所有这些元素是如何在同一时刻融合到项目中的。
环境
首先,我们需要启用新变量并初始化他们,从而使我们的地球模型可以展示的更炫。我们可以先设置每个处理环境因素的变量:
var container = document.getElementById('container');
camera = new THREE.PerspectiveCamera(angle, aspect, near, far);
camera.position.set(0, 0, 0);
scene = new THREE.Scene();
light = new THREE.SpotLight(0xFFFFFF, 1, 0, Math.PI / 2, 1);
light.position.set(4000, 4000, 1500);
light.target.position.set (1000, 3800, 1000);
下面是针对上面代码执行情况的描述:
- 在我们的HTMl中抓取container对象
- 我们用之前声明的变量设置camera对象(更多关于cameras是如何在3D中工作的信息,可以点击这里)
- 通过
position.set
方法设置camera的位置, 这个方法需要携带一个维度(x, y, z)参数对象, 可能你已经想到了, 我们将会使用这个camera去定位我们的3D对象,本教程中的3D对象就是我们的地球模型。 - 接下来设置我们的light对象。如果没有light对象做渲染的话,那么整个模型出来的效果将会是一片漆黑,所以我们必须细心的注意这一步骤。Three.js的SpotLight object对象拥有与我们的camera对象大致相同的参数,只不过这个对象的第一个参数colour必须为十六进制的值,然后剩余的其他参数与camera基本相同。
- 最后,我们需要设置我们的画布对象renderer.另外一个需要确保的点则是:我们需要提前将画布对象完整的渲染到了屏幕上,再次强调,如果没有完成这一步,那么整个画布将会什么也看不见,一片漆黑。我们给画布添加了去锯齿效果,并且将这个效果作为Dom元素添加到我们的原始容器中。
现在我们需要通过将整个地球粘贴在网上一样的方式来构建自身整个模型。代码如下:
var earthGeo = new THREE.SphereGeometry (30, 40, 400),
earthMat = new THREE.MeshPhongMaterial();
var earthMesh = new THREE.Mesh(earthGeo, earthMat); earthMesh.position.set(-100, 0, 0);
earthMesh.rotation.y=5;
scene.add(earthMesh);
在这里我们创建了一个网状(Mesh)对象,这个网状是一种可以被用来装扮并看起来像地球形状的对象,然后给这个对象添加一些几何结构,外观包装,或者一些有质感的材料来包裹这个网状体。我们同样会将这个对象设置适当的在位置,与其他参数对象一样,我们会并且将Mesh对象添加到我们的场景(scene)中。
如下有个样例。这里面有些额外的渲染效果,稍后我们将会讲解。这个样例看起来离我们想要的越来越近了。
蓝色星球
接下来有趣的部分是给这个家伙制作皮肤。首先我们将会使用一张漫反射贴图,它会让这个家伙看起来更像个地图。你可以像下面的方式一样添加:
// diffuse map
earthMat.map = THREE.ImageUtils.loadTexture('images/earthmap1k.jpg');
如果你想要质感更好些的话,你可以尝试用这个图片,或者你可以去google搜索一张你想要的图片都行。高分辨率的图都可以。
现在这个模型看起来没那么糟糕了,但是我们仍然可以通过引用一点地形描绘的方式,使整个模型看起来更真实些。这个地球有一些高山,为了确保区分太阳系的其他星球,我们需要使用凹凸地图(bump map), 在3D模型中, 凹凸地图是黑白图,使用鲜明的白色去凸显图像凹凸不平的部分(例如我们示例中的:山脉)。
// bump map
earthMat.bumpMap = THREE.ImageUtils.loadTexture('images/elev_bump_16ka.jpg');
earthMat.bumpScale = 8;
使用上面的图片我们差不多达到了效果,再次强调,使用过Google搜索“Earth bump map”会获得大量的选择,但是如果你感觉都不好的话,你可以点击这个连接。 运行了以上的代码,我们将会看到如下效果:
让它转起来!
接下来剩余的事情就是我们给这个地球模型添加一些动画效果,为此,我们需要两个新的方法,我们命名为render()
和animate()
function animate() {
requestAnimationFrame(animate);
render();
}
我们的animate()
方法并不是很复杂,通过自身递归连续的调用requestAnimationFrame()
方法,anmiate()
会请求我们的render()
方法,让我们看看render()
方法的代码:
function render() {
var clock = new THREE.Clock(),
delta = clock.getDelta();
earthMesh.rotation.y += rotationSpeed * delta;
renderer.render(scene, camera);
}
我们看看上面的代码做了些什么工作。每次render()
方法被请求,它便会让地球模型在y轴上缓缓的转动起来(此处你可以选择设置任意的转动次数,我们在这里利用getDelta()
方法构建一个时钟对象来控制转动次数,当然你可以不使用这种方法)。然后render()
方法会执行清理画布操作,这是防止画布乱掉很重要的步骤,最后它会渲染我们的场景(以及场景对象中的其他所有对象)和我们的camera对象。
最后
当然,拥有拖拽操作会让我们的地球模型的体验更好,OrbitControls.js是一个可以为我们地球模型提供鼠标驱动旋转效果能力的脚本,并且它为我们的平流层里添加一些星星或者云作为地球模型的背景同样也并不困难,如果你并不嫌麻烦的话,你甚至可以利用WebGL的着色器(shaders)为你的星球添加一个平流层。
运行代码,你可以看到一个样例,在CodePen中最终的Demo如下:
通过按住鼠标拖动和滚动鼠标滑轮来查看效果(或者点击此处demo
结尾
WebGL和Three.js变得越发的具有挑战性,因为他们偶尔会要求我们要像3D艺术家一样,利用场景,画布,camera去完成我们的工作,最终的结果就是做出了一些加令人印象深刻的东西。如果你专注于在这个技术上的话,你可以通过在浏览器中使用3D特性创造出一些有趣的可能性。如果坚持它,相信不久你就很可能获取一些非凡的成绩。
原文地址:Building the Earth with WebGL and JavaScript
利用javascript和WebGL绘制地球 【翻译】的更多相关文章
- WebGL绘制有端头的线
关于WebGL绘制线原理不明白的小伙伴,可以看看我之前的文章WebGL绘制有宽度的线.这一篇我们主要来介绍端头的绘制,先看效果图. 端头一般被称为lineCap,主要有以下三种形式: butt最简单等 ...
- WebGL绘制有宽度的线
WebGL中有宽度的线一直都是初学者的一道门槛,因为在windows系统中底层的渲染接口都是D3D提供的,所以无论你的lineWidth设置为多少,最终绘制出来的只有一像素.即使在移动端可以设置有宽度 ...
- 利用Javascript判断操作系统的类型实现不同操作系统下的兼容性
原文地址 http://www.jb51.net/article/33640.htm 在通过Javascript实现客户端和服务端的交互时,有时候需要对操作系统进行判断,以便实现不同操作系统下的兼容性 ...
- 利用JavaScript函数对字符串进行加密
加密.解密问题对我来说一直是很神秘的,感到神奇无比. 理论了解 前段时间看到关于利用JavaScript函数unescape()和escape()对字符串进行替换处理.通过查资料得知, escape( ...
- ligerui_ligerTree_002_利用JavaScript代码配置ligerTree节点
利用JavaScript代码配置ligerTree节点: 源码地址:http://download.csdn.net/detail/poiuy1991719/8571255 效果图: <%@ p ...
- JavaScript网站设计实践(四)编写about.html页面,利用JavaScript和DOM,选择性的显示和隐藏DIV元素
一.现在我们在网站设计(三)的基础上,来编写about.html页面. 这个页面要用到的知识点是利用JavaScript和DOM实现选择性地显示和隐藏某些DIV about.html页面在前面我们为了 ...
- 如何利用JavaScript遍历JSON数组
1.设计源码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www. ...
- 利用JavaScript去掉数组中重复项
利用JavaScript的object的特性,我们可以非常容易的实现将一个数组的重复项去掉. object的特性是:key一定是唯一的. 把数组重复项去掉: 1 将数组转换成一个object对象,数组 ...
- [ASP.NET] 如何利用Javascript分割檔案上傳至後端合併
最近研究了一下如何利用javascript進行檔案分割上傳並且透過後端.特地記錄一下相關的用法 先寫限制跟本篇的一些陷阱 1.就是瀏覽器的支援了 因為本篇有用到blob跟webworker 在ie中需 ...
随机推荐
- MySQL 强制操作以及order by 使用
我们以MySQL中常用的hint来进行详细的解析,如果你是经常使用Oracle的朋友可能知道,Oracle的hincvt功能种类很多,对于优化sql语句提供了很多方法. 同样,在MySQL里,也有类似 ...
- Wing IDE 5 的破解
Wing IDE 百度百科 1.安装好Python,已测的是Python 2.7.10: 2.新建一个py文件CalcActivationCode.py(名字自己随便取): 3.CalcActivat ...
- [windows]禁止指定用户使用远程桌面服务登录
windows2003下禁止用户远程登录的方法如下: 1.打开控制面板 > 管理工具 > 本地安全策略 2.安全策略-->本地策略-->用户权限分配-->通过终端服务拒绝 ...
- 《只是为了好玩:Linux之父林纳斯自传》
<只是为了好玩:Linux之父林纳斯自传> 基本信息 作者: (美)Linus Torvalds David Diamond 译者: 陈少芸 出版社:人民邮电出版社 ISBN:978 ...
- 【SQL查询】集合查询之INTERSECT
[SQL查询]集合查询之INTERSECT 1 BLOG文档结构图 2 前言部分 2.1 导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~ ...
- try catch finally 用法
trycatchfinally 1.将预见可能引发异常的代码包含在try语句块中.2.如果发生了异常,则转入catch的执行.catch有几种写法:catch这将捕获任何发生的异常.catch(Exc ...
- python datetime模块参数详解
Python提供了多个内置模块用于操作日期时间,像calendar,time,datetime.time模块,它提供 的接口与C标准库time.h基本一致.相比于time模块,datetime模块的接 ...
- FZU 1608 Huge Mission(线段树)
Problem 1608 Huge Mission Time Limit: 1000 mSec Memory Limit : 32768 KB Problem Description Oaiei ...
- android使用微软雅黑字体
android使用微软雅黑字体,需要下载字体 ttf文件 下载地址:http://download.csdn.net/detail/xiaoliu123586/9049815 放在assert,然后引 ...
- Centos7 配置网络步奏详解
Centos7 配置网络步奏详解 编辑网卡配置文件 vi /etc/sysconfig/network-script/ifcfg-ens01 备注:这里的ens01不是所有系统都叫这个,有的可能叫其他 ...