初識three.js,搭建three.js+vue.js專案

mnn發表於2018-09-22

WebGL

簡介:WebGL(全寫Web Graphics Library)是一種3D繪圖協議,這種繪圖技術標準允許把JavaScript和OpenGL ES 2.0(OpenGL for Embedded Systems,OpenGL嵌入式版本,針對手機、遊戲機等裝置相對較輕量級的版本)結合在一起,通過增加OpenGL ES 2.0的一個JavaScript繫結,WebGL可以為HTML5 Canvas提供硬體3D加速渲染,這樣Web開發人員就可以藉助系統顯示卡來在瀏覽器裡更流暢地展示3D場景和模型了,還能建立複雜的導航和資料視覺化。

Three.js

簡介:Three.js是WebGL的JavaScript 3D庫,其對WebGL提供的介面進行了非常好的封裝,簡化了很多細節,大大降低了學習成本,成為前端開發者完成3D繪圖的得力工具。

three.js官方文件 :threejs.org/

three.js中文文件 : techbrood.com/threejs/doc…

Three.js整體認知(附:Three.js功能概覽

初識three.js,搭建three.js+vue.js專案
一、threejs三大元件(場景-scene,相機-camera,渲染器-renderer)

場景(Scenes)

場景是所有物體的容器,場景只有一種。

場景的建構函式是:

var scene = new THERR.Scene()
複製程式碼

Fog(線性霧):

scene.fog = new THREE.Fog(0xcce0ff, 10, 500)
複製程式碼

照相機(Cameras)

定義了三維空間到二維螢幕的投影方式,投影方式主要分為正交投影和透視投影。

1.正交投影:正交投影照相機獲得的結果對於在三維空間內平行的線,投影到二維空間中也一定是平行的。

2.透視投影:透視投影照相機獲得的結果是類似人眼在真實世界中看到的有“近大遠小”的效果。

初識three.js,搭建three.js+vue.js專案

一般說來,對於製圖、建模軟體通常使用正交投影,這樣不會因為投影而改變物體比例;而對於其他大多數應用,通常使用透視投影,因為這更接近人眼的觀察效果,以下詳細介紹透視投影。

透視投影照相機(Perspective Camera)的建構函式是:

var camera = new THREE.PerspectiveCamera(fov, aspect, near, far)
複製程式碼

讓我們通過一張透視照相機投影的圖來了解這些引數。

初識three.js,搭建three.js+vue.js專案

透檢視中,灰色的部分是視景體,是可能被渲染的物體所在的區域,在該視景體以外的物體將不會被渲染。

fov是視景體豎直方向上的張角(是角度制而非弧度制),如側檢視所示。

aspect等於width / height,是照相機水平方向和豎直方向長度的比值,通常設為Canvas的橫縱比例。

near照相機到視景體最近的距離,為正值。

far照相機到視景體最遠的距離,為正值。

渲染器(Renderers)

渲染器的作用就是將相機拍攝出的畫面在瀏覽器中呈現出來。渲染器決定了渲染的結果應該畫在頁面的什麼元素上面,並且以怎樣的方式來繪製。three.js中有很多種類的渲染器,例如webGLRenderer、canvasRenderer、SVGRenderer,通常使用的是webGLRenderer渲染器。 webGLRenderer渲染器的建構函式是:

renderer = new THERR.WebGLRenderer()
複製程式碼

建立完渲染器之後,需要呼叫render方法將之前建立好的場景和相機相結合從而渲染出來,即呼叫渲染器的render方法:

renderer.render(scene,camera)
複製程式碼

瞭解了three.js完成3D繪圖的三大要素之後,便可以在頁面中建立場景,並利用相機將場景渲染到網頁上。

首先需要下載three.js庫,並引用到自己的程式碼中,以下為三種引入方式,選擇合適的方式在自己的專案中。

<script src="lib/three.js"></script>  //ES5
const THREE=require('three')  //CommonJS/AMD
import * as THREE from 'three'   //ES6
複製程式碼
// 建立場景
var scene = new THREE.Scene(); 
// 建立透視相機
var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); 
// 建立一個 WebGL 渲染器
var renderer = new THREE.WebGLRenderer({
       alpha: true,// 預設情況下為黑色場景,此處設定為透明(即白色場景)
}); 
// 設定渲染器為全屏
renderer.setSize(window.innerWidth, window.innerHeight); 
// 新增到網頁中
document.body.appendChild(renderer.domElement);
複製程式碼

完成上述各個步驟之後,我們在網頁上看到的只有一塊靜態的白色場景,看不到任何東西,接下來通過一些基礎影像的學習和了解,以呈現一些圖形效果。

二、影像的表示

