本文主要是講解 Three.js 的相關(guān)概念炊邦,幫助大家對 Three.js 以及相關(guān)知識形成比較完整的理解芙粱。
今年來 web 得到了快速的發(fā)展,隨著 HTML5 的普及拴念,網(wǎng)頁的表現(xiàn)能力越來越大钧萍。網(wǎng)頁上已經(jīng)可以做出很多復(fù)雜的動畫,精美的效果政鼠。
在學(xué)習(xí) Three.js 之前风瘦,讓我們先了解一下OpenGL和WebGL。
OpenGL
OpenGL 大概許多人都有所耳聞公般,它是最常用的跨平臺圖形庫万搔。
WebGL
WebGL 是基于 OpenGL 設(shè)計的面向 web 的圖形標準,提供了一系列 JavaScript API官帘,通過這些 API 進行圖形渲染得以利用圖形硬件從而獲得較高性能瞬雹。
Three
Three 是通過對 WebGL 接口的封裝與簡化而形成的一個易用的圖形庫。
簡單點的說法:WebGL 可以看成是瀏覽器給我們提供的接口遏佣,在 javascript 中可以直接用這些 API 進行 3D 圖形的繪制;而 Three.js 就是在這些接口上又幫我們封裝得更好用一些揽浙。
準備工作
開發(fā)環(huán)境
Three.js 是一個 javascript 庫状婶,所以意敛,我們可以使用平時開發(fā) Javascript 應(yīng)用的環(huán)境開發(fā) Three.js 應(yīng)用。
調(diào)試建議使用 Chrome 或者 Firefox 瀏覽器膛虫。如果你使用的是 Firefox草姻,那么Firebug 會是你必不可少的插件;如果你使用的是 Chrome稍刀,那么直接使用控制臺調(diào)試即可撩独。這些和 Javascript 的調(diào)試是相同的。
下載
首先账月,我們需要在 Github 下載 Three.js 的代碼综膀。
下載,我們可以在源碼中局齿,看到 three.js 和 three.min.js 兩個文件剧劝,前者是沒有經(jīng)過代碼壓縮的,因此適用于調(diào)試階段抓歼;后者是經(jīng)過代碼壓縮的讥此,調(diào)試起來會不太方便,但文件較小谣妻,適用于最終的發(fā)布版萄喳。保存一個文件到本地,這里我們選擇 three.js蹋半。
引用
在使用 Three.js 之前他巨,我們需要在 HTML 文件中引用該文件:
<script type="text/javascript" src="three.js"></script>
然后就能通過全局變量THREE訪問到所有屬性和方法了。
Hello湃窍,world闻蛀!
每一個新技術(shù)的學(xué)習(xí),我們都是從 hello您市,world 開始的觉痛,學(xué)習(xí) three.js 我們也不例外。
WebGL 的渲染是需要 HTML5 Canvas元素的茵休,我們可以手動在 HTML 的<body>部分中定義 Canvas 元素薪棒,或者讓 Three.js 幫你生成。這兩種選擇一般沒有多大差別榕莺。
<body onload="init()">
<canvas id="mainCanvas" width="400px" height="300px" ></canvas>
</body>
在JavaScript代碼中定義一個init函數(shù)俐芯,在HTML加載完后執(zhí)行:
function init() {
// ...
}
一個典型的 Three.js 程序至少要包括渲染器(Renderer)、場景(Scene)钉鸯、照相機(Camera)吧史,以及你在場景中創(chuàng)建的物體。這里我們將介紹如何快速地使用這些東西唠雕。
渲染器(Renderer)
渲染器將和 Canvas 元素進行綁定贸营,如果之前在 HTML 中手動定義了 id 為 mainCanvas 的 Canvas 元素吨述,那么 Renderer 可以這樣寫:
var renderer = new THREE.WebGLRenderer({
canvas: document.getElementById('mainCanvas');
});
而如果想要使用 Three.js 生成 Canvas 元素,在 HTML 中就不需要定義 Canvas 元素钞脂,在 Javascript 代碼中可以這樣寫:
var renderer = new THREE.WebGLRenderer();
renderer.setSize(400, 300);
document.getElementByTagName('body')[0].appendChild(renderer.domElement);
上面代碼的第二行表示設(shè)置 Canvas 的寬 400 像素揣云,高 300 像素。第三行將渲染器對應(yīng)的 Canvas 元素添加到<body>中冰啃。
我們可以使用下面的代碼將背景色(用于清除畫面的顏色)設(shè)置為黑色:
renderer.setClearColor(0x000000);
場景(Scene)
在 Three.js 中添加的物體都是添加到場景中的邓夕,因此它相當于一個大容器。一般說阎毅,場景里沒有很復(fù)雜的操作焚刚,在程序最開始的時候進行實例化,然后將物體添加到場景中即可净薛。
var scene = new THREE.Scene();
照相機(Camera)
在介紹照相機設(shè)置前汪榔,我們先來簡單了解下坐標系。WebGL 和 Three.js 使用的坐標系是右手坐標系肃拜,看起來就是這樣的:
這里痴腌,我們定義了一個透視投影的照相機。
var camera = new THREE.PerspectiveCamera(45, 4 / 3, 1, 1000);
camera.position.set(0, 0, 5);
scene.add(camera);
值得注意的是燃领,照相機也需要被添加到場景中士聪。
長方體
我們要創(chuàng)建一個x、y猛蔽、z方向長度分別為1剥悟、2、3的長方體曼库,并將其設(shè)置為紅色区岗。
var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3),
new THREE.MeshBasicMaterial({
color: 0xff0000
})
);
scene.add(cube);
這段代碼也是比較容易理解的,雖然現(xiàn)在可能還不知道 MeshBasicMaterial 是什么毁枯,但是大致可以猜測出這是一種材質(zhì)慈缔,可以用來設(shè)置物體的顏色。還是要提醒下种玛,一定要記得把創(chuàng)建好的長方體添加到場景中藐鹤。
那么這里長度為1的單位是什么呢?這里的長度是在物體坐標系中的赂韵,其單位與屏幕分辨率等無關(guān)娱节,簡單地說,它就是一個虛擬空間的坐標系祭示,1代表多少并沒有實際的意義肄满,而重要的是相對長度。
渲染
在定義了場景中的物體,設(shè)置好的照相機之后稠歉,渲染器就知道如何渲染出二維的結(jié)果了讥电。這時候,我們只需要調(diào)用渲染器的渲染函數(shù)轧抗,就能使其渲染一次了。
renderer.render(scene, camera);
渲染效果圖:
OK瞬测,我們前面已經(jīng)簡單快速的講了一下如何快速搭建横媚,下面讓我們來講下 Three.js 中的一些概念:
我們要在屏幕上展示 3D 圖形,思路大體上是這樣子的月趟。
構(gòu)建一個三維控件:
1灯蝴、Three 中稱之為場景(Scene)選擇一個觀察點,并確定觀察方向/角度等 孝宗;
2穷躁、Three 中稱之為相機(Camera)在場景中添加供觀察的物體 ;
3因妇、Three 中的物體有很多種问潭,包括 Mesh, Line, Points等,它們都繼承自 Object3D 類將觀察到的場景渲染到屏幕上的指定區(qū)域 婚被;
4狡忙、Three 中使用 Renderer 完成這一工作。
Scene
場景是所有物體的容器址芯,也對應(yīng)著我們創(chuàng)建的三維世界灾茁。
Camera 坐標系
Camera 是三維世界中的觀察者,為了觀察這個世界谷炸,首先我們要描述空間中的位置北专。
三維投影
Three 中的相機有兩種旬陡,分別是正交投影相機 THREE.OrthographicCamera 和透視投影相機 HREE.PerspectiveCamera拓颓。
正交投影與透視投影的區(qū)別如上圖所示,左圖是正交投影季惩,物體發(fā)出的光平行地投射到屏幕上录粱,遠近的方塊都是一樣大的;右圖是透視投影画拾,近大遠小啥繁,符合我們平時看東西的感覺。
正交投影相機
注:圖中的”視點”對應(yīng)著 Three 中的 Camera青抛。
這里補充一個視景體的概念:視景體是一個幾何體旗闽,只有視景體內(nèi)的物體才會被我們看到,視景體之外的物體將被裁剪掉。這是為了去除不必要的運算适室。
正交投影相機的視景體是一個長方體嫡意,OrthographicCamera 的構(gòu)造函數(shù)是這樣的:OrthographicCamera( left, right, top, bottom, near, far )
Camera本身可以看作是一個點,left 則表示左平面在左右方向上與 Camera 的距離捣辆。另外幾個參數(shù)同理蔬螟。于是六個參數(shù)分別定義了視景體六個面的位置。
可以近似地認為汽畴,視景體里的物體平行投影到近平面上旧巾,然后近平面上的圖像被渲染到屏幕上。
透視投影相機
透視投影相機的視景體是個四棱臺忍些,它的構(gòu)造函數(shù)是這樣的:PerspectiveCamera( fov, aspect, near, far )
fov 對應(yīng)著圖中的視角鲁猩,是上下兩面的夾角。aspect 是近平面的寬高比罢坝。在加上近平面距離 near廓握,遠平面距離 far,就可以唯一確定這個視景體了嘁酿。
透視投影相機很符合我們通常的看東西的感覺隙券,因此大多數(shù)情況下我們都是用透視投影相機展示3D效果。
Objects
有了相機闹司,總需要看點什么吧是尔?這個時候我們就可以在場景中添加一些物體了。
Three 中供顯示的物體有很多开仰,它們都繼承自 Object3D 類拟枚,這里我們主要看一下 Mesh 和 Points 兩類。
Mesh
我們都知道众弓,計算機的世界里恩溅,一條弧線是由有限個點構(gòu)成的有限條線段連接得到的。線段很多時谓娃,看起來就是一條平滑的弧線了脚乡。
計算機中的三維模型也是類似的,普遍的做法是用三角形組成的網(wǎng)格來描述滨达,我們把這種模型稱之為Mesh模型奶稠。
這是那只著名的斯坦福兔子。它在 3D 圖形中的地位與數(shù)字圖像處理領(lǐng)域中著名的 lena 是類似的捡遍。
看這只兔子锌订,隨著三角形數(shù)量的增加,它的表面越來越平滑/準確画株。
在 Three 中辆飘,Mesh 的構(gòu)造函數(shù)是這樣的:Mesh( geometry, material )
geometry 是它的形狀啦辐,material 是它的材質(zhì)。
不止是 Mesh蜈项,創(chuàng)建很多物體都要用到這兩個屬性芹关。下面我們來看看這兩個重要的屬性。
Geometry
Geometry 形狀紧卒,相當直觀侥衬。Geometry 通過存儲模型用到的點集和點間關(guān)系(哪些點構(gòu)成一個三角形)來達到描述物體形狀的目的。
Three 提供了立方體(其實是長方體)跑芳、平面(其實是長方形)浇冰、球體、圓形聋亡、圓柱、圓臺等許多基本形狀际乘;
我們也可以通過自己定義每個點的位置來構(gòu)造形狀坡倔;
對于比較復(fù)雜的形狀,我們還可以通過外部的模型文件導(dǎo)入脖含。
Material
Material罪塔,材質(zhì),這就沒有形狀那么直觀了养葵。
材質(zhì)其實是物體表面除了形狀以為所有可視屬性的集合征堪,例如色彩、紋理关拒、光滑度佃蚜、透明度、反射率着绊、折射率谐算、發(fā)光度。
這里講一下材質(zhì)(Material)归露、貼圖(Map)和紋理(Texture)的關(guān)系洲脂。
材質(zhì)上面已經(jīng)提到了,它包括了貼圖以及其它剧包。
貼圖其實是‘貼'和‘圖'恐锦,它包括了圖片和圖片應(yīng)當貼到什么位置。
紋理嘛疆液,其實就是‘圖'了一铅。
Three 提供了多種材質(zhì)可供選擇,能夠自由地選擇漫反射/鏡面反射等材質(zhì)堕油。
Points
講完了Mesh馅闽,我們來看看另一種Object——Points飘蚯。
Points其實就是一堆點的集合,它在之前很長時間都被稱為ParticleSystem(粒子系統(tǒng))福也,r68版本時更名為PointCloud,r72版本時才更名為Points局骤。更名主要是因為,Mr.doob認為暴凑,粒子系統(tǒng)應(yīng)當是包括粒子和相關(guān)的物理特性的處理的一套完整體系峦甩,而Three中的Points簡單得多。因此最終這個類被命名為Points现喳。
Points能夠用來實現(xiàn)的典型效果是這樣的:官方example
Light
神說:要有光凯傲!
光影效果是讓畫面豐富的重要因素。
Three 提供了包括環(huán)境光 AmbientLight嗦篱、點光源 PointLight、 聚光燈 SpotLight灸促、方向光 DirectionalLight诫欠、半球光HemisphereLight 等多種光源。
只要在場景中添加需要的光源就好了浴栽。
Renderer
在場景中建立了各種物體荒叼,也有了光,還有觀察物體的相機典鸡,是時候把看到的東西渲染到屏幕上了被廓。這就是Render做的事情了。
Renderer綁定一個canvas對象萝玷,并可以設(shè)置大小嫁乘,默認背景顏色等屬性。
調(diào)用Renderer的render函數(shù)球碉,傳入scene和camera亦渗,就可以把圖像渲染到canvas中了。