2017-02-02 2 views
0

編集; codepen作業threejs getImageDataビデオパフォーマンス

まだ(私は優秀なリュットを変更しようとしています

https://codepen.io/bw1984/pen/pezOXm


は、ビデオのために働くためにここにhttps://airtightinteractive.com/demos/js/ruttetra/例をETRA(クロス元ポリシーを回避するために、ビデオファイルを提供する必要があります) threejsを使用して)、パフォーマンスに奇妙な問題が発生しています。

私のコードは現在期待どおりに動作していますが、実際にはMacBook ProのChromeで非常にスムーズに動作しますが、何らかの遅いメモリリークが発生するようですgetImageDataによって。奇妙なことに、タブをリフレッシュしようとすると唯一目立つように見えるので、おそらくクロムのガベージコレクションに関係するように見えるだろうか?とにかくCPUを殺すのではなく、GPUにむちゃくちゃの仕事をシャントしますか?

私は、コード最適化の点で明らかなものがないか、私が直面しているパフォーマンスの問題が、私がやろうとしていることの性質を考えれば期待されているのかどうか疑問に思っただけです。

私はWebGL/chromeの機能に興味がありますので、ブラウザの互換性について心配する必要はありません。

<script> 

var container, camera, scene, renderer, controls; 

// PI 
var PI = Math.PI; 
var TWO_PI = PI*2; 

// size 

SCREEN_WIDTH = window.innerWidth; 
SCREEN_HEIGHT = window.innerHeight; 
SCREEN_PIXEL_RATIO = window.devicePixelRatio; 

// camera 

var VIEW_ANGLE = 45; 
var ASPECT = SCREEN_WIDTH/SCREEN_HEIGHT; 
var NEAR = 0.1; 
var FAR = 20000000; 



// video raster 

var video; 
var videoImage; 
var videoImageContext; 

var _imageHeight; 
var _imageWidth; 


// lines 

var _lineGroup; 


// gui 

var _guiOptions = { 
    stageSize:  1, 
    scale:   1.0, 
    scanStep:  5, 
    lineThickness: 10.0, 
    opacity:  1.0, 
    depth:   50, 
    autoRotate:  false 
}; 


// triggered from audio.php getMediaStream 

function runme() 
{ 
    console.log('runme running'); 

    init(); 
    animate(); 
} 

runme(); 


function init() 
{ 
    container = document.createElement('div'); 
    document.body.appendChild(container); 

    //---------- 
    // scene 
    //---------- 

     scene = new THREE.Scene(); 


    //---------- 
    // camera 
    //---------- 

     camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR); 

     //camera.position.set(0,0,450); 

     camera.position.set(0,150,300); 


    //---------- 
    // objects 
    //---------- 

     // create the video element 
     video = document.createElement('video'); 
     // video.id = 'video'; 
     // video.type = ' video/ogg; codecs="theora, vorbis" '; 
     video.src = 'data/sintel.ogv'; 
     //video.src = 'data/az.mp4'; 

     video.load(); // must call after setting/changing source 
     video.play(); 

     videoImage = document.createElement('canvas'); 
     //videoImage.width = 480; 
     //videoImage.height = 204; 

     videoImageContext = videoImage.getContext('2d'); 

     _imageWidth = videoImage.width; 
     _imageHeight = videoImage.height; 

     //videoImageContext.fillStyle = '#ffffff'; 
     //videoImageContext.fillRect(0, 0, videoImage.width, videoImage.height); 



    //---------- 
    // controls 
    //---------- 

     controls = new THREE.OrbitControls(camera); 


    //---------- 
    // events 
    //---------- 

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


    //---------- 
    // render 
    //---------- 

     var args = { 
      //antialias: true // too slow 
     } 

     renderer = new THREE.WebGLRenderer(args); 

     renderer.setClearColor(0x000000, 1); 
     renderer.setPixelRatio(SCREEN_PIXEL_RATIO); //Set pixel aspect ratio 
     renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT); 

     // attach to dom 
     container.appendChild(renderer.domElement); 

     //render(); 
} 