繪製的前期準備工作已經做完,接下來要做的就是把想要繪製的物體新增到場景中。在計算機世界中,3D世界是由點組成,兩個點能夠組成一條直線,三個不在一條直線上的點就能夠組成一個三角面片,無數個三角面片就能夠組成各種各樣形狀的物體,通常把這種網格模型叫做Mesh模型。Mesh模型是三維開發中使用的最為廣泛的型。

初識three.js,搭建three.js+vue.js專案

Geometries(幾何圖形)

three.js給出了很多方法去生成固定的網格形狀,比如長方體(BoxGeometry)、球體(SphereGeometry)、圓形(CircleGeometry)等等。還有根據具體座標生成具體形狀的方法,可以藉助第三方建模軟體(SketchUp)建模之後匯入,目前支援的模型格式有.obj(最常用),.dae,.ctm,.ply,.stl,.wrl,.vtk等。Three.js有一系列支援外部匯入檔案的函式,是在three.js庫之外的,使用前需要單獨下載。(例如:OrbitControls-控制器、OBJLoader-載入.obj 檔案、MTLLoader-載入.mtl檔案)。

Materials(材質)

three.js給出了很多種直接生成材質的方法,其中比較常用的有MeshBasicMaterial(對光照無感,給幾何體一種簡單的顏色或顯示線框),MeshLambertMaterial(對光照有反應,無光源則不會顯示,用於建立暗淡的不發光的物體)、MeshPhongMaterial(對光照有反應,無光源不會顯示,用於建立金屬類米昂涼的物體)等等。物體之所以能被人眼看見,一種是它自身的材料就能發光,不需要藉助外界光源;另一種是自身材料不發光,需要反射環境中的光。對於自身不發光的物體,需要個場景新增光源從而達到可視的效果。

Lights(燈光)

three.js中可以建立出很多不同型別的光源,比如環境光AmbientLight(它的顏色會新增到整個場景和所有物件的當前顏色上),點光源PointLight(這種光源放出的光線來自同一點,且輻射方向四面八方,如蠟燭發出的光),方向光DirectionalLight(也稱作無限光,從這種光源發出的光線可以看做是平行的,如太陽光),聚光燈SpotLight(這種光源的光線從一個椎體中射出,在被照射的物體上產生聚光的效果,如手電筒發出的光。)有光源就缺少不了陰影,在Three.js中,能形成陰影的光源只有DirectionalLight和SpotLight;而相對地,能表現陰影效果的材質只有LambertMaterial和PhongMaterial。three.js中渲染陰影的開銷比較大,所以預設物體是沒有陰影的,需要單獨開啟。開啟陰影的方法:

  • 將渲染器的shadowMapEnabled屬性設定為true(告訴渲染器可以渲染隱形)
  • 將物體及光源的castShadow屬性設定為true(告訴物體及光源可以透射陰影)
  • 將接收該陰影的物體的receiveShadow屬性設定為true(告訴物體可以接收其他物體的陰影)

在瞭解了關於圖形的基本知識之後,在上面的程式碼的基礎上新增簡單影像。

var geometry = new THREE.BoxGeometry(1,1,1); // 建立一個長寬高都為1個單位的立方體
var material = new THREE.MeshBasicMaterial({color: 0x00ff00}); // 建立材質,對光照無感
var cube = new THREE.Mesh(geometry, material); // 建立一個立方體網格(mesh),將材質包裹在立方體上
scene.add(cube); // 將立方體網格新增到場景中

camera.position.z = 5; // 指定相機位置
function render() {
requestAnimationFrame(render); // 讓瀏覽器執行引數中的函式,不斷迴圈(瀏覽器一個新的API)
renderer.render(scene, camera); // 結合場景和相機進行渲染,即用攝像機拍下此刻的場景
}
render();
複製程式碼

render()函式中新增以下程式碼使上面再場景中新增的正方體運動起來。

cube.rotation.x += 0.1;
cube.rotation.y += 0.1;
複製程式碼

Controls(控制器)

軌道控制外掛OrbitControls.js可以實現場景用滑鼠互動,讓場景動起來,控制場景的旋轉、平移和縮放。由於OrbitControls.js是一個外掛,所以在three.js 中使用時,需要單獨引入該檔案。

controls = new THREE.OrbitControls(camera);// 初始化控制器
controls.target.set(0, 0, 0);// 設定控制器的焦點,使控制器圍繞這個焦點進行旋轉
controls.minDistance = 80;// 設定移動的最短距離(預設為零)
controls.maxDistance = 400;// 設定移動的最長距離(預設為無窮)
controls.maxPolarAngle = Math.PI / 3;//繞垂直軌道的距離(範圍是0-Math.PI,預設為Math.PI)
controls.update();// 照相機轉動時,必須更新該控制器
複製程式碼

配置該外掛之後實現的效果:

