GLTF模型讲解
前言
在繁忙的業(yè)務(wù)中,為了縮短設(shè)計和開發(fā)的周期,我們的 H5 小游戲更多的會采用 2D 的視覺風(fēng)格,但總是一個風(fēng)格是很無趣的,所以最近搞了一個 3D 物理游戲的需求,在開發(fā)的過程中遇到了不少問題,希望通過這篇文章將關(guān)于 Three.js、Cannon.js、模型、工具等基礎(chǔ)知識、問題總結(jié)分享給大家。
開始 3D 項(xiàng)目之前,首先從選擇 3D 框架開始,老牌引擎 Three.js 和微軟的 Babylon.js 都不錯,針對自己的項(xiàng)目需求選擇一款即可,這次我主要針對更熟悉的 Three.js 來講。
Three.js 基礎(chǔ)概念
使用 Three.js 前,首先要理解以下幾個核心概念:
Sence 場景
在 Three.js 中首先需要創(chuàng)建一個三維空間,我們稱之為場景。場景可以想象成是一個容器,里面存放著所有渲染的物體和使用的光源。
Axes 坐標(biāo)軸
Three.js 采用的是右手坐標(biāo)系,拇指、食指、中指分別表示 X、Y、Z 軸的方向。
Camera 攝像機(jī)
攝像機(jī)就相當(dāng)于我們的雙眼,決定了能夠在場景中的所見所得。
Three.js 中提供以下幾種攝像機(jī)類型,最為常用的是透視攝像機(jī),其他了解下即可。
ArrayCamera 陣列攝像機(jī)
一個 ArrayCamera 會包含多個子攝像機(jī),通過這一組子攝像機(jī)渲染出實(shí)際效果,適用于 VR 場景。
CubeCamera 立方攝像機(jī)
創(chuàng)建六個 PerspectiveCamera(透視攝像機(jī)),適用于鏡面場景。
StereoCamera 立體相機(jī)
雙透視攝像機(jī)適用于 3D 影片、視差效果。
OrthographicCamera 正交攝像機(jī)
OrthographicCamera(正交攝像機(jī))定義了一個矩形可視區(qū)域,物體只有在這個區(qū)域內(nèi)才是可見的,另外物體無論距離攝像機(jī)是遠(yuǎn)或事近,物體都會被渲染成一個大小,所以這種攝像機(jī)類型適用于 2.5D 場景(例如斜 45 度游戲)。
PerspectiveCamera 透視攝像機(jī)
最為常用的攝像機(jī)類型,模擬人眼的視覺,根據(jù)物體距離攝像機(jī)的距離,近大遠(yuǎn)小。默認(rèn)情況下,攝像機(jī)的初始位置 X、Y、Z 都為 0,攝像機(jī)方向是從正 Z 軸向負(fù) Z 軸看去。通過 Near和 Far 定義最近和最遠(yuǎn)的可視距離,Fov 定義可視的角度。
Mesh 網(wǎng)格
有了場景和攝像頭就可以看到 3D 場景中的物體,場景中的我們最為常用的物體稱為網(wǎng)格。
網(wǎng)格由兩部分組成:幾何體和材質(zhì)
Geometry 幾何體
記錄了渲染一個 3D 物體所需要的基本數(shù)據(jù):Face 面、Vertex 頂點(diǎn)等信息。
例如下面這個網(wǎng)格是由三角形組成,組成三角形的點(diǎn)稱為頂點(diǎn),組成的三角形稱為面。
Material 材質(zhì)
材質(zhì)就像是物體的皮膚,決定了幾何體的外表。
外表的定義可以讓一個物體看起來是否有鏡面金屬感、暗淡、純色、或是透明與否等效果。
Light 光源
光源相當(dāng)于在密閉空間里的一盞燈,對于場景是必不可少的
在 Three.js 常用的有這幾種光源:
AmbientLight 環(huán)境光源
屬于基礎(chǔ)光源,為場景中的所有物體提供一個基礎(chǔ)亮度。
DirectionalLight 平行光源
效果類似太陽光,發(fā)出的光源都是平行的。
HemisphereLight 半球光
只有圓球的半邊會發(fā)出光源。
PointLight 點(diǎn)光源
一個點(diǎn)向四周發(fā)出光源,一般用于燈泡。
SpotLight 聚光燈光源
一個圓錐體的燈光。
Shadow 陰影
另外要注意并不是每一種光源都能產(chǎn)生陰影,目前只有三種光源可以:
- DirectionalLight 平行光源
- PointLight 點(diǎn)光源
- SpotLight 聚光燈光源
另外如果要開啟模型的陰影的話,模型是由多個 Mesh 組成的,只開啟父的 Mesh 的陰影是不行的,還需要遍歷父 Mesh 下所有的子 Mesh 為其開啟投射陰影 castShadow 和接收投射陰影 receiveShadow。
// 遍歷子 Mesh 開啟陰影 object.traverse(function(child) {if (child instanceof THREE.Mesh) {child.castShadow = truechild.receiveShadow = true} })glTF 模型格式
前面提到 Three.js 引擎支持的格式非常的多,我們最為常見的格式有 .obj + .mtl +.jpg/.png,但使用這種模型格式存在一個問題,.obj 是靜態(tài)模型,不支持動畫數(shù)據(jù)存儲,無法使用模型的動畫,所以我建議使用 glTF 這種模型格式。
glTF 模型格式介紹
傳統(tǒng)的 3D 模型格式的設(shè)計理念更多是針對本地離線使用,所以這類 3D 模型格式?jīng)]有針對下載速度或加載速度進(jìn)行優(yōu)化,文件大小往往會非常的大,隨著 Web 端的興起,對文件大小更為敏感的今天,我們該嘗試別的模型格式了。
glTF 是由 Khronos Group 開發(fā)的 3D 模型文件格式,該格式的特點(diǎn)是最大程度的減少了 3D 模型文件的大小,提高了傳輸、加載以及解析 3D 模型文件的效率,并且它可擴(kuò)展,可互操作。
第一版 glTF 1.0 于 2015 年 10 月 19 日發(fā)布,2017 年 6 月 5 日的 Web 3D 2017 大會發(fā)布了最終版本 glTF 2.0。
glTF 模型格式文件組成
模型文件 .gltf
包含場景中節(jié)點(diǎn)層次結(jié)構(gòu)、攝像機(jī)、網(wǎng)格、材質(zhì)以及動畫等描述信息。
二進(jìn)制文件 .bin
包含幾何、動畫的數(shù)據(jù)以及其他基于緩沖區(qū)的數(shù)據(jù),.bin 文件可以直接加載到 GPU 的緩沖區(qū)中從而不需要額外的解析,因此能夠高效傳輸和快速加載。
材質(zhì)貼圖文件 .png / .jpg
3D 模型做凹凸貼圖或普通貼圖上所使用到文件。
glTF 模型格式導(dǎo)出
官方在 glTF 格式導(dǎo)出上提供了多種建模軟件的導(dǎo)出插件,比如有:
- 3DS Max Exporter
- Maya Exporter
- Blender glTF 2.0 Exporter
- ...
正巧我們常用的 C4D 建模軟件官方?jīng)]有提供 C4D 的導(dǎo)出插件,所以我們使用 C4D 導(dǎo)出后再導(dǎo)入 Blender,通過 Blender 作為中轉(zhuǎn)站導(dǎo)出 glTF 格式文件。
但由于兩個建模軟件之間的材質(zhì)并不能相通,導(dǎo)出后的模型文件材質(zhì)效果表現(xiàn)不佳,這是因?yàn)?Blender 有自己的一套材質(zhì)流程系統(tǒng),例如有 glTF Metallic Roughness 和 glTF Specular Glossiness,需在此基礎(chǔ)之上重新貼材質(zhì)后導(dǎo)出解決。
另外注意的一點(diǎn) Blender 的坐標(biāo)系與 Three.js 是不同的,Blender 會將 Z 和 Y 對調(diào)位置,在導(dǎo)出時要選擇 Convert Z up to Y up 進(jìn)行對調(diào)。
Three.js 使用 glTF 模型
Three.js 中使用 glTF 格式需額外引入 GLTFLoader.js 加載器。
var gltfLoader = new THREE.gltfLoader()gltfLoader.load(’./assets/box.gltf’, function(sence) {
var object = scene.gltf // 模型對象
scene.add(object) // 將模型添加到場景中
})
glTF 模型動畫
Animation Clip 動畫片段
前面提到 glTF 模型格式支持動畫,模型動畫可以使用 Blender 建模軟件制作,通過 Blender 提供的時間軸編輯變形動畫或者骨骼動畫,每個動畫可以編輯為一個 Action 動作,導(dǎo)出后使用 GLTFLoader 加載到 Three.js 中,可以拿到一個 animations 數(shù)組,animations 里包含了模型的每個動畫 Action 動作。
let gltfLoader = new THREE.gltfLoader()let mixer = null
gltfLoader.load(’./assets/box.gltf’, function(sence) {
let object = scene.gltf
let animations = sence.animations // 動畫數(shù)據(jù)
if (animations && animations.length) {
mixer = new THREE.AnimationMixer(object) // 對動畫進(jìn)行控制
for (let i = 0; i < animations.length; i++) {
mixer.clipAction(animations[i]).play() // 播放所有動畫
}
}
scene.add(object)
})
function update() {
let delta = clock.getDelta(mixer)
mixer.update(delta) // 更新動畫片段
}
Tween 動畫
對模型實(shí)現(xiàn)淡入淡出、縮放、位移、旋轉(zhuǎn)等動畫推薦使用 GSAP 來實(shí)現(xiàn)更為簡便。
let tween = new TimelineMax()tween.to(box.scale, 1, { // 從 1 縮放至 2,花費(fèi) 1 秒
x: 2,
y: 2,
z: 2,
ease: Power0.easeInOut, // 速度曲線
onStart: function() { // 監(jiān)聽動畫開始 },
onUpdate: function() { // 監(jiān)聽動畫過程 },
onComplete: function() { // 監(jiān)聽動畫結(jié)束 }
}).to(box.position, 1, { // 縮放結(jié)束后,位移 x 至 10,花費(fèi) 1 秒
x: 10,
y: 0,
z: 0
})
Draco 3D 模型壓縮工具
Draco 是一個用于壓縮、解壓縮 3D 幾何網(wǎng)格和點(diǎn)云的開源庫,為改善 3D 圖形存儲和傳輸而設(shè)計。
使用該工具可以對 glTF 格式進(jìn)一步的壓縮,會將 glTF 格式轉(zhuǎn)為 .glb 格式,并且 .bin 壓縮效果拔群,但是在 Three.js 中使用.glb 格式需要引入額外的解析庫,解析庫文件包括 draco_decoder.js(791KB)、draco_decoder.wasm(323 KB)、draco_wasm_wrapper.js(64.3 KB)。所以更推薦當(dāng)模型文件數(shù)量多,且文件較大時使用,否則得不償失。
壓縮使用 glTF Pipeline 工具,需要將三個種類的文件放在一起,執(zhí)行命令行進(jìn)行轉(zhuǎn)換。
$ npm install -g gltf-pipeline // 安裝 gltf-pipeline 工具$ gltf-pipeline -i model.gltf -o model.glb // 指定某個 .gltf 文件轉(zhuǎn)為 .glb 格式
Three.js 使用 .glb 格式引入 Draco 解碼庫
// 實(shí)例化 loaderlet loader = new THREE.GLTFLoader()
// Draco 解碼庫
THREE.DRACOLoader.setDecoderPath(’/examples/js/libs/draco’)
loader.setDRACOLoader(new THREE.DRACOLoader())
// 加載 glTF 模型
loader.load(‘models/gltf/box.gltf’, function(gltf) {
scene.add(gltf.scene)
})
Cannon.js 3D 物理引擎
目前在 Github 上搜索到的 3D 物理引擎庫有 Cannon.js、Oimo.js、Ammo.js、Energy.js、Physijs 等等,大部分都已許久沒有更新迭代了(長達(dá)好幾年),項(xiàng)目的 Star 數(shù)量和 Issues 數(shù)量也不多,我們該如何選擇?
Cannon.js、Oimo.js 和 Energy.js 作為 Babylon.js 的內(nèi)置物理引擎,我們試著從這三個下手。
Energy.js:使用 C++ 編寫轉(zhuǎn) JavaScript 的 3D 物理引擎,源碼不可讀,目前 Github 比較冷清。
Oimo.js:一款輕量級的 3D 物理引擎,文件大小 153 KB。
Cannon.js:完全使用 JavaScript 編寫的優(yōu)秀 3D 物理引擎,包含簡單的碰撞檢測、各種形狀的摩擦力、彈力、約束等功能。
從綜合性來看,我更偏向于 Cannon.js ,所以下面主要講講 Cannon.js。
Cannon.js 的特性
以下是 Cannon.js 的特性,基本可以滿足大部分的 3D 物理開發(fā)場景。
使用 Cannon.js
我們以官方的一個平面加球剛體的例子來快速上手 Cannon.js。在線例子
1、初始化物理世界
使用 Cannon.js 前需要創(chuàng)建 CANNON.World 對象,CANNON.World 對象是負(fù)責(zé)管理對象和模擬物理的中心。
創(chuàng)建完 CANNON.World 對象后,接著設(shè)置物理世界的重力,這里設(shè)置了負(fù) Y 軸為 10 m/s2。
let world = new CANNON.World()world.gravity.set(0, -10, 0)
Cannon.js 提供了 Broadphase、NaiveBroadphase 兩種碰撞檢測階段,默認(rèn)是 NaiveBroadphase。
world.broadphase = new CANNON.NaiveBroadphase()2、創(chuàng)建動態(tài)球體
創(chuàng)建 Body 分三個步驟:
- 創(chuàng)建形狀
- 為形狀添加剛體
- 將剛體添加到世界
let sphereBody = new CANNON.Body({ // Step 2
mass: 5,
position: new CANNON.Vec3(0, 10, 0),
shape: sphereShape
})
world.add(sphereBody) // Step 3
第一步創(chuàng)建了半徑為 1 的球形,第二步創(chuàng)建球的剛體,如果剛體的 mass 屬性設(shè)置為 0,剛體則會處于靜止?fàn)顟B(tài),靜止的物體不會和其他靜止的物體發(fā)生碰撞,我們這里為球的剛體設(shè)置了 5kg,球會處于動態(tài)的狀態(tài),會受的重力的影響而移動,會與其他物體發(fā)生碰撞。
3、創(chuàng)建靜態(tài)平面和動態(tài)球體
// 平面 Bodylet groundShape = new CANNON.Plane()
let groundBody = new CANNON.Body({
mass: 0,
shape: groundShape
})
// setFromAxisAngle 旋轉(zhuǎn) X 軸 -90 度
groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -1.5707963267948966)
world.add(groundBody)
創(chuàng)建平面形狀,接著是剛體,這里設(shè)置了平面剛體的 mass 為 0,保證剛體處于靜止?fàn)顟B(tài)。默認(rèn)情況下平面的方向是朝向 Z 方向的(豎立著),可以通過 Body.quaternion.setFromAxisAngle 對平面進(jìn)行旋轉(zhuǎn)。
4、創(chuàng)建平面和球的網(wǎng)格
前面創(chuàng)建的剛體在場景中并沒有實(shí)際的視覺效果,這一步創(chuàng)建平面、球的網(wǎng)格。
// 平面網(wǎng)格let groundGeometry = new THREE.PlaneGeometry(20, 20, 32)
let groundMaterial = new THREE.MeshStandardMaterial({
color: 0x7f7f7f,
side: THREE.DoubleSide
})
let ground = new THREE.Mesh(groundGeometry, groundMaterial)
scene.add(ground)
// 球網(wǎng)格
let sphereGeometry = new THREE.SphereGeometry(1, 32, 32)
let sphereMaterial = new THREE.MeshStandardMaterial({ color: 0xffff00 })
let sphere = new THREE.Mesh(sphereGeometry, sphereMaterial)
scene.add(sphere)
5、模擬世界
接著我們?yōu)槲锢硎澜玳_啟持續(xù)更新,并且將創(chuàng)建的球剛體與球網(wǎng)格關(guān)聯(lián)起來。
function update() {requestAnimationFrame(update)
world.step(1 / 60)
if (sphere) {
sphere.position.copy(sphereBody.position)
sphere.quaternion.copy(sphereBody.quaternion)
}
}
通過這幾步,一個簡單的物理場景就完成了,另外更多官方例子可以點(diǎn)擊這里,可以查看到 Cannon.js 各個約束、摩擦力、模擬汽車等特性的例子。
其他:
1、自定義物理材質(zhì)需關(guān)聯(lián)
還是上面的例子,現(xiàn)在場景中剛體的物理特性都為默認(rèn)的,我希望球的恢復(fù)系數(shù)高一點(diǎn),即掉落時彈跳的更高。首先需要通過 CANNON.Material 實(shí)例物理材質(zhì),剛體使用該物理材質(zhì),最后通過 CANNON.ContactMaterial 來定義兩個剛體相遇后會發(fā)生什么。
// 平面let ground_cm = new CANNON.Material() // Step 1 : 實(shí)例 CANNON.Material
let groundBody = new CANNON.Body({
…
material: groundMaterial // Step 2 : 使用該物理材質(zhì)
…
})
// 球
let sphere_cm = new CANNON.Material()
let sphereBody = new CANNON.Body({
…
material: sphere_cm
…
})
let sphere_ground = new CANNON.ContactMaterial(ground_cm, sphere_cm, { // Step 3 : 定義兩個剛體相遇后會發(fā)生什么
friction: 1,
restitution: 0.4
})
world.addContactMaterial(sphere_ground) // Step 4 : 添加到世界中
2、剛體添加位移動畫時需取消速度值
比如我使用 GSAP 庫對某個剛體進(jìn)行 Y 軸向上移動,在 update 階段需要將剛體的重力加速度設(shè)置為 0,否則動畫結(jié)束后剛體會出現(xiàn)向下砸的效果。
let tween = new TimelineMax()tween.to(boxBody.position, 2, {
x: 0,
y: 10,
z: 0,
update: function() {
// 歸 0 設(shè)置
boxBody.velocity.setZero()
boxBody.initVelocity.setZero()
boxBody.angularVelocity.setZero()
boxBody.initAngularVelocity.setZero()
}
})
3、只檢測碰撞,不發(fā)生物理效果
允許只檢測是否碰撞,實(shí)際不發(fā)生物理效果,需要為剛體添加以下屬性:
boxBody.collisionResponse = false4、縮放剛體
如果剛體需要縮放,則需要為剛體添加此屬性,來更新剛體大小。
boxBody.updateMassProperties()let tween = new TimelineMax()
tween.to(sphereBody.shapes[0], 2, {
radius: 0.2 // 縮放至 0.2
})
點(diǎn)擊交互
在 3D 的世界中不能像我們在 DOM 中為一個節(jié)點(diǎn)綁定點(diǎn)擊事件那么容易,在 Three.js 中提供了 THREE.Raycaster 方法處理點(diǎn)擊交互,使用鼠標(biāo)或者手指點(diǎn)擊屏幕時,會將二維坐標(biāo)進(jìn)行轉(zhuǎn)換,發(fā)射一條射線判斷與哪個物體發(fā)生了碰撞,由此得知點(diǎn)擊了哪個物體。點(diǎn)擊這里官方例子
let raycaster = new THREE.Raycaster()let mouse = new THREE.Vector2()
function onTouchEnd(ev) {
// 點(diǎn)擊獲取屏幕坐標(biāo)
var event = ev.changedTouches[0]
mouse.x = (event.clientX / window.innerWidth) 2 - 1
mouse.y = -(event.clientY / window.innerHeight) 2 + 1
raycaster.setFromCamera(mouse, camera)
let intersects = raycaster.intersectObjects(scene, true)
for (let i = 0; i < intersects.length; i++) {
console.log(intersects[i]) // 與射線發(fā)生碰撞的物體
}
}
性能方面
模型精細(xì)程度
在 Web 端由于性能的限制,在開發(fā)過程中要盡量避免做一些損耗性能較大的事情。
首先是模型的精細(xì)程度,在保證效果的前提下,盡量降低模型面的數(shù)量,也就是說采用低模模型,一些模型的凹凸褶皺感也可以通過凹凸貼圖的方式去實(shí)現(xiàn),越是復(fù)雜的模型在實(shí)時渲染的過程中就越占用手機(jī)性能。
光源與陰影
另外一方面光源、陰影也是占性能,尤其是陰影。光源一般會使用平行光或者聚光燈,這種光源照射在物體上更為真實(shí),使用半球光會稍微提升幀數(shù),但效果略差些,陰影效果前面提到過要遍歷每一個子 Mesh 接收產(chǎn)生陰影 castShadow 和接收陰影 receiveShadow,這相當(dāng)耗費(fèi)性能,開啟后對陰影的精細(xì)程度以及陰影類型進(jìn)行參數(shù)優(yōu)化,在 Android 系統(tǒng)性能不太好,iOS 系統(tǒng)基本能保證流暢運(yùn)行,所以建議根據(jù)設(shè)備系統(tǒng)優(yōu)化。
var n = navigator.userAgentif (/iPad|iPhone|iPod/.test(n) && !window.MSStream) { } // 針對 iOS 系統(tǒng)使用陰影
抗鋸齒與像素比
抗鋸齒是讓模型的邊緣效果更加圓滑不粗糙,也會占用一些性能,默認(rèn)是關(guān)閉的,視情況開啟。
renderer.antialias = true // 開啟抗鋸齒另外像素比 setPixelRatio,移動端由于 Retina 屏的緣故,一般會設(shè)置為 2,所以使用window.devicePixelRatio 獲取實(shí)際設(shè)備像素比動態(tài)設(shè)置的話,部分大屏手機(jī)的像素比有 3 的情況,所有會因?yàn)橄袼乇冗^高造成性能問題。
renderer.setPixelRatio(2) // 推薦renderer.setPixelRatio(window.devicePixelRatio) // 不推薦
工具推薦
最后推薦一些在開發(fā)過程中常用的工具:
OrbitControls 軌道控制器
OrbitControls 是用于調(diào)試 Camera 的方法,實(shí)例化后可以通過鼠標(biāo)拖拽來旋轉(zhuǎn) Camera 鏡頭的角度,鼠標(biāo)滾輪可以控制 Camera 鏡頭的遠(yuǎn)近距離,旋轉(zhuǎn)和遠(yuǎn)近都會基于場景的中心點(diǎn),在調(diào)試預(yù)覽則會輕松許多。
new THREE.OrbitControls(camera, renderer.domElement)glTF Viewer 模型快速預(yù)覽工具
在設(shè)計師建模完成導(dǎo)出后,設(shè)計師并不知道在 Three.js 最終會呈現(xiàn)一個什么效果或者開發(fā)者也想快速的查看模型是否存在問題,glTF 官方貼心的提供了一款快速預(yù)覽的工具,提供了兩個版本:Web 版本和 Desktop 版本。
將 .gltf、.bin、.jpg/.png 文件拖拽到工具中,可以調(diào)試預(yù)覽到模型的動畫、變形目標(biāo)、背景、線框模式、自動旋轉(zhuǎn)、光源等功能。
Camera Helper 攝像機(jī)調(diào)試模式
開啟 Camera Helper 調(diào)試模式后,可以直觀的看到 Camera 的 Fov、 Nera、Far的參數(shù)效果。
let camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000)let helper = new THREE.CameraHelper(camera)
scene.add(helper)
Light Helper 光源調(diào)試模式
聚光燈開啟 Light Helper 調(diào)試模式后,可以直觀的看到 distance、angle 的參數(shù)效果。
let light = new THREE.DirectionalLight(0xffffff)let helper = new THREE.DirectionalLightHelper(0xffffff)
scene.add(helper)
AxesHelper 坐標(biāo)軸調(diào)試模式
AxesHelper 是在場景的中心點(diǎn),添加一個坐標(biāo)軸(紅色:X 軸、綠色:Y 軸、藍(lán)色:Z 軸),方便辨別方向。
let axesHelper = new THREE.AxesHelper(10)scene.add(axesHelper)
Cannon.js 3D 物理引擎調(diào)試模式
Cannon.js 3D 物理引擎提供的調(diào)試模式需引入 Debug renderer for Three.js,可以將創(chuàng)建的物理盒子、球、平面等顯示線框,便于在使用過程中實(shí)時查看效果。
let cannonDebugRenderer = new THREE.CannonDebugRenderer(scene, world)function render() {
requestAnimationFrame(render)
cannonDebugRenderer.update() // Update the debug renderer
}
dat.GUI 圖形用戶界面調(diào)試工具
在開發(fā)過程中,常常需要對參數(shù)變量進(jìn)行微調(diào),針對這個 Three.js 提供了 dat.GUI,dat.GUI 是一個輕量級的圖形用戶界面調(diào)試工具,使用后在右上角會出現(xiàn)一個 GUI 可視化參數(shù)配置區(qū)域,通過修改數(shù)值來實(shí)時查看結(jié)果。
let opts = {x: 0,
y: 0,
scale: 1
}
let gui = new dat.GUI()
gui.add(opts, ‘x’, -3, 3)
gui.add(opts, ‘y’, -3, 3)
gui.add(opts, ‘scale’, 1, 3)
function loop() {
cube.position.x = opt.x
cube.position.y = opt.y
cube.scale.set(opts.scale, opts.scale, opts.scale)
requestAnimationFrame()
}
Stats 調(diào)試工具
Stats 工具可以實(shí)時查看:
FPS:最后一秒的幀數(shù),越大越流暢
MS:渲染一幀需要的時間(毫秒),越低越好
MB:占用的內(nèi)存信息
CUSTOM:自定義面板
var stats = new Stats()stats.showPanel(1)
document.body.appendChild(stats.dom)
function animate() {
requestAnimationFrame(animate)
}
requestAnimationFrame(animate)
尾巴
最后,希望本篇文章所講到的內(nèi)容能幫助你更好的開發(fā) 3D 項(xiàng)目。另外,如果你有更好的建議或意見,也歡迎你在下方評論區(qū)留言,感謝您的閱讀。
我們會定期更新關(guān)于「H5游戲開發(fā)」的文章,歡迎關(guān)注我們的知乎專欄。
總結(jié)
- 上一篇: WinPE安装64位Win7的方法
- 下一篇: 分享多引擎样本查毒网站+多款杀软在线查毒