function render() 
{ 

    if(video.readyState === video.HAVE_ENOUGH_DATA && !video.paused && !video.ended) // and video.currentTime > 0 
    { 
     //_imageWidth = videoImage.width; 
     //_imageHeight = videoImage.height; 

     videoImageContext.drawImage(video,0,0,_imageWidth,_imageHeight); 


     // Grab the pixel data from the backing canvas 
     var _data = videoImageContext.getImageData(0,0,videoImage.width,videoImage.height).data; 

     //log(data); 

     //_pixels = data; 

     var x = 0, y = 0; 

     if(_lineGroup) 
     { 
      scene.remove(_lineGroup); 
      //_lineGroup = null; 
     } 

     _lineGroup = new THREE.Object3D(); 


     var _material = new THREE.LineBasicMaterial({ 
      color: 0xffffff, 
      linewidth: _guiOptions.lineThickness 
     }); 


     // loop through the image pixels 

     for(y = 0; y < _imageHeight; y+= _guiOptions.scanStep) 
     { 

      var _geometry = new THREE.Geometry(); 

      for(x=0; x<_imageWidth; x+=_guiOptions.scanStep) 
      { 
       var color = new THREE.Color(getColor(x, y, _data)); 

       var brightness = getBrightness(color); 

       var posn = new THREE.Vector3(x -_imageWidth/2,y - _imageHeight/2, -brightness * _guiOptions.depth + _guiOptions.depth/2); 

       //_geometry.vertices.push(new THREE.Vertex(posn)); 
       _geometry.vertices.push(posn); 

       _geometry.colors.push(color); 

       _color = null; 
       _brightness = null; 
       _posn = null; 
      } 

      // add a line 
      var _line = new THREE.Line(_geometry, _material); 

      //log(line); 

      _lineGroup.add(_line); 

      // gc 
      _geometry = null; 
     } 

     scene.add(_lineGroup); 

     _data = null; 
     _line = null; 

    } 

    renderer.render(scene,camera); 
} 


function animate(){ 

    requestAnimationFrame(animate); 

    stats.update(); 

    render(); 
} 


function onWindowResize(){ 

    camera.aspect = window.innerWidth/window.innerHeight; 
    camera.updateProjectionMatrix(); 
    renderer.setSize(window.innerWidth, window.innerHeight); 
    render(); 
} 



// Returns a hexadecimal color for a given pixel in the pixel array. 

function getColor(x, y, _pixels) 
{ 
    var base = (Math.floor(y) * _imageWidth + Math.floor(x)) * 4; 

    var c = { 
     r: _pixels[base + 0], 
     g: _pixels[base + 1], 
     b: _pixels[base + 2], 
     a: _pixels[base + 3] 
    }; 
    return (c.r << 16) + (c.g << 8) + c.b; 
} 



// return pixel brightness between 0 and 1 based on human perceptual bias 

function getBrightness(c) 
{ 
    return (0.34 * c.r + 0.5 * c.g + 0.16 * c.b); 
} 

</script> 

誰もが提供できるすべてのヘルプは非常に私はちょうどこのようなものを試して始めていますし、ほとんど自分自身に私の小さなをラップしようとして動脈瘤を与えているように、そのだけで正しい方向に私を指していても、高く評価されるだろうその周りの心。

+0

また、現状のコードではクロムがクラッシュする可能性があることにご注意ください。 – bw1984

+0

私はそれが何をすべきかを完全に理解していないが、新しいTHREE.Line'私はtheresが原因だと思った。ここで何をしていても、キャッシュする必要があります。ジオメトリが構築されている(四角形の線)か、各フレームを配置できる線のプールが必要です。レンダリングループでは、これは、これらのノードのそれぞれに多数のデータがあり、そのデータが多くの場合オブジェクト(ベクトルと行列)の形を取っているため、これがメモリを強調していると思います。 – pailhead

+0

全体として、ビデオを読み込んでCPU上でこれを行う必要はありません。ちょうどテクスチャとして読み込んでシェイダー – pailhead

答えて

0

低速メモリリークが起因する可能性が最も高い。

 // add a line 
     var _line = new THREE.Line(_geometry, _material); 

     //log(line); 

     _lineGroup.add(_line); 

THREE.Line他のオブジェクトと大量のデータを含むオブジェクトです。インスタンス化するたびに、.matrix.matrixWorld.modelViewMatrix.normalMatrixが作成され、すべての配列が数字の束になっています。 .position,,.rotationおよびおそらく.upは、ベクター、クワットなどであり、わずかに小さいが、特別なコンストラクタを備えた配列でもある。

このすべてを16ミリ秒ごとに割り当てて、次のフレームだけをリリースすることが、おそらくあなたの「リーク」の原因です。

THREE.Lineオブジェクトのプールを作成し、その代わりにすべてのフレームを描画する必要があります。 .visibleで制御できる描画オブジェクトの数とその変形プロパティを変更します。

0

@pailhead事前にラインとライングループをあらかじめレンダリングしておき、代わりに各アニメーションフレームの頂点を更新して、子猫のように取り除くことをアドバイスしました。更新されたコードが確実にピックアップされるように、次の行を挿入する必要もあります。

e.geometry.verticesNeedUpdate = true; 

私は、ホストされたビデオはcodepen(クロスオリジンポリシー違反の問題)上で動作するように取得する方法を見つけ出すカントが、私は、作業コードを表示するまでとにかくバージョンを入れています。

https://codepen.io/bw1984/pen/pezOXm

私はすぐに私は

私は色の作業を取得するために無駄にしようとしてきたことができ、それがなければならないだろうとして、自己ホスト型(作業)バージョンアップを取得しようとします別の日の運動。