【溫故知新】——BABYLON.js基礎·常用知識點總結
前言:複習BABYLON.js官網101基礎文件之後,總結了一些在公司專案中常用的基礎知識點。官網文件地址:http://doc.babylonjs.com/babylon101/
一、建立場景的模板:
var createScene = function () {
// 建立場景空間
var scene = new BABYLON.Scene(engine);
// 在場景中新增一個攝像頭並將其附加到畫布上
var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 2, 2, BABYLON.Vector3.Zero(), scene);
camera.attachControl(canvas, true);
// 在場景中新增燈光
var light1 = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(1, 1, 0), scene);
var light2 = new BABYLON.PointLight("light2", new BABYLON.Vector3(0, 1, -1), scene);
//這是你建立和操作網格的地方
var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {}, scene);
return scene;
};
當編寫自己的HTML時,只需要將createScene function嵌入到一個HTML頁面結構中,並帶有一個<script>標籤和其他一些條目。
你需要載入巴比倫的javascript程式碼。同樣,在平板電腦和手機上使用的是指標事件,而不是滑鼠事件,所以PEP事件系統也需要載入。
二、建立一個固定形狀的一般形式是:
var shape = BABYLON.MeshBuilder.CreateShape(name, options, scene);
options引數允許您做一些事情,比如設定形狀的大小,並設定您是否可以更新它。
1、 Box盒子
var box = BABYLON.MeshBuilder.CreateBox("box", {}, scene); //預設的盒子box
var myBox = BABYLON.MeshBuilder.CreateBox("myBox", {height: 5, width: 2, depth: 0.5}, scene);
- option引數:
size height width depth(深度) faceColors(面顏色,6種顏色的陣列,每個框面一個)
faceUV(面UV,6個向量陣列,每個盒子面一個) updatable(可更新的) sideOrientation(邊方向)
2、Sphere球體
var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {}, scene); //預設的球體sphere
var mySphere = BABYLON.MeshBuilder.CreateSphere("mySphere", {diameter: 2, diameterX: 3}, scene);
- option引數:
segments(段數) diameter(直徑) diameterX diameterY diameterZ arc(弧度)
slice(切片) updatable(可更新的) sideOrientation(邊方向)
3、Plane平面
var plane = BABYLON.MeshBuilder.CreatePlane("plane", {}, scene); //預設的平面plane
var myPlane = BABYLON.MeshBuilder.CreatePlane("myPlane", {width: 5, height: 2}, scene);
- option引數:
size width height updatable(可更新的) sideOrientation(邊方向)
frontUVs(前UV,只有當邊方向設定為 sideOrientation:BABYLON.Mesh.DOUBLESIDE)
backUVs(後UV,只有當邊方向設定為 sideOrientation:BABYLON.Mesh.DOUBLESIDE)
sourcePlane(源平面,源平面(數學)網格將被轉換為)
sourcePlane是一個平面網格的獨特選擇,它提供了一種方法來定向和定位它。
現在只考慮它的方向在建立上是向量(0,0,1)現在你要讓方向成為向量(0,1,1)然後你用它來建立一個源平面
var sourcePlane = new BABYLON.Plane(0, -1, 1, 0);
sourcePlane.normalize();
這就建立了一個數學平面,它被用作定位源。第四個引數是向方向向量方向移動的距離。這裡暫時設為0。
4、Ground地面
var ground = BABYLON.MeshBuilder.CreateGround("ground", {}, scene); //預設的地面ground
var myGround = BABYLON.MeshBuilder.CreateGround("myGround", {width: 6, height: 4, subdivsions: 4}, scene);
- option引數:
width height updatable(可更新的) subdivisions(數量的平方細分)
CreateGround的一個變體是createfromheightmap它可以讓你形成起伏的地面而不是平坦的平面
① Face Colors or UV
這隻適用於有限數量的網格,它們有不同的面孔,如盒子,而不是球體。
這讓你可以給每個物體一個面,給他們一個單獨的顏色或影象。
找出面顏色和麵UV。
② Updatable
當一個網格Updatable的引數集為true時,它意味著可以改變與網格的每個頂點相關聯的資料,從而改變網格的形狀。
③ Side Orientation
側方向選項用於改變網格的每一面
這個選項有四種可能的值:
BABYLON.Mesh.FRONTSIDE,
BABYLON.Mesh.BACKSIDE,
BABYLON.Mesh.DOUBLESIDE,
BABYLON.Mesh //預設值是預設值,並且等於當前的FRONTSIDE
通過移動你的螢幕指標向左和向右旋轉平面,在下面的例子中,你可以比較預設和雙邊……
④ Front and Back UV
當一個網格有一個面向側的選項時,它被設定為雙側DOUBLESIDE,那麼前面和後面就有可能顯示不同的影象。
三、建立引數化形狀
在101課程中,你只會遇到線條,你只需要使用MeshBuilder方法,而不是舊的傳統網格Mesh方法。
1、Lines線
線是一系列三維的線段,其中一條線段的末端是下一個線段的開始。線是由三維空間中的一系列點points來描述的。
這三個點(0,0,0),(0,1,1),(0,1,0)將形成兩個線段。
這些點在Babylon.js中被構造為Vector3物件,並在一個數組中按順序排列,以傳遞給CreateLines方法,以位置向量給出的。
var myPoints = [];
var point1 = new BABYLON.Vector3(0, 0, 0);
myPoints.push(point1);
var point2 = new BABYLON.Vector3(0, 1, 1);
myPoints.push(point2);
var point3 = new BABYLON.Vector3(0, 1, 0);
myPoints.push(point3);
//或者
var myPoints =[
new BABYLON.Vector3(0, 0, 0),
new BABYLON.Vector3(0, 1, 1),
new BABYLON.Vector3(0, 1, 0)
];
然後,這些點的陣列必須傳遞給點選項
//建立線lines
var lines = BABYLON.MeshBuilder.CreateLines("lines", {points: myPoints}, scene);
您可以建立虛線CreateDashedLines,並將破折號dashNb的數量作為一個選項。
- CreateLines option引數:
points(向量的陣列,這條線的路徑) updatable(可更新的) instance(要更新的線網格的例項)
colors(顏色陣列,每個點顏色) useVertexAlpha(false 表示不需要阿爾法混合--更快)
- CreateDashedLines option引數:
points(向量的陣列,這條線的路徑) dashSize(破折號的大小) gapSize(縫隙的大小)
dashNb(破折號的預定數量) updatable(可更新的) instance(要更新的線網格的例項)
- Updatable Option
實線和虛線有一個可更新的選項。當這是true的時候,就有可能改變與直線的每個頂點相關的資料,從而改變線的路徑。
- Instance Option
線條也有一個例項選項,這意味著有另一種方法可以通過傳遞一組新的點來更新線路的路徑。
為了使其工作,建立的原始行必須具有可更新選項Updatable為true,並且所建立的線作為option例項的值傳遞。
陣列中的點數量必須保持不變。
//建立線
var lines = BABYLON.MeshBuilder.CreateLines("lines", {points: myArray, updatable: true}, scene);
//更新現有的線例項:這裡不需要場景引數
lines = BABYLON.MeshBuilder.CreateLines("lines", {points: myNewArray, instance: lines});
大多數但不是所有的引數形狀都有例項選項,所以可以用這種方式更新它們的網格。
四、參照系
Babylon.js使用兩種參照系,世界軸和本地軸。世界軸的原點永遠不會改變。
在所有的diagrams圖表和playgrounds上X軸是紅色的,Y軸是綠色的,Z軸是藍色的
當網格被建立時,它們的中心被放置在世界軸的原點,它們的位置總是相對於世界軸。
本地軸與網格一起移動。本地軸的原點總是在網格的建立中心,不管它的位置是什麼。
網格的旋轉和放大的中心是在本地軸的原點,但是通過使用一個轉換節點或一個矩陣來設定一個軸心點,它們可以被改變到那個點。
五、向量
所有的位置,旋轉和縮放都是用new BABYLON.Vector3(x, y, z),並且可以單獨設定。
六、定位、旋轉和縮放
1、Position——定位
位置是pilot使用一個向量(x,y,z)來表示軸,本地軸與試點移動。
pilot.position = new BABYLON.Vector3(2, 3, 4);
//或單個元件
pilot.position.x = 2;
pilot.position.y = 3;
pilot.position.z = 4;
本地軸和世界軸仍然保持著相同的方向。
2、Rotation——旋轉
在3D空間中旋轉的警告總是很棘手的。旋轉被應用到形狀的順序改變了形狀的最終方向,你還需要知道正在使用哪個參照系。
在BabylonJS中旋轉設定使用
pilot.rotation = new BABYLON.Vector3(alpha, beta, gamma);
//或者
pilot.rotation.x = alpha; //繞x軸旋轉
pilot.rotation.y = beta; //繞y軸旋轉
pilot.rotation.z = gamma; //繞z軸旋轉
alpha, beta 和 gamma是用弧度來測量的
在三次旋轉之後,你需要立即停下來思考一下,你需要問三個不同的軸——“在哪個順序中,他們應用了哪一種參考系,在哪個方向?”
下列兩種慣例中的任何一種都可以被認為是在BabylonJS的旋轉中使用的。因為兩者都導致了相同的結果。
慣例1——本地軸Local Axes
對於本地軸的旋轉,網格與旋轉中心在軸的原點處,在座標軸上關於本地軸的旋轉順序y,x,z,當你看正軸的方向時,所有的旋轉都是逆時針的。
下圖顯示了試點的初始起始位置,然後是關於本地y軸的π/2的旋轉,然後是關於本地x軸的π/2的旋轉,最後是本地z軸的π/2的旋轉。
慣例2——世界軸World Axes
與慣例1相比,旋轉的中心不會改變,但是旋轉的軸是這樣的。
世界軸使用旋轉是在本地軸的原點處將網格與旋轉中心旋轉,在座標軸上關於世界軸的旋轉順序z,x,y,
當你看正軸的方向時,所有的旋轉都是逆時針的。
總結:無論你怎麼想它的結果都是一樣的。下面的結果都是一樣的
pilot.rotation = new BABYLON.Vector3(alpha, beta, gamma);
pilot.rotation.x = alpha;
pilot.rotation.y = beta;
pilot.rotation.z = gamma;
pilot.rotation.z = gamma;
pilot.rotation.x = alpha;
pilot.rotation.y = beta;
pilot.rotation.y = beta;
pilot.rotation.z = gamma;
pilot.rotation.x = alpha;
問題:如果你想要一個旋轉的序列從一個關於x軸的旋轉開始,然後是關於y軸,然後是z軸?
對於世界軸,你使用rotate method
對於本地軸,Babylon.js既有rotate method,也有 addRotation method.
你可以用addRotation method來排列一個旋轉序列。
這個方法提供了一個關於一個軸的旋轉值,它可以從第一個軸到最後一個,如下面的例子所示。
mesh.addRotation(Math.PI/2, 0, 0).addRotation(0, Math.PI/2, 0).addRotation(0, 0, Math.PI/2);
一個接一個從初始位置的試點,後跟一個繞本地x軸旋轉π/ 2,然後繞本地y軸旋轉π/ 2和最後繞本地z軸旋轉π/ 2。
一般mesh.addRotation(alpha, beta, gamma) 至少需要alpha, beta, gamma中的兩個為0,分別表示關於本地x,y,z軸的旋轉
3、Scaling——縮放
//沿著x軸、y軸和z軸進行縮放
mesh.scaling = new BABYLON.Vector3(scale_x, scale_y, scale_z);
//或單獨設定
mesh.scaling.y = 5;
七、材質對光線的反應
無論這種材質是一種顏色還是一種質地,它對光線的反應都是不同的。
1.Diffuse散射-在光下觀察的材料的基本顏色或紋理;
2.Specular高光-由光照射到材料上的高光;
3.Emissive放射——材料的顏色或質地,就像自亮;
4.Ambient環境-由環境背景照明所點燃的材料的顏色或紋理。
散射和高光材質需要一個光源light source 來建立
環境顏色需要設定場景的環境顏色,給環境背景照明。
scene.ambientColor = new BABYLON.Color3(1, 1, 1);
Transparency透明度——你可以通過材料看到的水平可以被設定,對於透明
部分的影象,它可以被使用,這樣材質的適當部分
是不可見的。這就需要設定一個alpha屬性。
八、材質顏色
建立一個材質使用:
var myMaterial = new BABYLON.StandardMaterial("myMaterial", scene);
用一種、一些或全部的:
- diffuseColor固有色貼圖,
- specularColor高光反射顏色貼圖,
- emissiveColor放射色 和
- ambientColor環境色貼圖
來設定材料的顏色。
請記住,只有場景環境顏色scene ambient color 設定好時,才會使用ambientColor。
var myMaterial = new BABYLON.StandardMaterial("myMaterial", scene);
myMaterial.diffuseColor = new BABYLON.Color3(1, 0, 1);
myMaterial.specularColor = new BABYLON.Color3(0.5, 0.6, 0.87);
myMaterial.emissiveColor = new BABYLON.Color3(1, 1, 1);
myMaterial.ambientColor = new BABYLON.Color3(0.23, 0.98, 0.53);
mesh.material = myMaterial;
- Ambient Color——環境顏色
場景的環境顏色,必須存在,是白色的。
當一個場景的環境顏色元件被設定為0時,例如紅色,那麼無論在材質環境中紅色的值是什麼,它都不會產生任何影響。
- Transparent Color——透明色
透明性是通過將一個材質alpha屬性從0(不可見)設定為1(不透明)來實現的。
myMaterial.alpha = 0.5;
九、材質紋理
紋理是使用儲存的影象形成的
//建立一個材質使用
var myMaterial = new BABYLON.StandardMaterial("myMaterial", scene);
用一種、一些或全部的
- diffuseTexture固有紋理,
- specularTexture高光反射紋理,
- emissiveTexture放射紋理 和
- ambientTexture 環境紋理
來設定材料的紋理。
請記住,只有場景環境顏色scene ambient color 設定好時,才會使用ambientTexture。
var myMaterial = new BABYLON.StandardMaterial("myMaterial", scene);
myMaterial.diffuseTexture = new BABYLON.Texture("PATH TO IMAGE", scene);
myMaterial.specularTexture = new BABYLON.Texture("PATH TO IMAGE", scene);
myMaterial.emissiveTexture = new BABYLON.Texture("PATH TO IMAGE", scene);
myMaterial.ambientTexture = new BABYLON.Texture("PATH TO IMAGE", scene);
mesh.material = myMaterial;
>>>>>注意:當沒有指定法線時,Babylon's standard material 將計演算法線
透明材質紋理
① 透明度是通過將材質alpha屬性從0(不可見)設定為1(不透明)來實現的。
myMaterial.alpha = 0.5;
② 此外,用於紋理的影象可能已經有了透明度設定。在這種情況下,我們將紋理的hasAlpha屬性設定為true。
myMaterial.diffuseTexture.hasAlpha = true;
>>>>>>為了讓立方體的後面通過前面的透明區域可見,我們必須處理背部的選擇。
③ Back Face Culling——背面剔除
這是一種有效地繪製3D模型的二維螢幕渲染的方法。
通常不需要畫出立方體或其他物體的背面,因為它會被前面隱藏起來。
在BabylonJS,預設設定是,正如你所期望的,設定為true。
myMaterial.backFaceCulling = true;
- WireFrame——線框
你可以線上框模式下看到一個網格:
materialSphere1.wireframe = true;
十、相機
對於使用者的輸入控制,所有的相機都需要連線到畫布上
camera.attachControl(canvas, true);
第二個引數是可選的,預設為false。當false的時候,在畫布事件上的預設動作是被阻止的。設定為true,允許畫布預設動作。
說明:
① 一個Gamepad(手柄)可以使用一個控制器。
② 用於觸控控制,無論是PEP還是hand.js都是必要的。
1、Universal Camera——萬能相機
預設的行為是:
1.keyboard鍵盤-左和右箭頭移動相機左右,上下箭頭移動它向前和向後;
2.mouse滑鼠——用相機旋轉相機的原點;
3.touch向左或向右滑動,左右移動相機,上下滑動,向前和向後移動;
4.gamepad手柄-對應於裝置。
構建一個萬能相機
// 引數:名稱、位置、場景
var camera = new BABYLON.UniversalCamera("UniversalCamera", new BABYLON.Vector3(0, 0, -10), scene);
// 把相機對準一個特定的位置。在這個例子中是場景的原點
camera.setTarget(BABYLON.Vector3.Zero());
// 把相機固定在畫布上
camera.attachControl(canvas, true);
2、Arc Rotate Camera——弧旋轉相機
- 相機總是指向一個給定的目標位置,並可以在目標周圍旋轉,目標是旋轉的中心。
- 它可以用游標和滑鼠來控制,也可以用觸控事件來控制。
- 它相對於目標(地球)的位置可以由三個引數設定,alpha(弧度)經度(橫切面)的旋轉,beta(弧度)的緯度(縱切面)的旋轉和半徑(目標位置的距離)。
- 由於技術原因,將beta值設定為0或PI會導致問題,在這種情況下,beta偏移0.1弧度(大約0.6度)。
- alpha和beta都是順時針方向增長的
- 相機的位置也可以由一個向量來設定,這個向量將會超過alpha、beta和半徑的任何現值。這比計算所需的角度要容易得多。
- 無論是使用鍵盤、滑鼠還是觸控式滑動,都可以改變alpha值和向下方向的變化。
構建一個弧旋轉相機:
//引數:alpha、beta、半徑、目標位置、場景
var camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 10, new BABYLON.Vector3(0, 0, 0), scene);
//定位攝像機覆蓋alpha,beta,半徑
camera.setPosition(new BABYLON.Vector3(0, 0, 20));
//把相機連線到畫布上
camera.attachControl(canvas, true);
通過使用CTRL+MouseLeftClick,也可以使用ArcRotateCamera來進行Panning移鏡頭操作。你可以指定使用MouseRightClick來替代,通過在attachControl呼叫中設定useCtrlForPanning:
camera.attachControl(canvas, noPreventDefault, useCtrlForPanning);
如果需要的話,你也可以通過設定來完全禁用panning :
scene.activeCamera.panningSensibility = 0;
3 . FollowCamera——跟隨相機
- 給它一個網格作為目標,無論它現在處於什麼位置,它都會移動到一個目標位置來檢視目標。
- 當目標移動時,跟隨相機也會移動。
- 當它被建立時,跟隨相機的初始位置設定,然後目標位置設定為三個引數:
- 距離目標的距離-攝像機半徑camera.radius;
- 目標上方的高度
- 在x y平面上的角度
- 相機移動到目標位置的速度是通過它的加速度(camera.cameraAcceleration)達到最大速度(camera.maxCameraSpeed)。
構建一個跟隨相機:
// 引數:名稱、位置、場景
var camera = new BABYLON.FollowCamera("FollowCam", new BABYLON.Vector3(0, 10, -10), scene);
//半徑:相機距離目標距離
camera.radius = 30;
// 相機高於目標中心(原點)的目標高度
camera.heightOffset = 10;
// 目標在x y平面上繞目標(中心)的目標旋轉角度
camera.rotationOffset = 0;
//從當前位置到目標位置移動相機的加速度
camera.cameraAcceleration = 0.005
//停止的加速度
camera.maxCameraSpeed = 10
//把相機連線到畫布上
camera.attachControl(canvas, true);
注意:在目標建立後設置相機目標,並注意到BABYLONJS的v2.5變化。
建立目標網格
camera.target = targetMesh; // 2.4和更早的版本
camera.lockedTarget = targetMesh; //2.5版本開始
十一、燈光
所有的網格都允許光通過它們,除非陰影生成被啟用。允許的預設燈光數是4,但這可以增加。
1、The Point Light——點光源
var light = new BABYLON.PointLight("pointLight", new BABYLON.Vector3(1, 10, 1), scene);
2、The Directional Light——平行光源
var light = new BABYLON.DirectionalLight("DirectionalLight", new BABYLON.Vector3(0, -1, 0), scene);
3、The Spot Light——聚光燈
聚光燈是由一個位置、一個方向、一個角度和一個指數來定義的。這些值定義了一個從位置開始的光錐,向方向發射。
在弧度中,角度定義了聚光燈的錐形光束的大小(照明區域),指數定義了光的衰減速度和距離(範圍)。
var light = new BABYLON.SpotLight("spotLight", new BABYLON.Vector3(0, 30, -10), new BABYLON.Vector3(0, -1, 0), Math.PI / 3, 2, scene);
4 、The Hemispheric Light——半球光(模擬環境光)
- 一個半球的光是一種簡單的模擬環境光的方法。
- 一個半球的光是由一個方向來定義的,通常是向天空“向上”。
- 然後,通過設定顏色屬性來實現完全的效果。
var light = new BABYLON.HemisphericLight("HemiLight", new BABYLON.Vector3(0, 1, 0), scene);
十二、燈光相關
1、Color Properties——顏色屬性
- 有三種燈光的屬性會影響顏色。
- 其中的兩種漫射和高光適用於所有四種類型的光,第三種,地面顏色ground color,只適用於半球光。
- Diffuse漫射給一個物體提供了基本的顏色
- Specular高光在物體上產生高光顏色
- 帶有黑色背景色的白色半球光是一種有用的照明方法
- 白色/黑色半球光-向上的畫素白色(漫射),向下的畫素黑色(底色)
2、Limitations——限制
Babylon.js允許你建立和註冊儘可能多的燈,但要知道,一個標準材質只能處理一個定義的數字同步燈。
(預設情況下,這個值等於4,這意味著場景燈光列表中的前四個指示燈)。你可以用這段程式碼來改變這個數字:
var material = new BABYLON.StandardMaterial("mat", scene);
material.maxsimultaneousLights = 6;
但是要小心!因為有更多的動態燈光,Babylon.js將生成更大的陰影,這可能與手機或小型平板電腦等低端裝置不相容。
在這種情況下,Babylon.js將嘗試用更少的燈光重新編譯著色器。
3、On, Off or Dimmer——開啟,關閉或調光
- 每一個燈都可以關閉
light.setEnabled(false);
- 或開啟
light.setEnabled(true);
想要調暗或調量光線?然後設定強度intensity屬性(預設值為1)
light0.intensity = 0.5;
light1.intensity = 2.4;
對於點燈和聚光燈你可以設定光的範圍range熟悉
light.range = 100;
4、Choosing Meshes to Light——選擇燈光點亮的網格
當一個光被創造出來時,所有的現有網格都將被它點亮。有兩種方法可以將一些網格從被點亮的地方排除出去。
一個網格可以新增到獨佔的網格陣列中,或者新增不被排除在包含的列表中。
被排除的網格的數量可能是決定使用哪種方法的一個因素。
- Lighting Normals——照明法線
光對一個網格的反應取決於每個網格頂點的值,稱為法線。
每個平面的正面是當法線指向你時你看到的,背面是相反的面。
正如你所看到的,燈光只會影響到正面而不是背面。
- Lightmaps——燈光貼圖
複雜的照明在執行時計算成本非常高。為了節省計算,燈光貼圖可以用來儲存計算出的照明,這種紋理將被應用到一個給定的網格中
var lightmap = new BABYLON.Texture("lightmap.png", scene);
var material = new BABYLON.StandardMaterial("material", scene);
material.lightmapTexture = lightmap
使用紋理作為陰影貼圖而不是光照貼圖,設定 material.useLightmapAsShadowmap欄位為true
場景燈光與光照貼圖混合的方式是基於場景中燈光的lightmapMode模式。
light.lightmapMode = BABYLON.Light.LIGHTMAP_DEFAULT;
使光照貼圖的紋理在光線應用後被混合。
light.lightmapMode = BABYLON.Light.LIGHTMAP_SPECULAR;
下面這個和LIGHTMAP_DEFAULT是一樣的,除了光的高光和陰影將被應用
light.lightmapMode = BABYLON.Light.LIGHTMAP_SHADOWSONLY;
這和lightmapdefault是一樣的除了只有從這個光中得到的陰影將被應用
- Projection Texture——投影紋理
在某些情況下,定義光的漫射顏色(擴散給物體的基本顏色)是很好的,從一個恆定的顏色的紋理。想象一下,你正在試圖模擬教堂內部的燈光效果。
穿過彩色玻璃的光線將投射在地面上。
這同樣適用於從投影儀上發出的光線,或者你可以在迪斯科舞廳看到的燈光效果。
>>>>為了支援這個特性,可以依賴於燈光的projectionTexture屬性。到目前為止,只支援聚光燈SpotLight
注:轉載請註明出處