2017-01-19 2 views
0

Этот вопрос может быть странным, но предположим, что у нас есть холст, который, например, рисует некоторый 3D-контент, подобный этому experiment.HTML Canvas Sniff Webgl Data

Не обращайте внимания на использование 3JS, Babylon или любой другой библиотеки для достижения такого же эффекта, можно установить некоторый интервал, который копирует рождение каждого вокселя и повторяет (перерисовывает) его позже.

Просто я хочу записать процесс рисования холста и воспроизвести его, не используя последовательность RTC, видео или изображений.

Что было сделано?

Я пытался с WebGl Context и Stream Capture, но, к сожалению, не удалось достичь желаемого результата.

Может ли кто-нибудь помочь в этом?

+1

Как вы пробовали Stream Capture? Это хорошо работает для меня в данной [примерной ссылке] (http://www.laplace2be.com/lab/PixelParticles/). Скопируйте это в консоль: 'let s = mycanvas.captureStream(), r = new MediaRecorder (s), chunks = []; r.ondataavailable = e => chunks.push (e.data); r.onstop = e => { window.open (URL.createObjectURL (новый Blob (куски))); }; r.start(); setTimeout (_ => r.stop(), 3000); ' – Kaiido

+0

@Kaiido благодарит за ваш комментарий, я сделал это, но этот blob на самом деле является веб-видео, которое на самом деле не является оптимальным решением в моем случае, поскольку размер будет огромным. не могли бы вы добавить это как ответ? – ProllyGeek

ответ

1

Вы можете обернуть контекст WebGL и захватить все вызовы функций. Пример упаковки контекста WebGL будет что-то вроде

const rawgl = document.querySelector("canvas").getContext("webgl"); 
 
const gl = wrapContext(rawgl); 
 

 
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); 
 
gl.enable(gl.SCISSOR_TEST); 
 
gl.scissor(40, 50, 200, 60); 
 
gl.clearColor(0,1,1,1); 
 
gl.clear(gl.COLOR_BUFFER_BIT); 
 
gl.scissor(60, 40, 70, 90); 
 
gl.clearColor(1,0,1,1); 
 
gl.clear(gl.COLOR_BUFFER_BIT); 
 

 
function wrapContext(gl) { 
 
    const wrapper = {}; 
 
    for (let name in gl) { 
 
    var prop = gl[name]; 
 
    if (typeof(prop) === 'function') { 
 
     wrapper[name] = wrapFunction(gl, name, prop); 
 
    } else { 
 
     wrapProperty(wrapper, gl, name); 
 
    } 
 
    } 
 
    return wrapper; 
 
} 
 

 
function wrapFunction(gl, name, origFn) { 
 
    // return a function that logs the call and then calls the original func 
 
    return function(...args) { 
 
    log(`gl.${name}(${[...args].join(", ")});`); 
 
    origFn.apply(gl, arguments); 
 
    }; 
 
} 
 

 
function wrapProperty(wrapper, gl, name) { 
 
    // make a getter because these values are dynamic 
 
    Object.defineProperty(wrapper, name, { 
 
    enumerable: true, 
 
    get: function() { 
 
     return gl[name]; 
 
    }, 
 
    }); 
 
} 
 

 
function log(...args) { 
 
    const elem = document.createElement("pre"); 
 
    elem.textContent = [...args].join(" "); 
 
    document.body.appendChild(elem); 
 
}
canvas { border: 1px solid black; } 
 
pre { margin: 0; }
<canvas></canvas>

В вашем случае вместо регистрации вызовов нужно добавить их в какой-то массив звонков только на кадры, которые вы хотите захвачены.

Затем вам нужно каким-то образом отслеживать все ресурсы (буфера, текстуры фреймбуферов, renderbuffers, шейдеры, программа) и все их параметры (например, настройка фильтрации на текстурах), и вы также должны отслеживать единые настройки и т.д.

WebGL-Inspector делает это и может воспроизводить фреймы, поэтому это может быть хорошим примером. Также есть библиотека webgl-capture.

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

+0

как вы создаете полосу прокрутки в вашем ответе? – J3STER

+0

Что это значит? [Он прокручивает меня] (http://imgur.com/a/qkhY1). Если это не прокрутка для вас, я предлагаю вам [указать ошибку] ​​(http://meta.stackoverflow.com). В противном случае любой блок кода, в котором я больше 40 строк, автоматически получает полосу прокрутки – gman

+0

Спасибо за вашу помощь @gman, ваш ответ заставил меня найти много вещей, которые я раньше не понимал. – ProllyGeek

1

Я не знаю, как вы это пробовали с помощью метода captureStream, но на вашей странице примера этот код действительно работает.

let s = mycanvas.captureStream(), 
r = new MediaRecorder(s), 
chunks = []; 
r.ondataavailable = e => chunks.push(e.data); 
r.onstop = e => { 
    let videoURL = URL.createObjectURL(new Blob(chunks)); 
    doSomethingWith(videoURL); 
    }; 
r.start(); 
setTimeout(_=>r.stop(), 3000); // records 3 seconds 

Теперь, когда вы получили правильный blobURL, указывающие на ваш холст записи, вы можете играть в <video> элемент, а затем draw it in your webgl context.

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