1

メモリリークに関するトピックがたくさんあることは知っていますが、解決策を試しましたが、まだ機能しません。

私はこの例に取り組んでいます

ので、私は持っています

materialPano=new THREE.MeshFaceMaterial( materials );
materialPano.needsUpdate=true;
mesh = new THREE.Mesh( new THREE.CubeGeometry( 400, 400, 400, 7, 7, 7 ), materialPano  );

ボタンをクリックしたときにテクスチャを変更する機能を追加しています。問題は、以前のテクスチャが削除されず、新しいテクスチャごとに使用メモリが増加することです。

したがって、ボタンをクリックすると、次の機能が実行されます。

materials = [loadTexture(myNewTexture1 ), loadTexture( myNewTexture2),loadTexture( myNewTexture3 ),loadTexture( myNewTexture4 ),loadTexture( myNewTexture5), loadTexture( myNewTexture6)];

myNewTexureKボタンで変化する新しい画像ファイルです。そしてメッシュ素材をアップデート。

materialPano.materials=materials;
mesh.material=materialPano;

問題は、以前のテクスチャを削除する方法がわからないことです。私はそのような多くのことを試しました:

for(var k=0;k<materials.length;k++){
    materials[k].deallocate();
    scene.remove(materials[k]);
    renderer.deallocateTexture(materials[k]);
    renderer.deallocateMaterial(materials[k]);
    renderer.deallocateObject(materials[k]);
    delete materials[k];
    materials[k]=null;
}
renderer.deallocateMaterial(materials);
renderer.deallocateObject(materials);
delete materials;
materials=null;

そして、ここで私はmaterials=[loadTexture(newTexture,...)];

そして、私はそのloadTextureような関数を変更しました:

function loadTexture( path ) {

            var texture = new THREE.Texture( texture_placeholder );
            var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: true } );

            var image = new Image();
            image.onload = function () {

                texture.needsUpdate = true;
                material.map.image = this;

                render();
            };

            image.src = path;

            texture.deallocate();//new line
            renderer.deallocateTexture( texture );//new line

            return material;

        }

しかし、それは何も削除しません!そして、例を変更せずに、ページを更新するとメモリも増加することに気付きました。例でメモリリークが発生していますか?

メモリリークを避けるためにテクスチャを本当に削除する方法はありますか?

どうもありがとう!

誰も解決策を持っていませんか?:(メッセージを編集して、より正確になるようにします。

var mesh;

function loadTexture( path ) {

var texture = new THREE.Texture( texture_placeholder );
var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: true } );

var image = new Image();
image.onload = function () {

    texture.needsUpdate = true;
    material.map.image = this;

    render();
};
image.src = path;

texture.deallocate();
renderer.deallocateTexture( texture );

return material;

}

function init(){
 //some initializations, create scene, webgl renderer, ...

 var materiales = [
loadTexture( '1.jpg' ), 
loadTexture( '2.jpg'),
loadTexture( '3.jpg' ),
loadTexture( '4.jpg' ),
loadTexture( '5.jpg'), 
loadTexture( '6.jpg' )
];

mesh = new THREE.Mesh( new THREE.CubeGeometry( 400, 400, 400, 7, 7, 7 ),new THREE.MeshFaceMaterial( materiales ) );
scene.add( mesh );
}

ボタンをクリックすると、次のようになります。

updateTexture(){

 var materiales = [
loadTexture( 'new1.jpg' ), 
loadTexture( 'new2.jpg'),
loadTexture( 'new3.jpg' ),
loadTexture( 'new4.jpg' ),
loadTexture( 'new5.jpg'), 
loadTexture( 'new6.jpg' )
];

 mesh.material=new THREE.MeshFaceMaterial( materiales );
}

問題は、クリックするたびにメモリが増加することです。そのコードだけで、通常、以前の mesh.material を削除するものは何もありません。しかし、私は次のような多くのことを試しました:

mesh.deallocate(mesh.material);
mesh.geometry.deallocate(mesh.material);
scene.deallocate(mesh.material);
renderer.deallocateMaterial(mesh.material);
renderer.deallocateTexture(mesh.material);
renderer.deallocateObject(mesh.material);
scene.remove(mesh.material);

