2014-01-05 23 views
5

我正在處理基於2D圖層的應用程序,並且想要使用WebGL進行合成。這些圖層可能會相對於彼此移動,並且每個圖層只有每個圖層的小(矩形)部分可能會發生變化。但是,該矩形部分的寬度和高度可能會發生不可預測的變化。 我想每層使用一個畫布(2D)和一個紋理,並且每個畫布在每個畫布上僅重繪被修改的圖層部分,然後只需將該小區域上載到GPU以將相應部分更新爲紋理,在GPU爲我合成之前。然而,我還沒有找到一種有效的方式將圖像的一部分上傳到紋理的一部分。看起來texSubImage2D()可以更新紋理的一部分,但只拍攝完整的圖像/畫布,並且似乎無法指定要使用的圖像的矩形區域。WebGL:有沒有一種將圖像/畫布的一部分作爲紋理上傳的有效方法?

我已經想到了這樣做的幾種方法,但每次似乎有明顯的開銷:

  • 使用getImageData() + texSubImage2D()只上傳到GPU改變的部分(開銷將畫布像素數據的ImageData)
  • 重新上傳整個層畫布texImage2D()
  • 每一幀或創建/調整小canvas2D到正確的尺寸,以伏貼每層修改,然後使用texSubImage2D()將其發送到更新相關紋理(記憶r節約開銷)

那麼,有沒有辦法指定圖像的一部分/畫布的紋理?類似於texImagePart2D()texSubImagePart2D,它們都會接受另外四個參數,sourceXsourceYsourceWidthsourceHeight以指定要使用的圖像/畫布的矩形區域?

+0

至少在大多數嵌入式GPU中,TexSubImage2D API將會變慢。使用TexImage2D本身可能會更好。 – prabindh

+0

因此,即使只修改了整個紋理的一部分,也沒有比重新上傳整個紋理更快的方法嗎?但我不明白,爲什麼它會變慢,如果它只上傳一個小矩形而不是整個紋理?是否因爲修改現有的紋理很慢? – Jor

回答

4

不幸的是,沒有辦法上傳一部分畫布/圖像。

WebGL所基於的OpenGL ES 2.0不提供這種方法。 OpenGL ES 3.0確實提供了一種將源的較小矩形上傳到紋理或紋理的一部分的方法,因此可能下一版本的WebGL將提供該功能。

現在你可以有一個單獨的畫布來幫助上傳。一是大小畫布比賽你想要的部分上傳

canvasForCopying.width = widthToCopy; 
canvasForCopying.height= heightToCopy; 

然後你想複製到畫布畫布的部分用於複製

canvasForCopying2DContext.drawImage(
    srcCanvas, srcX, srcY, widthToCopy, heightToCopy, 
    0, 0, widthToCopy, heightToCopy); 

然後用它來上傳到複製紋理你想要它。

gl.texSubImage2D(gl.TEXTURE_2D, 0, destX, destY, gl.RGBA, gl.UNSIGNED_BYTE, 
       canvasForCopying); 

getImageData很可能會比較慢,因爲瀏覽器必須調用readPixels得到圖像數據和攤位的圖形管線。瀏覽器不必爲drawImage這樣做。

至於爲什麼texImage2D有時可能比texSubImage2D更快取決於驅動程序/ GPU,但顯然有時texImage2D可以使用DMA來實現,而texSubImage2D不能。texImage2D也可以通過製作新的紋理來流水線化,並且懶散地丟棄舊的那個,因爲texSubImage2D不能。

我個人並不擔心,但如果你想檢查,使用texImage2DtexSubImage2D(不要只是一個時間,因爲圖形是流水線)上傳成千上萬的紋理。如果紋理很大,並且要更新的部分小於紋理的25%,則可能會發現texSubImage2D會更快。至少這是我上次查看時發現的。大多數當前的驅動程序至少進行了優化,如果您撥打texSubImage2D並恰好替換整個內容,他們會在內部調用texImage2D代碼。

+0

非常感謝您的詳細解答。我想我會使用該drawImage/texSubImage2D解決方法。問候。 – Jor

相關問題