Three.js 入門詳解

本文主要是講解 Three.js 的相關概念,幫助大家對 Three.js 以及相關知識形成比較完整的理解。
今年來 web 得到了快速的發(fā)展,隨著 HTML5 的普及,網(wǎng)頁的表現(xiàn)能力越來越大。網(wǎng)頁上已經(jīng)可以做出很多復雜的動畫,精美的效果。
在學習 Three.js 之前,讓我們先了解一下OpenGL和WebGL。

OpenGL

OpenGL 大概許多人都有所耳聞,它是最常用的跨平臺圖形庫。

WebGL

WebGL 是基于 OpenGL 設計的面向 web 的圖形標準,提供了一系列 JavaScript API,通過這些 API 進行圖形渲染得以利用圖形硬件從而獲得較高性能。

Three

Three 是通過對 WebGL 接口的封裝與簡化而形成的一個易用的圖形庫。

簡單點的說法:WebGL 可以看成是瀏覽器給我們提供的接口,在 javascript 中可以直接用這些 API 進行 3D 圖形的繪制;而 Three.js 就是在這些接口上又幫我們封裝得更好用一些。

準備工作

開發(fā)環(huán)境

Three.js 是一個 javascript 庫,所以,我們可以使用平時開發(fā) Javascript 應用的環(huán)境開發(fā) Three.js 應用。
調試建議使用 Chrome 或者 Firefox 瀏覽器。如果你使用的是 Firefox,那么Firebug 會是你必不可少的插件;如果你使用的是 Chrome,那么直接使用控制臺調試即可。這些和 Javascript 的調試是相同的。

下載

首先,我們需要在 Github 下載 Three.js 的代碼。
下載,我們可以在源碼中,看到 three.js 和 three.min.js 兩個文件,前者是沒有經(jīng)過代碼壓縮的,因此適用于調試階段;后者是經(jīng)過代碼壓縮的,調試起來會不太方便,但文件較小,適用于最終的發(fā)布版。保存一個文件到本地,這里我們選擇 three.js。

引用

在使用 Three.js 之前,我們需要在 HTML 文件中引用該文件:

<script type="text/javascript" src="three.js"></script>

然后就能通過全局變量THREE訪問到所有屬性和方法了。

Hello,world!

每一個新技術的學習,我們都是從 hello,world 開始的,學習 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);

上面代碼的第二行表示設置 Canvas 的寬 400 像素,高 300 像素。第三行將渲染器對應的 Canvas 元素添加到<body>中。
我們可以使用下面的代碼將背景色(用于清除畫面的顏色)設置為黑色:

renderer.setClearColor(0x000000);

場景(Scene)

在 Three.js 中添加的物體都是添加到場景中的,因此它相當于一個大容器。一般說,場景里沒有很復雜的操作,在程序最開始的時候進行實例化,然后將物體添加到場景中即可。

var scene = new THREE.Scene();

照相機(Camera)

在介紹照相機設置前,我們先來簡單了解下坐標系。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的長方體,并將其設置為紅色。

var cube = new THREE.Mesh(new THREE.CubeGeometry(1, 2, 3),
        new THREE.MeshBasicMaterial({
            color: 0xff0000
        })
);
scene.add(cube);

這段代碼也是比較容易理解的,雖然現(xiàn)在可能還不知道 MeshBasicMaterial 是什么,但是大致可以猜測出這是一種材質,可以用來設置物體的顏色。還是要提醒下,一定要記得把創(chuàng)建好的長方體添加到場景中。

那么這里長度為1的單位是什么呢?這里的長度是在物體坐標系中的,其單位與屏幕分辨率等無關,簡單地說,它就是一個虛擬空間的坐標系,1代表多少并沒有實際的意義,而重要的是相對長度。

渲染

在定義了場景中的物體,設置好的照相機之后,渲染器就知道如何渲染出二維的結果了。這時候,我們只需要調用渲染器的渲染函數(shù),就能使其渲染一次了。

renderer.render(scene, camera);

渲染效果圖:


圖片.png

OK,我們前面已經(jīng)簡單快速的講了一下如何快速搭建,下面讓我們來講下 Three.js 中的一些概念:
我們要在屏幕上展示 3D 圖形,思路大體上是這樣子的。
構建一個三維控件:
1、Three 中稱之為場景(Scene)選擇一個觀察點,并確定觀察方向/角度等 ;
2、Three 中稱之為相機(Camera)在場景中添加供觀察的物體 ;
3、Three 中的物體有很多種,包括 Mesh, Line, Points等,它們都繼承自 Object3D 類將觀察到的場景渲染到屏幕上的指定區(qū)域 ;
4、Three 中使用 Renderer 完成這一工作。

Scene

場景是所有物體的容器,也對應著我們創(chuàng)建的三維世界。

Camera 坐標系

Camera 是三維世界中的觀察者,為了觀察這個世界,首先我們要描述空間中的位置。


Three中使用采用常見的右手坐標系定位。
三維投影

Three 中的相機有兩種,分別是正交投影相機 THREE.OrthographicCamera 和透視投影相機 HREE.PerspectiveCamera。


2016090915304040.png

正交投影與透視投影的區(qū)別如上圖所示,左圖是正交投影,物體發(fā)出的光平行地投射到屏幕上,遠近的方塊都是一樣大的;右圖是透視投影,近大遠小,符合我們平時看東西的感覺。

正交投影相機
正交投影相機