そして、メモリはまだ増加しています。私は Firefox v 17.0.1 で作業していると正確に言います。リークは Chrome でも表示されます。

4

4 に答える 4

0

webglバージョンで問題が解決しました。

追加 :

for(var k=0;k<materialsT.length;k++){
    renderer.deallocateTexture(materialsT[k].map);
    renderer.deallocateTexture(materialsT[k]);
    materialsT[k].deallocate();
    materialsT[k].map.deallocate();
}

マテリアルの直前のchangeTexture関数でT=[loadTexture(...)、...]。、および

texture.deallocate();
renderer.deallocateTexture( texture );

戻る直前のloadTexture関数で。

ただし、キャンバスバージョンにはまだリークがあります。

于 2013-01-11T10:32:22.160 に答える
0

待たせてごめんね。ここでコードをテストできます: http://jodyj.com/test/ キャンバス版と webgl 版があります。ボタンをクリックするだけで、メモリの増加を確認できます (たとえば、プロセス ウィンドウで)。

キャンバス バージョンの場合、メモリ リークは Firefox と Chrome で発生しますが、IE では発生しません。webgl バージョン (IE ではない) では、Firefox と Chrome でメモリ リークが発生します。コードにコメントを付け、どの行がリークを作成するかを示しました (materialPano.materials=materialsT; )。メッシュ、マテリアルの割り当て解除機能でテストしましたが、何も変わりません。

ありがとう!

于 2013-01-10T14:27:00.057 に答える
0

これは私がhttp://mrdoob.github.com/three.js/examples/webgl_panorama_equirectangular.htmlに加えた変更です

http://mrdoob.github.com/three.js/examples/canvas_geometry_panorama.htmlから loadTexture 関数、changeTexture() 関数を実行するボタンを追加しました。

<!DOCTYPE html>

<head>
<title>three.js webgl - equirectangular panorama demo</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<style>
    body {
        background-color: #000000;
        margin: 0px;
        overflow: hidden;
    }

    #info {
        position: absolute;
        top: 0px; width: 100%;
        color: #ffffff;
        padding: 5px;
        font-family:Monospace;
        font-size:13px;
        font-weight: bold;
        text-align:center;
    }

    a {
        color: #ffffff;
    }
</style>
</head>
<body>

<div id="container"></div>
<div id="info"><a href="http://threejs.org" target="_blank">three.js webgl</a> - equirectangular panorama demo. photo by <a href="http://www.flickr.com/photos/jonragnarsson/2294472375/" target="_blank">Jón Ragnarsson</a>.<input id="changeTexture" type="button" value="Memory leak test" onclick="changeTexture();"> </div>

<script src="./build/three.min.js"></script>

