Three.jsのパフォーマンスの最適化



Three Js Performance Optimization



ジオメトリとマテリアルを共有してみてください

同じ色の300個の単純な立方体モデルを作成する必要がある場合:

for (let i = 0 i <300 i++) { let geometry = new THREE.BoxGeometry(10, 10, 10) let material = new THREE.MeshLambertMaterial({color: 0x00ffff}) let mesh = new THREE.Mesh(geometry, material) //random location mesh.position.set(THREE.Math.randFloatSpread(200), THREE.Math.randFloatSpread(200), THREE.Math.randFloatSpread(200)) group.add(mesh) }

同じジオメトリとマテリアルを共有しようとしています。



let geometry = new THREE.BoxGeometry(10, 10, 10) let material = new THREE.MeshLambertMaterial({color: 0x00ffff}) for (let i = 0 i <300 i++) { let mesh = new THREE.Mesh(geometry, material) //random location mesh.position.set(THREE.Math.randFloatSpread(200), THREE.Math.randFloatSpread(200), THREE.Math.randFloatSpread(200)) group.add(mesh) }

モデルが削除されると、マテリアルとジオメトリがメモリから削除されます

use remove()シーンからモデルを削除すると、基本的にメモリが削減されていないことがわかります。ジオメトリとマテリアルはまだメモリに保存されているため、手動で呼び出す必要があります。dispose()メソッドはそれらをメモリから削除します。

シーングループ全体を削除する場合のケースコードは次のとおりです。



/ / Delete group function deleteGroup(name) { let group = scene.getObjectByName(name) if (!group) return / / Delete all the mesh within the model group group.traverse(function (item) { if (item instanceof THREE.Mesh) { Item.geometry.dispose() //Delete geometry Item.material.dispose() //Delete material } }) scene.remove(group) }

個別に操作する必要のないモデルをマージするには、mergeメソッドを使用します
このメソッドの新しいバージョンは、ジオメトリに統合されています。主なアプリケーションシナリオは、幾何学的に同一の材料が多数あるモデルです。複数のジオメトリを単一の全体的なジオメトリに接続することで、パフォーマンスを節約できます。欠点は、単一のモデルを制御できないことです。
ケースを表示するには、ここをクリックしてください:ここをクリック
組み合わせを選択しないときにredraw20000モデルを選択すると、通常、フレームレートは12フレームになります。ただし、組み合わせを選択すると、レンダリングのフレームレートがフルフレーム(60フレーム)に達する可能性があり、パフォーマンスが大幅に向上します。

マージの使用法:

/ / Merge the model, then merge using the merge method var geometry = new THREE.Geometry() The //merge method merges two geometry objects or geometry objects inside Object3D, and uses the transformation of the object to merge the vertices, faces, and UVs of the geometry. / / / / / / / / / / / / / / / for(var i=0 i<20000 i++){ Var cube = addCube() //Create a geometry model at a random location cube.updateMatrix() //Manually update the matrix of the model Geometry.merge(cube.geometry, cube.matrix) //Merge geometry } scene.add(new THREE.Mesh(geometry, cubeMaterial))

ループレンダリングで更新を使用しないでください

ここでの更新は、現在のジオメトリ、マテリアル、テクスチャなどが変更されていることを示しています。次のようなメモリデータを再更新する必要があります。



  • ジオメトリ:
Three.js
  • 材料
geometry.verticesNeedUpdate = true //The vertices have been modified geometry.elementsNeedUpdate = true //The face has been modified geometry.morphTargetsNeedUpdate = true //The deformation target has been modified geometry.uvsNeedUpdate = true //The uv map has been modified geometry.normalsNeedUpdate = true //The normal has been modified geometry.colorsNeedUpdate = true //Changes to the vertex color
  • テクスチャ
material.needsUpdate = true

それらが更新されている場合は、trueに設定すると、Three.jsはデータをビデオメモリに再送信し、構成アイテムをfalseに再変更します。これは非常に効率的なプロセスであるため、必要な場合にのみ変更を試み、render()メソッドには入れません。

必要な場合にのみレンダリングする
操作がないときにループを常にレンダリングするのがリソースの浪費である場合は、必要な場合にのみレンダリングするメソッドを紹介します。

最初にループレンダリングに判定を追加します。判定値がtrueの場合、レンダリングをループできます。

texture.needsUpdate = true
  • 次に、遅延関数を設定します。各呼び出しの後に、次のことができますvar renderEnabled function animate() { if (renderEnabled) { renderer.render(scene, camera) } requestAnimationFrame(animate) } animate()次のように設定renderEnabledそして、3秒遅延して設定しますtrueこの遅延時間は、必要に応じて変更できます。
false
  • 次に、必要に応じてこれを呼び出します/ / call once can render three seconds let timeOut = null function timeRender() { / / set to renderable state renderEnabled = true / / Clear the last delay if (timeOut) { clearTimeout(timeOut) } timeOut = setTimeout(function () { renderEnabled = false }, 3000) } このメソッドは、たとえば、カメラコントローラーが更新された後のコールバックに含めることができます。
timeRender()

カメラの位置が変わると、コールバックがトリガーされ、ループレンダリングがオンになり、ページ表示が更新されます。

  • シーンにモデルを追加する場合は、re-renderを呼び出すだけです。
controls.addEventListener('change', function(){ timeRender() })

最後に、重要な問題は、マテリアルのテクスチャが非同期であるということです。画像が追加された後、コールバックをトリガーする必要があります。幸い、Three.jsはこれを考慮に入れています。 Three.js静的オブジェクトTHREE.DefaultLoadingManagerのonLoadコールバックは、各テクスチャ画像がロードされた後にコールバックをトリガーします。これに依存することで、Three.jsのすべてのコンテンツを変更できます。トリガー後の再レンダリングは、アイドル状態でのレンダリングを停止します。

scene.add(mesh) timeRender()