注:圖中的”視點”對應著 Three 中的 Camera。
這里補充一個視景體的概念:視景體是一個幾何體,只有視景體內的物體才會被我們看到,視景體之外的物體將被裁剪掉。這是為了去除不必要的運算。
正交投影相機的視景體是一個長方體,OrthographicCamera 的構造函數(shù)是這樣的:OrthographicCamera( left, right, top, bottom, near, far )
Camera本身可以看作是一個點,left 則表示左平面在左右方向上與 Camera 的距離。另外幾個參數(shù)同理。于是六個參數(shù)分別定義了視景體六個面的位置。
可以近似地認為,視景體里的物體平行投影到近平面上,然后近平面上的圖像被渲染到屏幕上。

透視投影相機
透視投影相機

透視投影相機的視景體是個四棱臺,它的構造函數(shù)是這樣的:PerspectiveCamera( fov, aspect, near, far )
fov 對應著圖中的視角,是上下兩面的夾角。aspect 是近平面的寬高比。在加上近平面距離 near,遠平面距離 far,就可以唯一確定這個視景體了。
透視投影相機很符合我們通常的看東西的感覺,因此大多數(shù)情況下我們都是用透視投影相機展示3D效果。

Objects

有了相機,總需要看點什么吧?這個時候我們就可以在場景中添加一些物體了。
Three 中供顯示的物體有很多,它們都繼承自 Object3D 類,這里我們主要看一下 Mesh 和 Points 兩類。

Mesh

我們都知道,計算機的世界里,一條弧線是由有限個點構成的有限條線段連接得到的。線段很多時,看起來就是一條平滑的弧線了。
計算機中的三維模型也是類似的,普遍的做法是用三角形組成的網(wǎng)格來描述,我們把這種模型稱之為Mesh模型。


2016090915304143.jpg

這是那只著名的斯坦福兔子。它在 3D 圖形中的地位與數(shù)字圖像處理領域中著名的 lena 是類似的。
看這只兔子,隨著三角形數(shù)量的增加,它的表面越來越平滑/準確。
在 Three 中,Mesh 的構造函數(shù)是這樣的:Mesh( geometry, material )
geometry 是它的形狀,material 是它的材質。
不止是 Mesh,創(chuàng)建很多物體都要用到這兩個屬性。下面我們來看看這兩個重要的屬性。

Geometry

Geometry 形狀,相當直觀。Geometry 通過存儲模型用到的點集和點間關系(哪些點構成一個三角形)來達到描述物體形狀的目的。
Three 提供了立方體(其實是長方體)、平面(其實是長方形)、球體、圓形、圓柱、圓臺等許多基本形狀;
我們也可以通過自己定義每個點的位置來構造形狀;
對于比較復雜的形狀,我們還可以通過外部的模型文件導入。

Material

Material,材質,這就沒有形狀那么直觀了。
材質其實是物體表面除了形狀以為所有可視屬性的集合,例如色彩、紋理、光滑度、透明度、反射率、折射率、發(fā)光度。
這里講一下材質(Material)、貼圖(Map)和紋理(Texture)的關系。
材質上面已經(jīng)提到了,它包括了貼圖以及其它。
貼圖其實是‘貼'和‘圖',它包括了圖片和圖片應當貼到什么位置。
紋理嘛,其實就是‘圖'了。
Three 提供了多種材質可供選擇,能夠自由地選擇漫反射/鏡面反射等材質。

Points

講完了Mesh,我們來看看另一種Object——Points。
Points其實就是一堆點的集合,它在之前很長時間都被稱為ParticleSystem(粒子系統(tǒng)),r68版本時更名為PointCloud,r72版本時才更名為Points。更名主要是因為,Mr.doob認為,粒子系統(tǒng)應當是包括粒子和相關的物理特性的處理的一套完整體系,而Three中的Points簡單得多。因此最終這個類被命名為Points。
Points能夠用來實現(xiàn)的典型效果是這樣的:官方example

Light

神說:要有光!
光影效果是讓畫面豐富的重要因素。
Three 提供了包括環(huán)境光 AmbientLight、點光源 PointLight、 聚光燈 SpotLight、方向光 DirectionalLight、半球光HemisphereLight 等多種光源。
只要在場景中添加需要的光源就好了。

Renderer

在場景中建立了各種物體,也有了光,還有觀察物體的相機,是時候把看到的東西渲染到屏幕上了。這就是Render做的事情了。
Renderer綁定一個canvas對象,并可以設置大小,默認背景顏色等屬性。
調用Renderer的render函數(shù),傳入scene和camera,就可以把圖像渲染到canvas中了。

參考資料:
圖靈社區(qū)維基百科

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 之前用qunee做了一個2.5d的機房監(jiān)控,丑的閃瞎我的卡姿蘭大眼,后來含淚用three.js做個3d的換...
    我得有妖氣閱讀 1,701評論 1 2
  • react vr中文網(wǎng):www.vr-react.com react vr qq群:481244084 示例源碼 ...
    liu_520閱讀 3,943評論 4 6
  • Three.js是一個3DJavaScript庫,基于右手坐標系,可以創(chuàng)建簡單或是比較復雜的三維圖形并應用豐富多彩...
    呆呆的木木閱讀 25,064評論 42 59
  • 看完許士林的自白。我忽然想了解白娘子的故事。雖然早已經(jīng)看過了電視劇。我又去把它翻了一遍。這是個從南宋流傳至今的一個...
    秋笏笑月閱讀 503評論 0 0
  • 最近實在窮逼到不行,不得不重操舊業(yè),在論壇找了半天聯(lián)系了一個小學生作業(yè)輔導班,電話簡單詢問以后約了見面時間簡單面試...
    coatbeer閱讀 202評論 0 0

友情鏈接更多精彩內容