操控 效果
按住滑鼠左鍵並移動 攝像機圍繞場景中心旋轉
轉動滑鼠滑輪或按住中鍵並移動 放大或縮小
按住滑鼠右鍵並移動 在場景中平移
上、下、左、右方向鍵 在場景中平移

Loaders(載入器)

用來載入不同格式的檔案,主要介紹以下三種:

OBJLoader載入器(需要單獨引入js檔案):用來載入.obj檔案(分為有材質和沒有材質兩種)。

// 沒有材質
new THREE.OBJLoader().load('./tree.obj', function (obj) {
    obj.scale.set(10, 10, 10);
    obj.position.set(-10, 0, 0);
   obj.children.forEach(function (e) {
          e.castShadow = true
});// 設定陰影
    scene.add(obj)
});
複製程式碼

MTLLoader載入器(需要單獨引入js檔案):用來載入.mtl檔案(即載入有材質物體的obj檔案之前先載入mtl檔案)。

// 有材質
new THREE.MTLLoader().setPath('./model/VANS/').load('VANS.mtl', function (materials) {
    materials.preload();
    new THREE.OBJLoader().setMaterials(materials).setPath('./model/VANS/').load('VANS.obj', function (obj) {
        obj.scale.set(0.8, 0.8, 0.8);
        obj.position.set(-40, -50, 10);
        scene.add(obj)  
    })
});
複製程式碼

CSS2DRenderer載入器(需要單獨引入js檔案):如果要將基於HTML的標籤與3D物件組合,則CSS2DRenderer渲染器非常有用。這裡,各個DOM元素也被包裝到CSS2DObject的一個例項中並新增到場景圖中。

// 初始化 CSS2DRenderer
labelRenderer = new THREE.CSS2DRenderer();
labelRenderer.setSize(window.innerWidth, window.innerHeight); // 設定渲染器的大小
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.top = 0;
container.appendChild(labelRenderer.domElement);
// 標註例項
function addSprite(text, Mash, callback) {
       biaozhudiv = document.createElement('div');
       biaozhudiv.className = 'label';
       biaozhudiv.textContent = text;
       biaozhudiv.onclick = function () {
           callback(Mash)
       };
       biaozhuLabel = new THREE.CSS2DObject(biaozhudiv);
       biaozhuLabel.position.set(0, 0, 0);
       Mash.add(biaozhuLabel);
    }
複製程式碼

Textures(紋理)

紋理是一個2D圖片(甚至也有1D和3D的紋理),它可以用來新增物體的細節;可以想象紋理是一張繪有磚塊的紙,無縫摺疊貼合到你的3D的房子上,這樣你的房子看起來就像有磚牆外表了。

var textureCube = new THREE.CubeTextureLoader().load(urls);
scene.background = textureCube;
複製程式碼

Three.js+vue.js

1.用npm 安裝three npm install three     

three.js 安裝地址 :www.npmjs.com/package/thr…

安裝成功後,在專案中 import three from 'three';,之後執行程式。

發現控制檯報錯 default export is not declared in imported module 說明three.js沒有預設的匯出物件,應該寫成 import * as three from 'three'; 或者可以這樣: import { Scene, WebGLRenderer, PerspectiveCamera, BoxGeometry, MeshBasicMaterial, Mesh} from 'three';

或者使用CommonJS的形式引入var three = require ('three');

2.用npm安裝軌道控制外掛 npm install three-orbit-controls  

three-orbit-controls安裝地址:www.npmjs.com/package/thr…

該外掛引入之前確認three.js 庫已經引入, OrbitControls = require('three-orbit-controls')(THREE)

使用方法: controls = new OrbitControls(camera);

3.用npm安裝載入.obj和.mtl檔案的外掛 npm i --save three-obj-mtl-loader

three-obj-mtl-loader安裝地址 :www.npmjs.com/package/thr…

該外掛引入之前必須確認three.js庫已經引入,該外掛包括載入.obj和.mtl 檔案的載入器

import {MTLLoader,OBJLoader} from 'three-obj-mtl-loader';

使用方法:mtlLoader = new MTLLoader(); objLoader = new OBJLoader();

注:單獨使用three-mtl-loaderthree-obj-loader兩個外掛時,會發生錯誤:

初識three.js,搭建three.js+vue.js專案

4.用npm安裝three-css2drender外掛, npm i --save three-css2drender

three-css2drender安裝地址: www.npmjs.com/package/thr…

外掛引入之前必須確認htree.js庫已經引入

import {CSS2DRenderer,CSS2DObject} from 'three-css2drenderer';

使用方法: labelRenderer = new CSS2DRenderer(); label = new CSS2DObject( text );

Three.js+vue.js 練習專案

原始碼:github.com/mfnn/Mnn.gi…

相關文章