開始使用 Three.js

Paul Lewis

簡介

我曾使用 Three.js 進行部分實驗,並且能夠輕鬆在瀏覽器中運用 3D 功能。可讓您建立相機、物件、光源和材料等,並從中選擇轉譯器,這表示,您可以決定是否要使用 HTML 5 的畫布、WebGL 或 SVG 來繪製場景。由於是開放原始碼 您甚至可以參與這項專案但現在,我將著重說明我所學到的知識,並將重點放在引擎上 並介紹一些基本概念

對於 Three.js 的強大之處,有時您可能遇到困難。一般來說,您會需要耗費大量時間處理這些範例,進行反向工程,且在某些情況下 (其實是) 尋找特定功能,偶爾會透過 GitHub 提問。順帶一提,如果您想提問,我發現 doobAlteredQualia 的老師非常有幫助。

1. 基本概念

我假設您至少具備 3D 相關知識,並熟悉 JavaScript 的合理程度。如果您不評估,那可能值得一試,然後再嘗試運用這些內容,以免混淆。

我們會在 3D 環境中提供下列內容,引導你完成建立程序:

  1. 場景
  2. 轉譯器
  3. 相機
  4. 一或兩項 (含材料)

當然,您也可以做一些有趣的事,我相信您將馬上開始研究, 並開始在瀏覽器中體驗 3D 效果。

2. 支援

在瀏覽器中提供支援服務的簡短注意事項。Google 的 Chrome 瀏覽器,就我的經驗而言,最適合搭配使用的轉譯器和基礎 JavaScript 引擎是最適合的處理瀏覽器。Chrome 支援 Canvas、WebGL 和 SVG,速度飛快。從第 4 版開始,Firefox 便迎來了近一步JavaScript 引擎的觸控速度似乎比 Chrome 慢,但它對轉譯技術的支援也相當不錯。Opera 和 Safari 目前正在開發 WebGL 支援功能,但目前版本只支援畫布。Internet Explorer (第 9 版以上) 僅支援畫布轉譯,但我從未聽說 Microsoft 打算新增 WebGL 功能。

3. 背景脈絡介紹

我們認為您已選擇支援所有算繪技術的瀏覽器,並想使用畫布或 WebGL 進行算繪,因為比較標準選擇。Canvas 比 WebGL 更為廣泛,但值得注意的是,WebGL 在圖形卡的 GPU 上執行,這表示 CPU 可集中處理其他非轉譯工作,例如任何嘗試執行的物理或使用者互動。

無論您選擇的轉譯器為何,請務必留意 JavaScript 需要針對效能進行最佳化調整。對瀏覽器來說 3D 並不是簡單的任務 (這真的是不可能),因此請務必瞭解程式碼中任何瓶頸,如果可以的話,請加以移除!

因此,假設您已下載並在 HTML 檔案中納入了 3.js,接著該如何設定場景?如下所示:

// set the scene size
var WIDTH = 400,
HEIGHT = 300;

// set some camera attributes
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;

// get the DOM element to attach to
// - assume we've got jQuery to hand
var $container = $('#container');

// create a WebGL renderer, camera
// and a scene
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera(
                VIEW_ANGLE,
                ASPECT,
                NEAR,
                FAR );

var scene = new THREE.Scene();

// the camera starts at 0,0,0 so pull it back
camera.position.z = 300;

// start the renderer
renderer.setSize(WIDTH, HEIGHT);

// attach the render-supplied DOM element
$container.append(renderer.domElement);

不要太難處理了,真的!

4. 建立網格

所以我們有場景、相機和轉譯器 (我在範例程式碼中選擇採用 WebGL ),但實際上沒有繪製內容。Three.js 實際上支援載入數種不同的標準檔案類型,如果您是從 Blender、Maya、Cinema4D 或其他檔案輸出模型,這個選項就非常實用。為了確保一切輕而易舉 (這一切就是從頭起步!)我會介紹基本功能基本是幾何網格,也就是球體、平面、立方體和圓柱等相對基本的網格。Three.js 可讓您輕鬆建立這些原始物件:

// set up the sphere vars
var radius = 50, segments = 16, rings = 16;

// create a new mesh with sphere geometry -
// we will cover the sphereMaterial next!
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(radius,
segments,
rings),

sphereMaterial);

// add the sphere to the scene
scene.add(sphere);

