2016-10-24 3 views
0

Я получаю Uint8Array с RGBA значениями, а также некоторые сведения о том, какая часть изображения была обновлена. Каков самый быстрый способ вернуть эту необработанную информацию растрового изображения на холст? Я использую 2D контекст рендеринга вручную цикл, хотя массив и установить информацию пикселей, но это невероятно медленно:Самый быстрый способ визуализации Uint8Array на холст

let imageData = new ImageData(1920, 1080); 
for (var i=0;i < args.frameBuffer.length; i+=4) { 
    imageData.data[i] = args.frameBuffer[i]; 
    imageData.data[i+1] = args.frameBuffer[i+1]; 
    imageData.data[i+2] = args.frameBuffer[i+2]; 
    imageData.data[i+3] = args.frameBuffer[i+3]; 
} 
context.putImageData(imageData, 0, 0, args.dirtyX, args.dirtyY, args.dirtyWidth, args.dirtyHeight); 

Что бы более эффективный способ сделать это? Будет ли WebGL более реалистичным, чем 2D-контекст? Родной или через что-то вроде Three.js?

+0

Посмотри на [текстурах] (https://developer.mozilla.org/ EN-US/Docs/Web/API/WebGL_API/Учебное пособие/Using_textures_in_WebGL). В частности, в [texImage2D] (https://developer.mozilla.org/en/docs/Web/API/WebGLRenderingContext/texImage2D). – mlkn

+1

Чтобы переместить данные между типизированными массивами, вы можете использовать 'imageDataTo.data.set (imageDataFrom.data)' Для копирования части данных (прямой) используйте 'set' и' subArray' для перемещения строк. Для каждой строки (imageData is id) 'idTo.data.set (idFrom.data.subArray ((yFrom * idFrom.width + xFrom) * 4, width), (yTo * idTo.width + xTo) * 4)' If вам нужно проверить каждый пиксель, вы можете создать Uint32Array для обработки пикселя в одном режиме чтения/записи с помощью 'data32 = new Uint32Array (imageData.data.buffer)' Note little/big endian. Также canvas - это изображение, поэтому вы можете визуализировать 'context.drawImage (canvasFrom, ...' от холста до холста – Blindman67

ответ

0

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

Лучший способ может использовать бит saveDrawingBuffer для webgl, а затем использовать две текстуры в круговом режиме с TexImage2D. Чтобы отобразить только грязную область, вам нужно настроить данные вершин для DrawArrays на основе грязных координат.

WebGL все равно придется копировать данные по множеству, но, возможно, эти пути копирования лучше оптимизированы, чем putImageData. Но существует серьезная опасность того, что webgl может быть медленнее, потому что драйверы часто оптимизируют для использования, когда текстурные изображения статичны и используются для нескольких визуализаций. Это ускоряет рендеринг, но медленнее загружает данные текстуры.

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

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

Если бы вы могли сделать что-то вроде

let imageData = new ImageData(args.frameBuffer, args.dirtyWidth, args.dirtyHeight); 
context.putImageData(imageData, args.dirtyX, args.dirtyY); 

Конечно текущий интерфейс может быть повторен с

let imageData = new ImageData(args.frameBuffer, 1920, Math.floor((args.frameBuffer.length + 4*1919)/(4*1920))); 
context.putImageData(imageData, 0,0, args.dirtyX, args.dirtyY, args.dirtyWidth, args.dirtyHeight); 
+0

Спасибо за то, что я использовал весь frameBuffer. Это уже значительно ускоряет работу. – sqwk

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