作者:前端藏經(jīng)閣
轉(zhuǎn)發(fā)鏈接:https://www.yuque.com/xwifrr/uxqg5v/ggxx2b
WebGL
簡介:WebGL(全寫Web Graphics Library)是一種3D繪圖協(xié)議,這種繪圖技術(shù)標(biāo)準(zhǔn)允許把JavaScript和OpenGL ES 2.0(OpenGL for Embedded Systems,OpenGL嵌入式版本,針對手機(jī)、游戲機(jī)等設(shè)備相對較輕量級的版本)結(jié)合在一起,通過增加OpenGL ES 2.0的一個JavaScript綁定,WebGL可以為HTML5 Canvas提供硬件3D加速渲染,這樣Web開發(fā)人員就可以借助系統(tǒng)顯卡來在瀏覽器里更流暢地展示3D場景和模型了,還能創(chuàng)建復(fù)雜的導(dǎo)航和數(shù)據(jù)視覺化。
three.js
簡介:Three.js是WebGL的JavaScript 3D庫,其對WebGL提供的接口進(jìn)行了非常好的封裝,簡化了很多細(xì)節(jié),大大降低了學(xué)習(xí)成本,成為前端開發(fā)者完成3D繪圖的得力工具。
three.js官方文檔 :threejs.org/
three.js中文文檔 : https://techbrood.com/threejs/docs/
Three.js整體認(rèn)知(附:Three.js功能概覽)
一、threejs三大組件(場景-scene,相機(jī)-camera,渲染器-renderer)
場景(Scenes)
場景是所有物體的容器,場景只有一種。
場景的構(gòu)造函數(shù)是:
var scene = new THERR.Scene()復(fù)制代碼
Fog(線性霧):
scene.fog = new THREE.Fog(0xcce0ff, 10, 500)復(fù)制代碼
照相機(jī)(Cameras)
定義了三維空間到二維屏幕的投影方式,投影方式主要分為正交投影和透視投影。
1.正交投影:正交投影照相機(jī)獲得的結(jié)果對于在三維空間內(nèi)平行的線,投影到二維空間中也一定是平行的。
2.透視投影:透視投影照相機(jī)獲得的結(jié)果是類似人眼在真實(shí)世界中看到的有“近大遠(yuǎn)小”的效果。
一般說來,對于制圖、建模軟件通常使用正交投影,這樣不會因?yàn)橥队岸淖兾矬w比例;而對于其他大多數(shù)應(yīng)用,通常使用透視投影,因?yàn)檫@更接近人眼的觀察效果,以下詳細(xì)介紹透視投影。
透視投影照相機(jī)(Perspective Camera)的構(gòu)造函數(shù)是:
var camera = new THREE.PerspectiveCamera(fov, aspect, near, far)復(fù)制代碼
讓我們通過一張透視照相機(jī)投影的圖來了解這些參數(shù)。
透視圖中,灰色的部分是視景體,是可能被渲染的物體所在的區(qū)域,在該視景體以外的物體將不會被渲染。
fov是視景體豎直方向上的張角(是角度制而非弧度制),如側(cè)視圖所示。
aspect等于width / height,是照相機(jī)水平方向和豎直方向長度的比值,通常設(shè)為Canvas的橫縱比例。
near照相機(jī)到視景體最近的距離,為正值。
far照相機(jī)到視景體最遠(yuǎn)的距離,為正值。
渲染器(Renderers)
渲染器的作用就是將相機(jī)拍攝出的畫面在瀏覽器中呈現(xiàn)出來。渲染器決定了渲染的結(jié)果應(yīng)該畫在頁面的什么元素上面,并且以怎樣的方式來繪制。three.js中有很多種類的渲染器,例如webGLRenderer、canvasRenderer、SVGRenderer,通常使用的是webGLRenderer渲染器。 webGLRenderer渲染器的構(gòu)造函數(shù)是:
renderer = new THERR.WebGLRenderer()復(fù)制代碼
創(chuàng)建完渲染器之后,需要調(diào)用render方法將之前創(chuàng)建好的場景和相機(jī)相結(jié)合從而渲染出來,即調(diào)用渲染器的render方法:
renderer.render(scene,camera)復(fù)制代碼
了解了three.js完成3D繪圖的三大要素之后,便可以在頁面中創(chuàng)建場景,并利用相機(jī)將場景渲染到網(wǎng)頁上。
首先需要下載three.js庫,并引用到自己的代碼中,以下為三種引入方式,選擇合適的方式在自己的項(xiàng)目中。
<script src="lib/three.js"></script> //ES5const THREE=require('three') //CommonJS/AMDimport * as THREE from 'three' //ES6復(fù)制代碼
// 創(chuàng)建場景var scene = new THREE.Scene(); // 創(chuàng)建透視相機(jī)var camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000); // 創(chuàng)建一個 WebGL 渲染器var renderer = new THREE.WebGLRenderer({ alpha: true,// 默認(rèn)情況下為黑色場景,此處設(shè)置為透明(即白色場景)}); // 設(shè)置渲染器為全屏renderer.setSize(window.innerWidth, window.innerHeight); // 添加到網(wǎng)頁中document.body.appendChild(renderer.domElement);復(fù)制代碼
完成上述各個步驟之后,我們在網(wǎng)頁上看到的只有一塊靜態(tài)的白色場景,看不到任何東西,接下來通過一些基礎(chǔ)圖像的學(xué)習(xí)和了解,以呈現(xiàn)一些圖形效果。
二、圖像的表示
繪制的前期準(zhǔn)備工作已經(jīng)做完,接下來要做的就是把想要繪制的物體添加到場景中。在計算機(jī)世界中,3D世界是由點(diǎn)組成,兩個點(diǎn)能夠組成一條直線,三個不在一條直線上的點(diǎn)就能夠組成一個三角面片,無數(shù)個三角面片就能夠組成各種各樣形狀的物體,通常把這種網(wǎng)格模型叫做Mesh模型。Mesh模型是三維開發(fā)中使用的最為廣泛的型。
Geometries(幾何圖形)
three.js給出了很多方法去生成固定的網(wǎng)格形狀,比如長方體(BoxGeometry)、球體(SphereGeometry)、圓形(CircleGeometry)等等。還有根據(jù)具體坐標(biāo)生成具體形狀的方法,可以借助第三方建模軟件(SketchUp)建模之后導(dǎo)入,目前支持的模型格式有.obj(最常用),.dae,.ctm,.ply,.stl,.wrl,.vtk等。Three.js有一系列支持外部導(dǎo)入文件的函數(shù),是在three.js庫之外的,使用前需要單獨(dú)下載。(例如:OrbitControls-控制器、OBJLoader-加載.obj 文件、MTLLoader-加載.mtl文件)。
Materials(材質(zhì))
three.js給出了很多種直接生成材質(zhì)的方法,其中比較常用的有MeshBasicMaterial(對光照無感,給幾何體一種簡單的顏色或顯示線框),MeshLambertMaterial(對光照有反應(yīng),無光源則不會顯示,用于創(chuàng)建暗淡的不發(fā)光的物體)、MeshPhongMaterial(對光照有反應(yīng),無光源不會顯示,用于創(chuàng)建金屬類米昂涼的物體)等等。物體之所以能被人眼看見,一種是它自身的材料就能發(fā)光,不需要借助外界光源;另一種是自身材料不發(fā)光,需要反射環(huán)境中的光。對于自身不發(fā)光的物體,需要個場景添加光源從而達(dá)到可視的效果。
Lights(燈光)
three.js中可以創(chuàng)建出很多不同類型的光源,比如環(huán)境光AmbientLight(它的顏色會添加到整個場景和所有對象的當(dāng)前顏色上),點(diǎn)光源PointLight(這種光源放出的光線來自同一點(diǎn),且輻射方向四面八方,如蠟燭發(fā)出的光),方向光DirectionalLight(也稱作無限光,從這種光源發(fā)出的光線可以看做是平行的,如太陽光),聚光燈SpotLight(這種光源的光線從一個椎體中射出,在被照射的物體上產(chǎn)生聚光的效果,如手電筒發(fā)出的光。)有光源就缺少不了陰影,在Three.js中,能形成陰影的光源只有DirectionalLight和SpotLight;而相對地,能表現(xiàn)陰影效果的材質(zhì)只有LambertMaterial和PhongMaterial。three.js中渲染陰影的開銷比較大,所以默認(rèn)物體是沒有陰影的,需要單獨(dú)開啟。開啟陰影的方法:
- 將渲染器的shadowMapEnabled屬性設(shè)置為true(告訴渲染器可以渲染隱形)
- 將物體及光源的castShadow屬性設(shè)置為true(告訴物體及光源可以透射陰影)
- 將接收該陰影的物體的receiveShadow屬性設(shè)置為true(告訴物體可以接收其他物體的陰影)
在了解了關(guān)于圖形的基本知識之后,在上面的代碼的基礎(chǔ)上添加簡單圖像。
var geometry = new THREE.BoxGeometry(1,1,1); // 創(chuàng)建一個長寬高都為1個單位的立方體var material = new THREE.MeshBasicMaterial({color: 0x00ff00}); // 創(chuàng)建材質(zhì),對光照無感var cube = new THREE.Mesh(geometry, material); // 創(chuàng)建一個立方體網(wǎng)格(mesh),將材質(zhì)包裹在立方體上scene.add(cube); // 將立方體網(wǎng)格添加到場景中camera.position.z = 5; // 指定相機(jī)位置function render() {requestAnimationFrame(render); // 讓瀏覽器執(zhí)行參數(shù)中的函數(shù),不斷循環(huán)(瀏覽器一個新的API)renderer.render(scene, camera); // 結(jié)合場景和相機(jī)進(jìn)行渲染,即用攝像機(jī)拍下此刻的場景}render();復(fù)制代碼
在render()函數(shù)中添加以下代碼使上面在場景中添加的正方體運(yùn)動起來。
cube.rotation.x = 0.1;cube.rotation.y = 0.1;復(fù)制代碼
Controls(控制器)
軌道控制插件OrbitControls.js可以實(shí)現(xiàn)場景用鼠標(biāo)交互,讓場景動起來,控制場景的旋轉(zhuǎn)、平移和縮放。由于OrbitControls.js是一個插件,所以在three.js 中使用時,需要單獨(dú)引入該文件。
controls = new THREE.OrbitControls(camera);// 初始化控制器controls.target.set(0, 0, 0);// 設(shè)置控制器的焦點(diǎn),使控制器圍繞這個焦點(diǎn)進(jìn)行旋轉(zhuǎn)controls.minDistance = 80;// 設(shè)置移動的最短距離(默認(rèn)為零)controls.maxDistance = 400;// 設(shè)置移動的最長距離(默認(rèn)為無窮)controls.maxPolarAngle = Math.PI / 3;//繞垂直軌道的距離(范圍是0-Math.PI,默認(rèn)為Math.PI)controls.update();// 照相機(jī)轉(zhuǎn)動時,必須更新該控制器復(fù)制代碼
配置該插件之后實(shí)現(xiàn)的效果:
操控效果按住鼠標(biāo)左鍵并移動攝像機(jī)圍繞場景中心旋轉(zhuǎn)轉(zhuǎn)動鼠標(biāo)滑輪或按住中鍵并移動放大或縮小按住鼠標(biāo)右鍵并移動在場景中平移上、下、左、右方向鍵在場景中平移
Loaders(加載器)
用來加載不同格式的文件,主要介紹以下三種:
OBJLoader加載器(需要單獨(dú)引入js文件):用來加載.obj文件(分為有材質(zhì)和沒有材質(zhì)兩種)。
// 沒有材質(zhì)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});// 設(shè)置陰影 scene.add(obj)});復(fù)制代碼
MTLLoader加載器(需要單獨(dú)引入js文件):用來加載.mtl文件(即加載有材質(zhì)物體的obj文件之前先加載mtl文件)。
// 有材質(zhì)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) })});復(fù)制代碼
CSS2DRenderer加載器(需要單獨(dú)引入js文件):如果要將基于HTML的標(biāo)簽與3D對象組合,則CSS2DRenderer渲染器非常有用。這里,各個DOM元素也被包裝到CSS2DObject的一個實(shí)例中并添加到場景圖中。
// 初始化 CSS2DRendererlabelRenderer = new THREE.CSS2DRenderer();labelRenderer.setSize(window.innerWidth, window.innerHeight); // 設(shè)置渲染器的大小labelRenderer.domElement.style.position = 'absolute';labelRenderer.domElement.style.top = 0;container.appendChild(labelRenderer.domElement);// 標(biāo)注實(shí)例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); }復(fù)制代碼
Textures(紋理)
紋理是一個2D圖片(甚至也有1D和3D的紋理),它可以用來添加物體的細(xì)節(jié);可以想象紋理是一張繪有磚塊的紙,無縫折疊貼合到你的3D的房子上,這樣你的房子看起來就像有磚墻外表了。
var textureCube = new THREE.CubeTextureLoader().load(urls);scene.background = textureCube;復(fù)制代碼
Three.js vue.js
1.用npm 安裝three npm install three?????
three.js 安裝地址 :https://www.npmjs.com/package/three
安裝成功后,在項(xiàng)目中 import three from 'three';,之后運(yùn)行程序。
發(fā)現(xiàn)控制臺報錯 default export is not declared in imported module 說明three.js沒有默認(rèn)的導(dǎo)出對象,應(yīng)該寫成 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安裝地址:https://www.npmjs.com/package/three-orbit-controls
該插件引入之前確認(rèn)three.js 庫已經(jīng)引入, 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安裝地址 :https://www.npmjs.com/package/three-obj-mtl-loader
該插件引入之前必須確認(rèn)three.js庫已經(jīng)引入,該插件包括加載.obj和.mtl 文件的加載器
import {MTLLoader,OBJLoader} from 'three-obj-mtl-loader';
使用方法:mtlLoader = new MTLLoader(); objLoader = new OBJLoader();
注:單獨(dú)使用three-mtl-loader 和 three-obj-loader兩個插件時,會發(fā)生錯誤:
4.用npm安裝three-css2drender插件, npm i –save three-css2drender
three-css2drender安裝地址: www.npmjs.com/package/three-css2drende
插件引入之前必須確認(rèn)htree.js庫已經(jīng)引入
import {CSS2DRenderer,CSS2DObject} from 'three-css2drenderer';
使用方法:
labelRenderer = new CSS2DRenderer();
label = new CSS2DObject( text );
作者:前端藏經(jīng)閣
轉(zhuǎn)發(fā)鏈接:https://www.yuque.com/xwifrr/uxqg5v/ggxx2b
版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻(xiàn),該文觀點(diǎn)僅代表作者本人。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請發(fā)送郵件至 舉報,一經(jīng)查實(shí),本站將立刻刪除。