所有內容都沒問題,但有關球體的材料,該怎麼辦?在程式碼中,我們使用了 sphereMaterial 變數,但尚未定義。首先,我們需要深入介紹材料

5. 材質

毫無疑問地,這是 Three.js 最實用的部分之一。本指南提供許多可套用至網格的常見 (且非常實用) 材質:

  1. 「基本」:代表其顯示「未亮」
  2. 蘭伯特
  3. 乒乓球

我還將介紹更多相關做法,但為了方便起見,我會帶你去發掘這些東西。如果使用 WebGL,特別是這些材料可助您一臂之力。原因何在?因為在 WebGL 中,您必須編寫所有轉譯內容的著色器。著色器本身是一大主題,但簡而言之,這些都是以 GLSL (OpenGL 著色器語言) 編寫而成,用於告訴 GPU 應如何呈現特定內容。這表示您需要模擬光線、反射等的數學運算。這可能很快就會變得非常複雜。有 Three.js 的話,您就不必這麼做,因為 Three.js 會為您簡化作業。然而,如果您想編寫著色器,也可以使用網格 ShaderMaterial 達成上述目標,因此採用彈性設定。

不過,現在我們先將檯燈材質套用至球體:

// create the sphere's material
var sphereMaterial = new THREE.MeshLambertMaterial(
{
// a gorgeous red.
color: 0xCC0000
});

值得一提的是,當您在建立顏色以外的材質時 (如平滑或環境地圖),還可以指定其他屬性。建議您前往維基頁面,瞭解您可以在材料上設定的各種屬性,事實上,您也可以瞭解引擎為您提供的任何物件。此外,最近您可以採用 threejs.org 的 API,以更具吸引力的 API 檢視。

6. 燈光!

如果現在要轉譯場景,系統會顯示紅色圓圈,雖然我們已經套用了蘭伯特材質,但場景中並未套用任何光源,因此根據預設,Three.js 會還原為全環境光源,與平坦色彩相同。讓我們用簡單的光源解決這個問題:

// create a point light
var pointLight = new THREE.PointLight( 0xFFFFFF );

// set its position
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;

// add to the scene
scene.add(pointLight);

7. 算繪

我們現在已完成所有設定,可以獲得優異的轉譯效果。但我們確實該這麼做

// draw!
renderer.render(scene, camera);

不過,您可能會想要多次轉譯,因此,如果要執行迴圈,請確實使用 requestAnimationFrame;這是在瀏覽器中處理動畫最聰明的方法。因為我們尚未完全受到支援,因此建議您查看 Paul Ireland 的相關資料

8. 常見物件屬性

如果您花一些時間查看 Three.js 的程式碼,就會看到許多 Object3D「沿用」的物件。這是基本物件,包含一些非常有用的屬性,例如 positionrotationscale 資訊。具體來說,我們的 360 網格是繼承自 Object3D 的網格,這個網格會新增專屬的屬性:幾何圖形材質。為何提到這些圖示?您不可能想在螢幕上出現完全沒有作用的球體。這些屬性可讓您即時處理網格和材料的基礎細節,因此值得調查。

// sphere geometry
sphere.geometry

// which contains the vertices and faces
sphere.geometry.vertices // an array
sphere.geometry.faces // also an array

// its position
sphere.position // has x, y and z properties
sphere.rotation // same
sphere.scale // ... same

9. 冷門秘密

我只是想快速指出 Three.js 的快速方法。舉例來說,如果您修改網格的端點,就會發現轉譯迴圈中不會有任何變化。原因何在?而 Three.js (就我所能說的) 會快取網格資料來做為最佳化的一環。實際上,您需要向 Three.js 標記有變更的項目,以便重新計算需要的任何項目。方法是使用以下功能:

// changes to the vertices
sphere.geometry.__dirtyVertices = true;

// changes to the normals
sphere.geometry.__dirtyNormals = true;

還有,我找到的兩個是最實用的工具。您應該只標記已變更的項目,以避免不必要的計算。

結論

希望這份關於 Three.js 的簡介對您有所幫助。沒有什麼感覺像是實際拿起髒話和嘗試某東西,所以我對它的評價太高了。在瀏覽器中原生執行 3D 的工作實在充滿樂趣,使用 Three.js 等引擎可為您省去許多麻煩,並且讓您可以做一些很酷的東西。為協助您快速瞭解,我已在本研究室文章中封裝原始碼,方便您當做參考。如果您喜歡透過 Twitter 分享以上內容,歡迎跟我打聲招呼!