2014-01-05 131 views
5

我們有一個應用程序,它使用THREE.js渲染身體網格的3D圖像。我們有一個名爲MeshViewer的對象,它封裝了渲染功能;在初始化方法中,我們設置了THREE.js webGL垃圾收集

this.renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true }) 

我們寫了一個腳本來測試this.renderer沒有被釋放。

<script> 
    var count = 0; 
    function loop() { 
     if (count >= 25) { 
      return; 
     } 
     else { 
      count++; 
      var viewer = new MeshViewer(
       'mesh_viewer', 
       's3_assets/textured_mean_scape_female.obj', 
       [] 
      ); 

      viewer.cleanup(); 

      setTimeout(function() { 
       loop(); 
      }, 500); 
     } 
    } 
    loop(); 
</script> 

在這種情況下,「mesh_viewer」是我們要嵌入瀏覽器中的DOM元素的ID。我們的清理方法設置

this.renderer = null 

清理工作,在這個意義上,如果我們不不執行清理,我們得到一個錯誤,即存在太多活動的WebGL上下文,而且我們不能再創建,如果我們清理乾淨,就不會出現這種錯誤。

我的問題是,爲什麼在setTimeout循環之前調用viewer.cleanup時會失敗,並且在setTimeout之前和之後調用cleanup時會通過? (這可能是一個超過THREE.js/WebGL問題的JavaScript問題。)

+2

爲什麼這個問題被低估? – yangmillstheory

+0

是否有任何控制檯錯誤? –

+0

也許傳遞給'setTimeout'的函數捕獲查看器及其所有屬性,包括渲染器,這意味着渲染器的引用計數永遠不會變爲0,因此不會被垃圾收集? –

回答

0

這可能與the way a browser executes javascript and other stuff in a single thread有關。

如果您在setTimeout之前放置viewer.cleanup();,瀏覽器的內部函數或THREE防護函數在調用loop();之前會抽出時間實際釋放渲染器。

其他viewer.cleanup();loop()將連續調用,沒有時間在其間發生任何事情。

注:我沒有做任何測試,以確認


另外一個建議:也許你應該把你的THREE.WebGLRenderer實例爲單例重用而不是釋放它的。