簡體   English   中英

繪制HTML 5畫布的最快方法是什么?

[英]What's the fastest way to draw to an HTML 5 canvas?

我正在調查使用HTML畫布作為顯示媒體制作游戲的可能性。 為了完成我需要做的示例任務,我需要從多個等距區塊構建游戲環境。 當然,在2D工作意味着他們必須采用矩形包裝,因此瓷磚之間有很大的重疊。

我已經夠大了,這個問題的自然解決方案就是調用BitBltMasked。 哦等等,不,HTML畫布沒有像BitBlt那樣簡單和令人愉悅的東西。 似乎將像素數據轉儲到畫布的唯一方法是使用drawImage(),它沒有用於忽略alpha通道的有用繪圖模式,或者使用具有數組中圖像數據的ImageData對象。 訪問。 是。 界限。 檢查。 和。 因此。 狗。 慢。

好吧,這更像是一個咆哮而不是一個問題(W3C喜歡的東西往往會引起我的注意),但我真正想知道的是如何快速繪制畫布? 我發現很難放棄做100s drawImages()的感覺,每次抽獎都尊重alpha通道,這本身就是有罪的,並且可能使我的應用程序在許多瀏覽器中表現得像屁股。 另一方面,實現BitBlt的唯一方法在很大程度上依賴於瀏覽器使用類似熱點的執行技術來使其快速運行。

有沒有辦法快速划分每個可能的實現,或者我只是忘記性能?

這是一個非常有趣的問題,你可以做一些有趣的事情來解決它。

首先,您應該知道drawImage可以接受Canvas,而不僅僅是圖像。 “sub-Canvas”甚至不需要在DOM中。 這意味着您可以在一個畫布上進行一些合成,然后將其繪制到另一個畫布上。 這開啟了整個世界的優化機會,特別是在等距瓷磚的背景下。

假設你的區域有50個瓷磚長50個瓷磚寬(為了我自己的理智,我會說米)。 您可以將區域划分為10x10m塊。 每個塊都由自己的Canvas表示。 要繪制完整場景,您只需將每個塊的Canvas對象繪制到顯示給用戶的主畫布上。 如果只有四個塊(一個20x20m的區域),則只執行四次drawImage操作。

當然,每個單獨的塊都需要渲染自己的Canvas。 在游戲刻度中,塊中沒有任何反應,您根本不做任何事情:畫布將保持不變並將按照您的預期繪制。 當某些事情發生變化時,你可以根據你的游戲做一些事情:

  1. 如果您的切片延伸到第三維(即:您有一個Z軸),您可以將切塊的每個“圖層”繪制到自己的畫布中,並僅更新需要更新的圖層。 例如,如果每個塊包含十層深度,則您將擁有十個Canvas對象。 如果更新了第6層上的某些內容,您只需要重新繪制第6層的Canvas(可能是每平方米一個drawImage ,這將是100),然后在塊(10)中每層執行一次drawImage操作以重新繪制大塊的畫布。 減少或增加塊大小可能會增加或減少性能,具體取決於您對游戲環境所做的更新次數。 可以進一步優化以消除對於模糊的瓦片等的drawImage調用。
  2. 如果你沒有第三個維度,你可以簡單地每平方米一個塊執行一個drawImage 如果更新了兩個塊,那么每個tick只有200個drawImage調用(加上屏幕上每個塊可以調用一個)。 如果您的游戲只涉及很少的更新,減少塊大小將進一步減少調用次數。
  3. 您可以在自己的游戲循環中對塊進行更新。 如果你正在使用requestAnimationFrame (你應該這樣),你只需要將塊Canvas對象繪制到屏幕上。 獨立地,您可以在setTimeout循環等中執行游戲邏輯。 然后,每個塊可以在幀之間自己更新,而不會影響性能。 這也可以在web worker中使用getImageDataputImageData在需要更新時將渲染的塊發送回主線程,盡管無縫地完成這項工作需要花費很多精力。

您擁有的另一個選項是使用像pixi.js這樣的庫來使用WebGL渲染場景。 即使對於2D,它也會通過減少CPU需要做的工作量並將其轉移到GPU來提高性能。 我強烈建議您查看它。

我知道GameJS有blit操作,我當然也認為其他任何html5游戲庫都有(gameQuery,LimeJS等)。 我不知道這些軟件包是否已解決了您所遇到的特定數組邊界檢查問題,但實際上它們的示例似乎在所有平台上都能快速運行。

你不應該假設加速是有意義的。 例如,GameJS開發人員報告說他將實現臟矩形跟蹤,但事實證明現代瀏覽器會自動執行此操作--- 鏈接

出於這個原因和其他原因,我建議在考慮速度之前先做點工作。 此外,使用繪圖庫,因為作者可能花了一些時間來優化性能。

我對此沒有個人知識,但是您可以查看appMobi“直接畫布”HTML元素,據稱這是一個更快的普通畫布鏈接版本。 我很困惑這是適用於所有瀏覽器還是僅適用於webkit瀏覽器,或者僅適用於appMobi自己的特殊瀏覽器。

同樣,如果沒有對Web瀏覽器內部流程的深入了解,您不應該假設加速是有意義的。 關於“直接畫布”的網頁提到了一系列減慢畫布速度的事情:“重新流動文本,映射熱點,為參考鏈接創建索引,不斷創建。” Alpha混合和數組邊界檢查沒有被提及作為緩慢的主要原因!

不幸的是,沒有辦法解決alpha組合開銷問題。 剪切可能是一種解決方案,但我懷疑會有多少(如果有的話)性能提升。 更不用說這種路線在不規則形狀上的實施有多復雜。

當你必須繪制整個顯示器時,你將不得不處理性能損失。 雖然之后,您有一個完整屏幕的預先計算的alpha圖像,您可以在一個drawImage調用中以偏移量繪制此圖像數據。 然后,您只需要單獨繪制滾動到視圖中的新切片。

但是,瀏覽器仍然需要在畫布中的不同位置重繪每個像素。 這是非常昂貴的。 如果只有滾動像素的方法會很好,但也沒有運氣。

想到的一個想法是,您可以實現多個畫布,翻譯每個單獨的畫布而不是重繪像素。 這將允許瀏覽器以更原生的方式決定如何重繪這些像素,至少在理論上是這樣。 然后,您可以在新的或已使用/緩存的canvas元素上呈現新顯示的tile。 定位它以匹配最后一個屏幕渲染。

但那只是我的兩個blits ...我的意思是位...呃,我的意思是美分:]

暫無
暫無

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

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