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()