Three.JS 添加删除 THREE.Geometry 到场景时 VRAM 内存泄漏

Three.JS VRAM memory leak when adding removing THREE.Geometry to scene

我在我的应用程序中遇到了 VRAM 内存泄漏。 该应用程序经常添加和删除 THREE.Geometry 以创建体积动画。 如果我使用 THREE.SphereBufferGeometry 代替具有自己填充顶点的 THREE.Geometry,则不会发生内存泄漏。

我已经创建了一个最小的应用程序来证明这个内存泄漏是真实的。 内存泄漏非常缓慢地增加 VRAM 内存,但它最终会填满。 我认为池不会有帮助,因为它是 VRAM 而不是托管内存。 我确实使用处置。

如果你能让这个示例正常工作并且没有内存泄漏,那可能会解决我的问题:

https://jsfiddle.net/4a7ksryd/16/

编辑:我在这里添加应用程序的代码:

var camera, scene, renderer;
var geometry, material, mesh;
var lastSphere;
var lastGeo;

init();
animate();

function init() {

    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
    camera.position.z = 1;

    scene = new THREE.Scene();


    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap; // default THREE.PCFShadowMap

    var light = new THREE.DirectionalLight( 0xffffff, 1, 100 );
light.position.set( 0, 4, 0 );          //default; light shining from top
light.castShadow = true;            // default false
//Set up shadow properties for the light
light.shadow.mapSize.width = 1024;  // default
light.shadow.mapSize.height = 1024; // default
light.shadow.camera.near = 1;    // default
light.shadow.camera.far = 20;     // default

scene.add( light );


    //Create a sphere that cast shadows (but does not receive them)

geometry = new THREE.SphereBufferGeometry( 0.1, 32, 32 );
material = new THREE.MeshStandardMaterial( { color: 0xff0000 } );
//    geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
//    material = new THREE.MeshNormalMaterial();

    mesh = new THREE.Mesh( geometry, material );
    mesh.position.y = 0.1;
    mesh.castShadows = true;
    mesh.receiveShadow = false;
    scene.add( mesh );

    var planeGeometry = new THREE.PlaneBufferGeometry( 15, 15, 1, 1 );
var planeMaterial = new THREE.MeshStandardMaterial( { color: 0xffffff, emissive:0x111111 } )
var plane = new THREE.Mesh( planeGeometry, planeMaterial );
plane.position.y = -0.2;
plane.rotation.x = -Math.PI / 2;
plane.receiveShadow = true;
scene.add( plane );


    document.body.appendChild( renderer.domElement );

}

function animate() {

    requestAnimationFrame( animate );

    mesh.rotation.x += 0.01;
    mesh.rotation.y += 0.02;

        var dim = 32;
        var geo1 = new THREE.Geometry();
    const numVertices = dim*dim;
    var vertices = new Array(numVertices);
    for (var i=0; i<vertices.length; i++)
    {
        const x = i%dim;
        const y = (Math.floor(i/dim))%dim;    
      vertices[i] = new THREE.Vector3(x*0.1, y*0.1, 0);
    }
    const numFaces = (dim-1)*(dim-1)*2;
    var faces = new Array(numFaces);

    for (var i=0; i<(faces.length/2); i++)
    {
        const x = i%(dim-1);
        const y = Math.floor(i/(dim-1))%(dim-1);
        faces[2*i] = new THREE.Face3(x+y*dim, x+1+y*dim, x+(y+1)*dim);
        faces[2*i+1] = new THREE.Face3(x+1+y*dim, x+1+(y+1)*dim, x+(y+1)*dim);
    }
    var uv = new Array(numFaces);
    for (var i=0; i<uv.length; i++)    
        uv[i] = [new THREE.Vector2(0, 0), new THREE.Vector2(0, 0), new THREE.Vector2(0, 0)];
    geo1.faces = faces;
    geo1.vertices = vertices;
    geo1.faceVertexUvs[0] = uv;
        geo1.uvsNeedUpdate = true;
        geo1.verticesNeedUpdate = true;
        geo1.elementsNeedUpdate = true;
//    var sphereGeometry = new THREE.SphereBufferGeometry( 0.1, 256, 256 );
    var sphereGeometry = geo1;
    var sphereMaterial = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
    var sphere = new THREE.Mesh( sphereGeometry, sphereMaterial );
    sphere.position.y = 0.1+Math.sin(mesh.rotation.x)*0.1;
    sphere.position.x = 0.5;
    sphere.castShadow = true; //default is false
    sphere.receiveShadow = false; //default
    if (lastGeo!=null)
        lastGeo.dispose();
    if (lastSphere!=null)
        scene.remove(lastSphere);
    scene.add( sphere );
    lastSphere = sphere;
    lastGeo = sphereGeometry;
//    geo1.dispose();

    renderer.render( scene, camera );

}

这实际上是 three.js 中的错误。我已经提交了 PR 来解决这个问题:

https://github.com/mrdoob/three.js/pull/20479