How-to-dispose-of-objects.html 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <!DOCTYPE html>
  2. <html lang="ja">
  3. <head>
  4. <meta charset="utf-8">
  5. <base href="../../../" />
  6. <script src="page.js"></script>
  7. <link type="text/css" rel="stylesheet" href="page.css" />
  8. </head>
  9. <body>
  10. <h1>[name]</h1>
  11. <p>
  12. アプリケーションのパフォーマンスを向上させ、メモリリークを回避するための重要なこととして、
  13. 未使用のライブラリエンティティの廃棄が挙げられます。
  14. three.js型のインスタンスを作成すると、決まった量のメモリが割り当てられます。
  15. しかし、*three.js*はジオメトリやマテリアルのような特定のオブジェクトのために、レンダリングに必要なバッファやshaderといったWebGL関連のエンティティを作成します。これらのオブジェクトは自動的に解放されるわけではありません。
  16. その代わり、アプリケーションはこのようなリソースを解放するために特別なAPIを使用する必要があります。
  17. このガイドでは、このAPIがどのように使用されるのか、また、このコンテキストではどのようなオブジェクトが関連しているのかについて簡単に説明します。
  18. </p>
  19. <h2>Geometries</h2>
  20. <p>
  21. ジオメトリは普通は、属性の集合として定義された頂点の情報を表します。
  22. *three.js*は、内部にはそれぞれの属性に対して、[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLBuffer WebGLBuffer]型のオブジェクトを作成します。
  23. これらのentityは[page:BufferGeometry.dispose]()が呼ばれた時にのみ削除されます。
  24. もしアプリケーションの中で、あるジオメトリが使われなくなった場合は、関連したリソースを開放するためにこの方法を実行してください。
  25. </p>
  26. <h2>Materials</h2>
  27. <p>
  28. マテリアルは、オブジェクトをどのように描画するかを定義します。
  29. *three.js*はマテリアルの定義情報をレンダリング用のシェーダプログラムを構築するために使います。
  30. シェーダプログラムは対応するマテリアルを捨てることでのみ、削除することができます。
  31. パフォーマンスのために、*three.js*は可能であればすでに存在するシェーダプログラムを再利用しようとします。
  32. そのため、シェーダプログラムは、関連したマテリアルがすべて廃棄された場合のみ削除されます。
  33. [page:Material.dispose]()を実行することで、マテリアルの削除を指示できます。
  34. </p>
  35. <h2>Textures</h2>
  36. <p>
  37. マテリアルの廃棄をしても、テクスチャには影響がありません。
  38. 一つのテクスチャが複数のマテリアルに同時に使用されることがあるので、
  39. テクスチャとマテリアルは別々に制御されています。
  40. テクスチャのインスタンスを作成すると、three.jsは内部に[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLTexture WebGLTexture]を作成します。
  41. バッファと同様に、このオブジェクトは[page:Texture.dispose]()を呼ぶことでしか削除できません。
  42. </p>
  43. <p>
  44. If you use an *ImageBitmap* as the texture's data source, you have to call [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap/close ImageBitmap.close]() at the application level to dispose of all CPU-side resources.
  45. An automated call of *ImageBitmap.close()* in [page:Texture.dispose]() is not possible, since the image bitmap becomes unusable, and the engine has no way of knowing if the image bitmap is used elsewhere.
  46. </p>
  47. <h2>Render Targets</h2>
  48. <p>
  49. [page:WebGLRenderTarget]型のオブジェクトは、描画先をカスタム出来るように、
  50. [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLTexture WebGLTexture]インスタンスだけでなく、[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLFramebuffer WebGLFramebuffer]と
  51. [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderbuffer WebGLRenderbuffer]も確保します。
  52. これらのオブジェクトは[page:WebGLRenderTarget.dispose]()を実行することで、解放されます。
  53. </p>
  54. <h2>Miscellaneous</h2>
  55. <p>
  56. exampleディレクトリには、コントロールや後処理用のパスクラスといったクラスがあります。
  57. これらのクラスは内部のイベントリスナーや描画対象を取り除くための*dispose()*メソッドを提供します。
  58. 一般的には、APIやクラスのドキュメントで*dispose()*があるかどうか探すのがおすすめです。
  59. *dispose()*メソッドが存在するなら、片付けの際に使うとよいでしょう。
  60. </p>
  61. <h2>FAQ</h2>
  62. <h3>なぜthree.jsは自動的にオブジェクトを処分できないのですか?</h3>
  63. <p>
  64. この質問はコミュニティで何度も訊かれた質問なので、この問題についてはきちんと解説します。
  65. 実のところ、*three.js*はライフタイムや、ユーザが作成したジオメトリやマテリアルのようなエンティティのスコープの情報をもっていません。これはアプリケーション側に責任があります。例えば、マテリアルが今のところレンダリングのために使用されていなくとも、次のフレームでは必要になるかもしれません。そのため、アプリケーションが特定のオブジェクトを削除しても良いと判断した場合、対応する*dispose()*メソッドを呼ぶことで描画エンジンに対してそのことを知らせなくてはなりません。
  66. </p>
  67. <h3>シーンからmeshを取り除くとそのジオメトリとマテリアルも削除されますか?</h3>
  68. <p>
  69. いいえ。ジオメトリとマテリアルは*dispose()*で明示的に削除する必要があります。
  70. メッシュのような3Dオブジェクト間でジオメトリとマテリアルは共有できることを覚えておいてください。
  71. </p>
  72. <h3>*three.js*でキャッシュされたオブジェクトの量について情報を知ることができますか?</h3>
  73. <p>
  74. はい。グラフィックボードのメモリとレンダリングプロセスの一連の統計情報で
  75. レンダラの特別なプロパティである[page:WebGLRenderer.info]を評価することができます。
  76. また、ほかにはテクスチャやジオメトリ、シェーダプログラムがどれくらい内部に保存されているかを知ることができます。
  77. もし、アプリケーションにパフォーマンス上の問題があることに気づいた場合、簡単にメモリリークを見つけるために
  78. このプロパティを調べてみることをおすすめします。
  79. </p>
  80. <h3>画像がまだロードされていない時に、テクスチャの*dispose()*を呼び出すとどうなりますか?</h3>
  81. <p>
  82. テクスチャの内部リソースは、イメージが完全に読み込まれた場合にのみ割り当てられます。
  83. 画像が読み込まれる前にテクスチャを破棄しても何も起こりません。
  84. リソースが割り当てられていないので、クリーンアップの必要もありません。
  85. </p>
  86. <h3>dispose()を呼び出した後に、対象のオブジェクトを使用すると何が起きますか?</h3>
  87. <p>
  88. 削除された内部のリソースは、エンジンによって再び作成されます。
  89. そのため、ランタイムエラーは発生しませんが、シェーダプログラムのコンパイルが必要な場合には特に
  90. 現在のフレームでのパフォーマンスの低下が発生するかもしれません。
  91. </p>
  92. <h3>*three.js*のオブジェクトをどのように管理するべきでしょうか?いつオブジェクトを削除するべきでしょうか?</h3>
  93. <p>
  94. この問いに対する明確で一般的な答えはありません。いつ*dispose()*を呼ぶのが正しいのかは、ユースケースに大きく依存します。常にオブジェクトを削除する必要があるわけではないことは強調しておきます。そのよい例として、複数のレベルで構成されているゲームがあります。こういったアプリの場合、オブジェクトを削除するのに適しているのはレベルを切り替えるときです。
  95. そうすることで、古いシーンを通じてオブジェクトに対して処理を適用し、古いマテリアルやジオメトリ、テクスチャを削除できます。前の章で言及したように、まだ使用中のオブジェクトを削除してもランタイムエラーは発生しません。最悪でも1フレーム分のパフォーマンス低下が発生するだけです。
  96. </p>
  97. <h2>Examples that demonstrate the usage of dispose()</h2>
  98. <p>
  99. [example:webgl_test_memory WebGL / test / memory]<br />
  100. [example:webgl_test_memory2 WebGL / test / memory2]<br />
  101. </p>
  102. </body>
  103. </html>