簡體   English   中英

將Uint8Array渲染到畫布的最快方法

[英]Quickest way to render a Uint8Array to a Canvas

我收到的是帶有RGBA值的Uint8Array ,以及一些信息,其中圖像的一部分已更新。 將原始位圖信息呈現回畫布的最快方法是什么? 我一直在使用2D渲染上下文來手動循環遍歷數組並設置像素信息,但這非常慢:

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之類的東西?

您可以使用gl.TexSubImage2D更新紋理,然后整體塗抹紋理。 但是TexSubImage2D存在性能問題,因為它必須等待上一渲染完成才能更新下一幀的紋理。

更好的方法是對webgl使用preserveDrawingBuffer位,然后與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);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM