利用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

时间: 2024-10-03 22:41:52

利用javascript和WebGL绘制地球 【翻译】的相关文章

利用JavaScript打印出Fibonacci数(不使用全局变量)

从汤姆大叔的博客里看到了6个基础题目:本篇是第4题 - 利用JavaScript打印出Fibonacci数(不使用全局变量) 解题关键: 1.Fibonacci数列的规律 2.递归 解点1:Fibonacci数列的规律 1,1,2,3,5,6,13,19,32.... //从第3项开始,每项都是前两项之和 解点2:递归 递归是一个复杂的概念,此题可以不用递归解决,但题目要求不能使用全局变量,所以我只能想到递归方法.简单的说,递归就是函数调用函数本身,但递归一定要有一个出口,否则就无限调用下去……

利用JavaScript如何创建一个table表格[第2种方法]

创建一个五行五列的表格(使用循环) <style> td{border:1px solid #ccc;} </style> <script> window.onload=function(){ var oTable=document.createElement("table"); var row; var cell; for(var i=0;i<5;i++){ row=document.createElement("tr")

JavaScript网站设计实践(四)编写about.html页面,利用JavaScript和DOM,选择性的显示和隐藏DIV元素

一.现在我们在网站设计(三)的基础上,来编写about.html页面. 这个页面要用到的知识点是利用JavaScript和DOM实现选择性地显示和隐藏某些DIV about.html页面在前面我们为了看导航栏菜单项高亮显示时,已经写了部分内容,只是那时写的代码没有实现div显示和隐藏,现在就在之前编写的基础上,为页面添加显示和隐藏div的效果. 没有写JavaScript之前看到的效果: 实现后的效果图: 这个就是我们现在要做的效果. 1.背景: 我们在about.html页面中写了一个ul列表

利用 JavaScript SDK 部署网页版“Facebook 登录”

利用 JavaScript SDK 部署网页版"Facebook 登录" 通过采用 Javascript 版 Facebook SDK 的"Facebook 登录",用户可以使用 Facebook 凭据登录您的网页.即使您因为一些原因而无法使用我们的 JavaScript SDK,也一样可以实施"Facebook 登录". 要在不使用 JavaScript SDK 的情况下实施"Facebook 登录",请参阅手动构建登录流程

[ASP.NET] 如何利用javascript分割檔案上傳至後端合併

最近研究了一下如何利用javascript進行檔案分割上傳並且透過後端.特地記錄一下相關的用法 先寫限制跟本篇的一些陷阱 1.就是瀏覽器的支援了 因為本篇有用到blob跟webworker 在ie中需要最少10版以上才有支援以下的方法喔! 2.因為我這是簡單的測試,所以我是將檔案存放在Session當中,實際要使用的話.應該會是將檔案分割存放在檔案系統中 廢話就不多說,我們先來看js端的程式碼 self.onmessage = function (e) { ////web worker star

利用JavaScript如何创建一个table表格

创建Table标签和定义表格头部份代码: window.onload=function(){ var arr=["编号","性别","姓名","年龄"]; var oDatas=[ { "id":1 , "gender":"男", "name" : "Javascript" , "age":30 }, { &

利用JavaScript通过单选框radio控制div的显示和隐藏

通过鼠标单击单选框的动作,实现某个div或多个div的显示和隐藏.实例如下: JavaScript代码如下: 1 function divClick(){ 2 3 var show = ""; 4 show = $("input[name='AdPrintMode']:checked").val(); 5 switch (show){ 6 case '1': 7 document.getElementById("img1").style.disp

利用JavaScript选择GridView行

利用JavaScript选择GridView行 本篇技巧和诀窍记录的是:利用JavaScript选择GridView行. 当我们想在GridView中添加删除.选择功能时,我们通常的做法是利用模板功能在每行添加一个按钮控件或者超链接按钮控件,单击按钮利用RowCommand获取每行的ID. 下面我们利用JavaScript完成这一功能. 我们可以通过调用JavaScirpt函数改变单击的行的背景颜色来模拟选择的行,这里需要声明一个隐藏字段,从JS中获得选取GridView行的ID.在选择/删除事

利用javascript设置图片等比例缩小

网站的内容页面,经常要放图片,如果图片太大会撑出,影响页面美观.如果只是用css限 制图片的最大宽度,会引起图片的变形,本文建议还是用js来实现,实现方式如下: <script language="javascript" type="text/javascript"> window.onload = function () { //判断图片大小,超过一定宽度,要通过js定义图片大小 $.each($(".sec-content img"