WebGL,Three.js 實作3D 地球模型
利用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中工作的資訊,可以點選這裡)
- 通過
方法設定camera的位置, 這個方法需要攜帶一個次元(x, y, z)參數對象, 可能你已經想到了, 我們将會使用這個camera去定位我們的3D對象,本教程中的3D對象就是我們的地球模型。position.set
- 接下來設定我們的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
作者:Ziv小威
出處:http://imziv.com/
關于作者:專注于Java技術的程式員一枚,此外對JS開發保持着較高的興趣。愛好音樂,閱讀,FM等等。
本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接。
如有問題,可以郵件:[email protected]
微網誌:Ziv小威