1.重用Material和Geometry
2.不在render()中實(shí)例化或是賦值操作
3.粒子系統(tǒng)代替粒子
4.操作一組對(duì)象使用Object3D或group
5.網(wǎng)格合并merge
6.使用Web workers
https://threejs.org/examples/?q=sand#raytracing_sandbox
7.分時(shí)加載算法(大數(shù)組)
8.延時(shí)渲染THREE.DefaultLoadingManager
9.刪除模型remove,使用dispose釋放幾何和材質(zhì),RenderTarget,texture
10.BufferGeometry代替Geometry
11.減少浮點(diǎn)計(jì)算团驱,寫成小數(shù)乘法
12.使用clone()方法
13.紋理圖片尺寸一定得是2的冪次方熊赖,并盡可能的小
14.跳幀設(shè)置
15.降低模型的復(fù)雜度減少面數(shù)
16.使用chrome的插件three.js inspector
17.使用stats.js進(jìn)行檢測(cè)幀率
18. JavaScript中的對(duì)象創(chuàng)建很昂貴徐矩,因此不要在循環(huán)中創(chuàng)建對(duì)象钦奋。相反瓢宦,創(chuàng)建一個(gè)單獨(dú)的對(duì)象斥季,如Vector3何暮,并vector.set()
在循環(huán)中使用或類似的方法
19.Web瀏覽器使用的JavaScript引擎經(jīng)常更改,并在幕后對(duì)代碼進(jìn)行了大量?jī)?yōu)化婆赠。不要相信你的直覺(jué)會(huì)更快绵脯,總是測(cè)試佳励。不要相信幾年前的文章告訴你要避免某些方法,如array.map或array.forEach蛆挫。自己測(cè)試一下赃承。
模型,網(wǎng)格和其他可見(jiàn)的東西
- 避免使用常見(jiàn)的基于文本的3D數(shù)據(jù)格式(如Wavefront OBJ或COLLADA)進(jìn)行資產(chǎn)交付悴侵。相反瞧剖,請(qǐng)使用針對(duì)Web優(yōu)化的格式,例如glTF
- 使用帶有g(shù)lTF的Draco網(wǎng)格壓縮
- 如果您需要使大組對(duì)象可見(jiàn)且不可見(jiàn)(或在場(chǎng)景中添加/刪除它們)可免,請(qǐng)考慮使用圖層以獲得最佳性能
- 位于相同位置的物體會(huì)導(dǎo)致閃爍抓于。嘗試抵消一些微小的東西<math><semantics><annotation encoding="application/x-tex">0.001</annotation></semantics></math>0 。0 0 1使事物看起來(lái)像是在同一個(gè)位置浇借,但讓你的GPU保持開(kāi)心
- 使場(chǎng)景以原點(diǎn)為中心捉撮,以防止在大坐標(biāo)處出現(xiàn)浮點(diǎn)錯(cuò)誤
- 切勿移動(dòng)Scene對(duì)象。它創(chuàng)建于<math><semantics><annotation encoding="application/x-tex">(0,0,0)</annotation></semantics></math>(0 妇垢,0 巾遭,0 ),這是其中所有對(duì)象的默認(rèn)參考框架闯估。
使您的平截頭體盡可能小灼舍,以獲得更好的性能。在開(kāi)發(fā)中使用大平截頭體是很好的涨薪,但是一旦你對(duì)應(yīng)用程序進(jìn)行微調(diào)以進(jìn)行部署骑素,就可以使你的平截頭體盡可能小,以獲得一些FPS
不要把東西放在遠(yuǎn)剪裁平面上(特別是如果你的遠(yuǎn)剪裁平面真的很大)刚夺,這可能會(huì)導(dǎo)致閃爍 - 不要使用
TriangleFanDrawMode
献丑,它很慢。 - 當(dāng)您有數(shù)百或數(shù)千個(gè)類似的幾何時(shí)光督,請(qǐng)使用幾何實(shí)例化
- 在GPU而不是CPU上進(jìn)行動(dòng)畫處理阳距,尤其是在為頂點(diǎn)或粒子設(shè)置動(dòng)畫時(shí)(有關(guān)此方法的一種方法塔粒,請(qǐng)參閱THREE.Bas)
性能
- 設(shè)置
object.matrixAutoUpdate = false
為靜態(tài)或很少移動(dòng)的對(duì)象结借,并object.updateMatrix()
在更新其位置/四元數(shù)/比例時(shí)手動(dòng)調(diào)用 - 透明對(duì)象很慢,在場(chǎng)景中使用盡??可能少的透明對(duì)象
-
alphatest
如果可能卒茬,使用而不是標(biāo)準(zhǔn)透明度船老,它更快 - 在測(cè)試應(yīng)用程序的性能時(shí),您需要做的第一件事就是檢查它是受CPU限制還是GPU綁定圃酵。使用基本材料替換所有材料
scene.overrideMaterial
(請(qǐng)參閱初學(xué)者提示和頁(yè)面開(kāi)頭)柳畔。如果性能提高,那么您的應(yīng)用就是GPU限制郭赐。 - 在快速機(jī)器上進(jìn)行性能測(cè)試時(shí)薪韩,您可能會(huì)獲得60fps的最大幀速率。使用
open -a "Google Chrome" --args --disable-gpu-vsync
fo run 無(wú)限幀率運(yùn)行chrome - 現(xiàn)代移動(dòng)設(shè)備具有高的像素比率 <math><semantics><annotation encoding="application/x-tex">五</annotation></semantics></math>5 - 考慮在這些設(shè)備上將最大像素比率限制為2或3,但會(huì)犧牲一些非常輕微的場(chǎng)景模糊
- 烘焙光照和陰影貼圖以減少場(chǎng)景中的燈光數(shù)量
- 如果您有資源和時(shí)間俘陷,請(qǐng)使用壓縮紋理罗捎。不幸的是,為網(wǎng)絡(luò)設(shè)置這些內(nèi)容是一件很痛苦的事情拉盾,因?yàn)樗性O(shè)備都不支持任何格式
- 密切關(guān)注場(chǎng)景中的drawcalls數(shù)量桨菜。一個(gè)好的經(jīng)驗(yàn)法則是減少繪制調(diào)用=更好的性能
- 遠(yuǎn)處的物體不需要與靠近相機(jī)的物體具有相同的細(xì)節(jié)水平。有許多技巧用于通過(guò)降低遠(yuǎn)處物體的質(zhì)量來(lái)提高性能捉偏。例如倒得,LOD(細(xì)節(jié)級(jí)別)對(duì)象存儲(chǔ)不同距離的不同對(duì)象(例如,近夭禽,中和遠(yuǎn))霞掺。您也可能只為遠(yuǎn)處的物體每隔2幀或3幀更新位置/動(dòng)畫
盡可能減少多重計(jì)數(shù)。請(qǐng)記住驻粟,模型根本不應(yīng)該過(guò)于詳細(xì)根悼。
將Obj文件轉(zhuǎn)換為Json和/或?yàn)閳?chǎng)景中的每個(gè)對(duì)象創(chuàng)建單獨(dú)的JSON文件。請(qǐng)記住蜀撑,geometry是您嘗試加載的文件中最重的數(shù)據(jù)塊挤巡。因此,如果可能酷麦,BufferGeometry為每個(gè)文件創(chuàng)建單獨(dú)的文件并通過(guò)它加載BufferGeometryLoader
在加載所有js和json文件之前矿卑,您可以使用一些壓縮/解壓縮技術(shù)。查看OpenCTM壓縮沃饶。您也可以嘗試gzip您的文件并對(duì)其進(jìn)行放氣母廷。
在創(chuàng)建網(wǎng)格的3d建模階段,合并盡可能多的幾何糊肤。最簡(jiǎn)單的方法是識(shí)別具有相同/相似材料的所有網(wǎng)格琴昆,合并這些幾何,并為這些幾何分配相同的材質(zhì)馆揉。您擁有的幾何數(shù)量越少业舍,渲染管道中繪制調(diào)用的次數(shù)就越少。因此升酣,您的表現(xiàn)將會(huì)提高舷暮。
您可以跟蹤您的drawcalls使用情況renderer.info
保持紋理文件大小較低的分辨率。我一般建議少于1K噩茄。
材料性能成本是這樣的MeshBasicMaterial< MeshLambertMaterial< MeshPhongMaterial< MeshStandardMaterial< MeshPhysicalMaterial下面。在將材質(zhì)指定給幾何體時(shí)要小心。Threejs doc清楚地說(shuō)明了每種材料的所有特征绩聘。因此沥割,如果您知道對(duì)象不需要材料的某些屬性耗啦,則回退到更便宜的材質(zhì)。
使用normalMaps偽造的goemetries机杜。這將減少您vertices所需的數(shù)量芹彬。
如果您的場(chǎng)景是靜態(tài)使用aoMap并且LightMap在場(chǎng)景中消除了對(duì)光源的需求及其計(jì)算成本。
如果場(chǎng)景是靜態(tài)的叉庐,請(qǐng)停止requestAnimationFrame并僅在需要時(shí)渲染舒帮。例。如果您使用的是orbitcontrol.js陡叠,請(qǐng)onChange在觸發(fā)用戶活動(dòng)時(shí)使用方法進(jìn)行渲染玩郊。
使用Chrome擴(kuò)展程序,如Threejs Inspector和WebGL Inspector進(jìn)行調(diào)試枉阵。
如果動(dòng)態(tài)刪除場(chǎng)景中的任何內(nèi)容译红,請(qǐng)確保正確處理數(shù)據(jù)。
300 MB的文件非常大兴溜。確保將其減少到30 mb或更低侦厚,理想情況下,低于10 mb以獲得最佳體驗(yàn)拙徽。
從場(chǎng)景中刪除一些東西刨沦?
首先,考慮不這樣做膘怕,特別是如果你稍后再添加它想诅。您可以暫時(shí)隱藏對(duì)象object.visible = false(也適用于燈光),或者material.opacity = 0岛心。您可以設(shè)置light.intensity = 0禁用燈光而不會(huì)導(dǎo)致著色器重新編譯来破。
后期處理
- 內(nèi)置的抗鋸齒功能不適用于后期處理(至少在WebGL 1中)。您需要使用FXAA或SMAA手動(dòng)執(zhí)行此操作(可能更快忘古,更好)
- 由于您沒(méi)有使用內(nèi)置AA徘禁,請(qǐng)務(wù)必禁用它!
- three.js有大量的后處理著色器髓堪,這真是太棒了送朱!但請(qǐng)記住,每次傳遞都需要渲染整個(gè)場(chǎng)景旦袋。完成測(cè)試后骤菠,請(qǐng)考慮是否可以將一些傳遞合并到一個(gè)自定義傳遞中
幾何
避免使用線環(huán)它改,因?yàn)樗仨氂删€條模擬
紋理
- 你的所有紋理都必須是2的冪(POT)大邪淘小: <math><semantics><annotation encoding="application/x-tex">1,2,4,8,16,...央拖,512,2048 ......</annotation></semantics></math>1 祭阀,2 鹉戚,4 ,8 专控,1 6 抹凳,...,5 1 2 伦腐,2 0 4 8 赢底,...
- 不要更改紋理的尺寸。相反柏蘑,創(chuàng)建新的幸冻,它更快
- 盡可能使用最小的紋理尺寸(你可以使用256x256平鋪紋理逃脫嗎?你可能會(huì)感到驚訝?确佟)
- 非二次冪(NPOT)紋理需要線性或最近的濾波洽损,以及鉗位到邊界或鉗位到邊緣的包裝。不支持Mipmap過(guò)濾和重復(fù)包裝革半。但嚴(yán)重的是碑定,只是不要使用NPOT紋理
- 具有相同尺寸的所有紋理在內(nèi)存中的大小相同,因此JPG的文件大小可能比PNG小又官,但它會(huì)占用GPU上相同的內(nèi)存量
定制材料
只有在他們改變時(shí)才更新你的制服延刘,而不是每一幀。
物料
內(nèi)置的three.js材料具有簡(jiǎn)單的性能/質(zhì)量權(quán)衡:
-
MeshStandardMaterial
最高質(zhì)量/最慢 MeshPhongMaterial
MeshLambertMaterial
-
MeshBasicMaterial
質(zhì)量最低/最快
使用您能承受的最優(yōu)質(zhì)材料六敬,并在需要時(shí)切換到質(zhì)量較差的材料访娶。
-
MeshLambertMaterial
不適用于有光澤的材料,但對(duì)于像布料這樣的啞光材料觉阅,它會(huì)產(chǎn)生非常相似的結(jié)果崖疤,MeshPhongMaterial
但速度更快 - 如果您正在使用變形目標(biāo),請(qǐng)確保
morphTargets = true
在材料中設(shè)置典勇,否則它們將無(wú)效劫哼! - 同去的變形法線
- 如果您使用SkinnedMesh進(jìn)行骨骼動(dòng)畫,請(qǐng)確保
material.skinning = true
- 與變形目標(biāo)割笙,變形法線或蒙皮一起使用的材質(zhì)無(wú)法共享权烧。您需要為每個(gè)蒙皮或變形網(wǎng)格創(chuàng)建一個(gè)獨(dú)特的材質(zhì)(
material.clone()
這里是您的朋友)。
陰影
- 如果場(chǎng)景是靜態(tài)的伤溉,則僅在更改內(nèi)容時(shí)更新陰影貼圖般码,而不是每幀
- 使用a
CameraHelper
可視化陰影相機(jī)的視錐體 - 請(qǐng)記住,點(diǎn)光陰影比其他陰影類型更昂貴乱顾,因?yàn)樗鼈儽仨氫秩玖危總€(gè)方向一次)板祝,而單個(gè)時(shí)間
DirectionalLight
和SpotLight
陰影相比 - 雖然我們對(duì)的話題
PointLight
陰影,注意走净,CameraHelper
只能可視化一個(gè)出6用于可視化的點(diǎn)光源陰影時(shí)券时,陰影的方向孤里。它仍然有用,但你需要將你的想象力用于其他5個(gè)方向
燈橘洞,尤其是SpotLight捌袜,PointLight,DirectionalLight很慢炸枣。在場(chǎng)景中使用盡??可能少的燈光
避免在場(chǎng)景中添加和刪除燈光虏等,因?yàn)檫@需要WebGLRenderer重新編譯所有著色器程序(它會(huì)緩存程序以便隨后執(zhí)行此操作,它會(huì)比第一個(gè)更快)
打開(kāi)renderer.physicallyCorrectLights使用SI單位的精確照明
渲染
-
preserveDrawingBuffer
除非您需要适肠,否則請(qǐng)勿啟用 - 除非您需要博其,否則禁用alpha緩沖區(qū)
- 除非您需要,否則不要啟用模板緩沖區(qū)
- 除非你需要它迂猴,否則禁用深度緩沖區(qū)(但你可能確實(shí)需要它)
-
powerPreference: "high-performance"
在創(chuàng)建渲染器時(shí)使用慕淡。這可能使用戶系統(tǒng)在多GPU系統(tǒng)中選擇高性能GPU。 - 考慮僅在相機(jī)位置通過(guò)epsilon或動(dòng)畫發(fā)生時(shí)更改時(shí)進(jìn)行渲染
- 如果您的場(chǎng)景是靜態(tài)的并且使用
OrbitControls
沸毁,您可以監(jiān)聽(tīng)change
事件以僅在相機(jī)移動(dòng)時(shí)渲染:
OrbitControls.addEventListener( 'change', () => renderer.render( scene, camera ) );
你不會(huì)從最后兩個(gè)獲得更高的幀速率峰髓,但你會(huì)得到的是更少的筆記本電腦風(fēng)扇開(kāi)啟,以及移動(dòng)設(shè)備上的電池消耗更少息尺。
注意:我已經(jīng)看到網(wǎng)絡(luò)上的一些地方建議您禁用抗鋸齒并應(yīng)用后處理AA通道携兵。在我的測(cè)試中,這不是真的搂誉。在現(xiàn)代硬件上徐紧,即使在低功耗移動(dòng)設(shè)備上,內(nèi)置MSAA似乎也非常便宜炭懊,而后處理FXAA或SMAA通過(guò)導(dǎo)致相當(dāng)大的幀丟失
Three.js OffscreenCanvas
產(chǎn)生陰影的:
THREE.DirectionLight() 平型光
THREE.PointLight() 點(diǎn)光源
THREE.SpotLight() 聚光燈
不產(chǎn)生陰影的:
THREE.AmbientLight() 環(huán)境光
THREE.HemiphereLight() 半球光
THREE.RectAreaLight() 平面光源