2017-02-02 14 views
0

Редактировать;threejs getImageData видео производительность

работает codepen (необходимо предоставить видео файл, чтобы избежать перекрестного происхождения политики)

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


Я пытаюсь изменить отличный Rutt ETRA примера здесь https://airtightinteractive.com/demos/js/ruttetra/ работать для видео (до сих пор используя три js), и я сталкиваюсь с некоторыми проблемами с производительностью.

Мой код в настоящее время работает, как ожидается, и на самом деле работает довольно гладко на chrome на моем macbook pro, но, похоже, вызывает некоторую медленную утечку памяти, которую я предполагаю сделать со всем тяжелым подъемом, который нужно сделать по getImageData. Как ни странно, его единственный заметный раз, когда я пытаюсь обновить вкладку, похоже, что это может быть связано с сборкой мусора в хроме, может быть? во всяком случае, чтобы шунтировать работу ворчания на GPU вместо того, чтобы убивать CPU?

Мне просто интересно, не хватает ли я чего-либо очевидного с точки зрения оптимизации кода или если проблемы производительности, с которыми я сталкиваюсь, следует ожидать, учитывая природу того, что я пытаюсь сделать.

Меня интересует только функциональность 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' я думал, что это преступник. Что бы вы ни делали здесь, вы должны кэшировать, вы должны либо иметь построенную геометрию (строки в прямоугольнике), либо иметь пул строк, которые вы можете расположить каждый кадр. В цикле рендеринга я считаю, что это подчеркивает память, поскольку каждый из этих узлов имеет кучу данных и что данные часто также находятся в формах объектов (в основном векторы и матрицы). – pailhead

+0

в целом, вам не нужно читать видео и делать это на процессоре, просто прочитайте его как текстуру и сделайте это в шейдере – pailhead

ответ

0

Медленная утечка памяти, скорее всего, из-за:

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

     //log(line); 

     _lineGroup.add(_line); 

THREE.Line является объектом, содержащий другие объекты и много данных. Каждый раз, когда вы его создаете, создается .matrix, .matrixWorld, .modelViewMatrix, .normalMatrix, которые являются массивами с множеством цифр. .position, .quaternion, .scale, .rotation и, возможно, .up являются векторами, quats и т. Д. И немного меньше, но также массивы со специальными конструкторами.

Выделяя все это каждые 16 миллисекунд только для выпуска следующего кадра, вероятно, является причиной вашей «утечки».

Вы должны создать пул из THREE.Line объектов и нарисовать их каждый раз. Количество выведенных объектов, которые вы можете контролировать с помощью .visible и мутировать их свойства преобразования.

0

@pailhead Я принял ваш совет о предварительном рендеринге линий и lineGroup заранее, а затем обновил вершины на каждом кадре анимации, а теперь его мурлыканье, как котенок. Также необходимо вставить следующую строку, чтобы убедиться, что обновлены координаты;

e.geometry.verticesNeedUpdate = true; 

Я не могу понять, как получить размещаемые видео для работы по codepen (вопросы нарушения политики перекрестного происхождения), но я поставил версию в любом случае, чтобы показать рабочий код.

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

Я попытаюсь получить самопринятый (рабочую) версию, как только я могу

Я тщетно пытался получить цвет работу, но это должно быть упражнение на другой день.

 Смежные вопросы

  • Нет связанных вопросов^_^