About the memory leak when dispose the texture

I create a mesh which is consist of PlaneGeometry using MeshBasicMaterial.
And then, I changed the map of the material to an image.
On mouse :create a texture from the image and put it to the material’s map
Over mouse:dispose the texture and set the material’s map to undefined.
It seems work well, but there is a problem that the memory is increasing all the time.
How can I reset the the material’s map in a right way?

Can you please demonstrate the leak with a live example? If you correctly dispose the texture, it requires debugging to find the bottleneck.

<!DOCTYPE html>
<html>
<head>
    <title>Example 04.01 - MeshBasicMaterial</title>
    <script type="text/javascript" src="../libs/three_r89.js"></script>
    <script type="text/javascript" src="../libs/CanvasRenderer.js"></script>
    <script type="text/javascript" src="../libs/Projector.js"></script>
    <style>
        body {
            /* set margin to 0 and overflow to hidden, to go fullscreen */
            margin: 0;
            overflow: hidden;
        }
    </style>
</head>
<body>

<div id="Stats-output">
</div>

<div id="WebGL-output">
</div>

<script type="text/javascript">
    var scene = new THREE.Scene();
    var objectNum = 20;
    var sphereY = -30;
    var cubeY = -20;
    var meshMaterial1 = new THREE.MeshBasicMaterial({color: 0x7777ff});
    var meshMaterial2 = new THREE.MeshBasicMaterial({color: 0x9933cc});
    var meshMaterial3 = new THREE.MeshBasicMaterial({color: 0x99ff33});
    var meshMaterial4 = new THREE.MeshBasicMaterial({color: 0x000000});
    var meshMaterial5 = new THREE.MeshBasicMaterial({color: 0xff0000});
    var materialList = [meshMaterial1, meshMaterial2, meshMaterial3, meshMaterial4, meshMaterial5];
    var materialCount = 0;

    function init() {
        var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
        var renderer;
        var webGLRenderer = new THREE.WebGLRenderer();
        webGLRenderer.setClearColor(new THREE.Color(0xEEEEEE, 1.0));
        webGLRenderer.setSize(window.innerWidth, window.innerHeight);
        webGLRenderer.shadowMapEnabled = true;

        var canvasRenderer = new THREE.CanvasRenderer();
        canvasRenderer.setSize(window.innerWidth, window.innerHeight);
        renderer = webGLRenderer;

        addObjectToScene();

        camera.position.x = -20;
        camera.position.y = 50;
        camera.position.z = 40;
        camera.lookAt(new THREE.Vector3(10, 0, 0));

        var ambientLight = new THREE.AmbientLight(0x0c0c0c);
        scene.add(ambientLight);

        var spotLight = new THREE.SpotLight(0xffffff);
        spotLight.position.set(-40, 60, -10);
        spotLight.castShadow = true;
        scene.add(spotLight);

        document.getElementById("WebGL-output").appendChild(renderer.domElement);
        render();
        function render() {
            requestAnimationFrame(render);
            renderer.render(scene, camera);
        }   
    }

    function removeObjectFromScene(){

        for(var index =scene.children.length -1;index>0;index--) {
            var removeTarget = scene.children[index];
            if (removeTarget instanceof THREE.Mesh) {
                scene.remove(removeTarget);            
                removeTarget.geometry.dispose();
                removeTarget.material.dispose();
            }
        }
    }

    function addObjectToScene(){
        var meshMaterial = materialList[materialCount%5];
        materialCount++;
        for(var index=0;index<objectNum;index++){
            var sphereGeometry = new THREE.SphereGeometry(3, 20, 20);
            var sphere = new THREE.Mesh(sphereGeometry, meshMaterial);
            sphere.position.x = 0 + index * 10;
            sphere.position.y = sphereY;
            sphere.position.z = -30;
            scene.add(sphere);

            var cubeGeometry = new THREE.BoxGeometry(3, 3, 3);
            var cube = new THREE.Mesh(cubeGeometry, meshMaterial);
            cube.position.x = 0 + index * 10;
            cube.position.y = cubeY;
            cube.position.z = 0;
            scene.add(cube);
        }

    }
    function resetScene() {
        console.log(String(new Date()) + " resetScene.");
        removeObjectFromScene();
        addObjectToScene();
    }
    setInterval(resetScene, 5000);
    window.onload = init;
</script>
</body>
</html>

I created a sample,just like above. 20 spheres and cubes are created every three mins.My question is when I execute this sample 12 hours, it seems that there is a memory leak.Is there any problem in the 「removeObjectFromScene」method?

sorry, I forgot to put the example into Preformatted text area.

You example code does not work with textures. I though you original performance problem is related to textures?

Anyway, your code is now similar to https://threejs.org/examples/#webgl_test_memory. I was not able to monitor a memory leak in this case.

BTW: Here is your sample as a fiddle: https://jsfiddle.net/f2Lommf5/6961/

Thank you for replying.

Sorry for not explaining the reason why I separated the example which was mentioned above from textures program. That is I demonstrated that there is no problem with textures.

And I shorten the changing time from every three mins to every three seconds , and then execute it one day to see if any thing will happen.

According to [webgl_test_memory], there is no problem in the [removeObjectFromScene] method, so I think the memory leak is still in my program.

I will finish this question if nothing happened.:sweat_smile:

1 Like