<script>

    var idTexture='id1';

    var camera, scene, renderer;

    var fov = 70,
    texture_placeholder,
    isUserInteracting = false,
    onMouseDownMouseX = 0, onMouseDownMouseY = 0,
    lon = 0, onMouseDownLon = 0,
    lat = 0, onMouseDownLat = 0,
    phi = 0, theta = 0;

    var materialsT, materialPano;

    init();
    animate();

    function init() {

        var container, mesh;

        container = document.getElementById( 'container' );

        camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1100 );
        camera.target = new THREE.Vector3( 0, 0, 0 );

        scene = new THREE.Scene();

        renderer = new THREE.WebGLRenderer();
        renderer.setSize( window.innerWidth, window.innerHeight );

        //put here your 6 textures, one per face. Of course, you can use the same texture for all the faces
        materialsT = [
            loadTexture( idTexture+'.jpg' ), 
            loadTexture( idTexture+'.jpg' ),
            loadTexture( idTexture+'.jpg'  ),
            loadTexture(idTexture+'.jpg' ),
            loadTexture( idTexture+'.jpg' ), 
            loadTexture( idTexture+'.jpg' )
        ];

        materialPano=new THREE.MeshFaceMaterial( materialsT );
        mesh = new THREE.Mesh( new THREE.CubeGeometry( 256, 256, 256, 7, 7, 7 ),materialPano );
        mesh.scale.x = -1;
        scene.add( mesh );


        container.appendChild( renderer.domElement );

        document.addEventListener( 'mousedown', onDocumentMouseDown, false );
        document.addEventListener( 'mousemove', onDocumentMouseMove, false );
        document.addEventListener( 'mouseup', onDocumentMouseUp, false );
        document.addEventListener( 'mousewheel', onDocumentMouseWheel, false );
        document.addEventListener( 'DOMMouseScroll', onDocumentMouseWheel, false);

        window.addEventListener( 'resize', onWindowResize, false );

    }

    function loadTexture( path ) {

        var texture = new THREE.Texture( texture_placeholder );
        var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: true } );

        var image = new Image();
        image.onload = function () {

            texture.needsUpdate = true;
            material.map.image = this;

            render();

        };
        image.src = path;

        texture.deallocate();
        renderer.deallocateTexture( texture );

        return material;

    }

    function changeTexture(){

        idCourant=(idTexture=='id1')?'id2':'id1';

        //you can use the same texture, there is still the memory leak
        materialsT = [
            loadTexture( idTexture+'.jpg' ), 
            loadTexture( idTexture+'.jpg'),
            loadTexture( idTexture+'.jpg' ),
            loadTexture( idTexture+'.jpg' ),
            loadTexture( idTexture+'.jpg'), 
            loadTexture( idTexture+'.jpg' )
        ];

        materialPano.materials=materialsT;//without this line, I don't have memory leak but I can't change the texture. So it means that loadTexture doesn't have memory leak since the memory doesn't increase when I click on the button with only materialsT=[loadTexture(...),...] in the changeTexture() function.

        //I try with the following (put before materialPano.materials=materialsT; of course) to deallocate materialPano but it doesn't do anything
        /*
        renderer.deallocateTexture(materialPano.materials);
        renderer.deallocateMaterial(materialPano.materials);
        renderer.deallocateObject(materialPano.materials);

        renderer.deallocateTexture(materialPano);
        renderer.deallocateMaterial(materialPano);
        renderer.deallocateObject(materialPano);
        //*/

    }

    function onWindowResize() {

        camera.aspect = window.innerWidth / window.innerHeight;
        camera.updateProjectionMatrix();

        renderer.setSize( window.innerWidth, window.innerHeight );

    }

    function onDocumentMouseDown( event ) {

        event.preventDefault();

        isUserInteracting = true;

        onPointerDownPointerX = event.clientX;
        onPointerDownPointerY = event.clientY;

        onPointerDownLon = lon;
        onPointerDownLat = lat;

    }

    function onDocumentMouseMove( event ) {

        if ( isUserInteracting ) {

            lon = ( onPointerDownPointerX - event.clientX ) * 0.1 + onPointerDownLon;
            lat = ( event.clientY - onPointerDownPointerY ) * 0.1 + onPointerDownLat;

        }
    }

    function onDocumentMouseUp( event ) {

        isUserInteracting = false;

    }

    function onDocumentMouseWheel( event ) {

        // WebKit

        if ( event.wheelDeltaY ) {

            fov -= event.wheelDeltaY * 0.05;

        // Opera / Explorer 9

        } else if ( event.wheelDelta ) {

            fov -= event.wheelDelta * 0.05;

        // Firefox

        } else if ( event.detail ) {

            fov += event.detail * 1.0;

        }

        camera.projectionMatrix.makePerspective( fov, window.innerWidth / window.innerHeight, 1, 1100 );
        render();

    }

    function animate() {

        requestAnimationFrame( animate );
        render();

    }

    function render() {

        lat = Math.max( - 85, Math.min( 85, lat ) );
        phi = ( 90 - lat ) * Math.PI / 180;
        theta = lon * Math.PI / 180;

        camera.target.x = 500 * Math.sin( phi ) * Math.cos( theta );
        camera.target.y = 500 * Math.cos( phi );
        camera.target.z = 500 * Math.sin( phi ) * Math.sin( theta );

        camera.lookAt( camera.target );

        renderer.render( scene, camera );

    }

</script>
</body>

mesh.material.materials[ i ].map = texture; をどこでどのように使用すればよいかわかりません。texture.needsUpdate = true; あなたが私に言ったように。

ありがとう!

于 2012-12-28T09:01:27.130 に答える