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