首頁
» 最佳化 WebGL
由於 WebGL 需要額外的驗證來確保網路安全性,因此已知執行 WebGL 應用程式的 CPU 端額外開銷,與原生 OpenGL 應用程式相比更高。 因此,當與 GL 函數介接時,移植圖形密集型應用程式可能會在 CPU 端遇到瓶頸。因此,為了獲得最佳效能,應特別注意分析和最佳化預期為 WebGL 密集型的應用程式中的 GL API 使用情況。本最佳化指南重點介紹了對於提升 WebGL 效能有用的各種不同技術。
市面上有太多的 GL 硬體和驅動程式供應商,以及作業系統組合,因此產生具體的最佳化指南是很困難的。在某些硬體/驅動程式/作業系統組合上有效的某些最佳化,在其他供應商的驅動程式上卻沒有明顯的差異。 幸運的是,很少有發現衝突的情況,其中針對某個驅動程式的某些最佳化會導致其他 GPU 供應商的硬體效能大幅下降。 通常,發生這種情況的原因是特定硬體不支援特定功能,這會導致驅動程式訴諸模擬。例如,在一個案例中,發現原生 GL 驅動程式宣告支援 ETC2 壓縮紋理格式,即使圖形硬體沒有實作此格式,而在另一個案例中,發現使用頂點著色器基本重新啟動索引會導致 GL 驅動程式回退到在軟體中執行頂點著色器。不幸的是,OpenGL 規格並未提供驅動程式回報這些效能注意事項的方法,這就是為什麼在最佳化 GL 時,能夠跨各種目標硬體進行基準測試幾乎是必要的。當執行時,密切關注瀏覽器的網頁主控台也很有用,因為瀏覽器可以在主控台記錄中回報額外的效能警告。
還應該承認,某些偵測到的效能問題是由於瀏覽器及其使用的軟體程式庫中的效率低下或完全的效能錯誤所致,與底層 GL 驅動程式或一般網路安全性無關。在最初最佳化 Emscripten 移植的 GL 程式碼庫時,發現大多數瀏覽器的 WebGL 堆疊效率低下,但這是可以預期的,因為在 Emscripten 和 asm.js 之前,甚至不可能在原生和網路之間進行如此精確的 GL 效能比較,以至於許多效能關鍵問題都被忽略了。隨著越來越多人使用大型 Emscripten 程式碼庫來測試 WebGL,這方面的情況正在穩步改善,因此本指南中的某些項目在未來可能不再相關。 如果您在未來閱讀本指南時發現某些東西在所有情況下似乎都是淨損失,請提交文件 PR 進行討論。同樣地,如果某些 GL 存取模式在網路上比原生慢幾個數量級,則很可能是效能錯誤。
以下最佳化技巧列出了已知在實踐中產生影響的各種情況,儘管建議永遠不要盲目地執行最佳化,而是在實驗時隨時準備好效能分析器。
Emscripten 允許使用不同的連結器旗標鎖定各種不同的 OpenGL 和 OpenGL ES API 風格。
依預設,如果未選擇任何特殊的 GL 相關連結器旗標,Emscripten 會鎖定 WebGL 1 API,使用者程式碼會透過在 C/C++ 程式碼中包含 OpenGL ES 2.0 標頭來存取(#include <GLES2/gl2.h>
和 #include <GLES2/gl2ext.h>
)。此模式的作用與 GLES 2 類似,但套用了一些 WebGL 特有的變更和限制。如需 WebGL 1 和 OpenGL ES 2 之間差異的近乎完整參考,請參閱 WebGL 1 規格:WebGL 與 OpenGL ES 2.0 之間的差異。
如果您的應用程式從用戶端記憶體中轉譯幾何圖形,則需要使用連結器旗標 -sFULL_ES2
建置。此模式方便簡化新程式碼庫的移植,但是 WebGL 本身不支援從用戶端記憶體轉譯,因此會模擬此功能。為了獲得最佳效能,請改用 VBO 並在建置時不要使用 -sFULL_ES2
連結器旗標。
如果您的應用程式鎖定舊的桌面 OpenGL API,則使用 -sLEGACY_GL_EMULATION
旗標建置時可能會有效。但是,以此模式建置時,即使有效,也不要期望獲得良好的效能。如果應用程式在此模式下很慢,而且僅使用固定管線而沒有任何著色器,也可以將 -sLEGACY_GL_EMULATION
與 -sGL_FFP_ONLY
連結器旗標配對,以嘗試恢復一些效能。儘管通常建議花費力氣將應用程式移植為改用 WebGL 1/OpenGL ES 2。
當鎖定 OpenGL ES 3 時,如果需要從用戶端記憶體轉譯,或者需要使用 glMapBuffer*()
API,請傳遞連結器旗標 -sFULL_ES3
來模擬這些功能,而核心 WebGL 2 沒有這些功能。預期這種模擬會損害效能,因此建議改用 VBO。
即使您的應用程式不需要任何 WebGL 2/OpenGL ES 3 功能,也請考慮將應用程式移植為在 WebGL 2 上執行,因為 WebGL 2 中的 JavaScript 端效能已最佳化為不產生暫時性的垃圾,據觀察,這會帶來 3-7% 的速度提升,並減少轉譯時潛在的停頓。若要啟用這些最佳化,請使用連結器旗標 -sMAX_WEBGL_VERSION=2
建置,並確保在 GL 啟動時建立 WebGL 2 環境 (如果使用 EGL,則為 OpenGL ES 3 環境)。
可以使用多種工具來衡量 GL 效能。一般來說,建議開發人員不要僅將重點放在搜尋 Web 瀏覽器特定的分析工具上,但在實務中發現原生分析器同樣有效,如果不是更好的話。使用原生分析器的唯一缺點是,對瀏覽器中 WebGL 的實作方式的一些深入了解可能是至關重要的,否則可能難以理解傳輸到 GPU 的呼叫串流。
若要大致了解不同 WebGL 入口點中花費的時間,請使用 Firefox 及其 Gecko 分析器附加元件。 此分析器工具能夠顯示跨越已執行程式碼的整個堆疊的時序資料:手寫 JavaScript、asm.js/WebAssembly 和原生 Firefox C/C++ 瀏覽器程式碼,這使其比其他分析工具更有價值。
能夠分析 CPU 額外開銷的實用原生工具包括 AMD CodeXL、Intel VTune Amplifier 和 macOS Instruments。如果瀏覽器效能分析工具表示大部分時間都花在瀏覽器入口點本身內,則這些工具可能有助於找出熱點所在。但是,當使用原生 CPU 分析工具時,有必要從原始碼手動建置瀏覽器程式碼,以取得符號資訊資料(例如 Windows 上的 .pdb 檔案),這些工具會在本機查閱這些資料。以這種方式偵錯 Firefox 時,停用 Firefox 中的多進程架構有助於取得在與瀏覽器本身相同的執行緒中執行內容進程的追蹤。將 Firefox 瀏覽器導覽到頁面 about:config
並將偏好設定 browser.tabs.remote.autostart.2
設定為 false
,然後重新啟動瀏覽器。
對於偵錯 GPU 端 API 呼叫追蹤,NVidia Nsight、Intel Graphics Performance Analyzers、Visual Studio 圖形偵錯工具 和 AMD CodeXL 都是有用的工具。在 Windows 上,Firefox 能夠使用 OpenGL 或 Direct3D 來轉譯 WebGL 內容。Direct3D 是預設值,但例如 AMD CodeXL 僅追蹤 OpenGL 呼叫串流。為了使用 AMD CodeXL 在 Firefox 中追蹤 WebGL API 呼叫,請將瀏覽器導覽至 about:config
並將偏好設定 webgl.disable-angle
設定為 true
,然後重新載入頁面。
在 WebGL 中,每個 GL 函式呼叫都會產生一定的額外負擔,即使是那些看似簡單且幾乎沒有做任何事的函式呼叫也是如此。這是因為 WebGL 實作需要驗證每次呼叫,因為底層的原生 OpenGL 規範沒有提供任何可以在網路上依賴的安全保證。此外,在 asm.js/WebAssembly 端,每個 WebGL 呼叫都會產生 FFI 轉換(在 asm.js 環境中執行程式碼和在瀏覽器原生 C++ 環境中執行程式碼之間的跳躍),其額外負擔略高於 asm.js/WebAssembly 內的常規函式呼叫。因此,在網路上,為了 CPU 端的效能,通常最好盡量減少對 WebGL 的呼叫次數。以下是一些可以應用的技巧。
在高層級優化渲染器和輸入資源,以避免冗餘呼叫。如果需要,請重構設計,使渲染器能夠更好地判斷哪些狀態變更相關,哪些是不需要的。最好的快取是不必要的快取,因此如果高層級渲染器能夠保持 GL 呼叫串流精簡,將會產生最快的結果。但是,在難以實現的情況下,某些類型的低層級快取可能會有效,如下所述。
將 GL 狀態快取在渲染器程式碼中,並避免多次冗餘呼叫來設定相同的狀態(如果它沒有變更)。例如,某些引擎可能會在每次繪圖呼叫之前盲目地重新設定深度測試或 alpha 混合模式,或為每次呼叫重設著色器程式。
避免所有在某些操作後將 GL 重設為特定「基礎狀態」的渲染器模式。常見的情況是在每次繪圖呼叫後執行 glBindBuffer(GL_ARRAY_BUFFER, 0)
、glUseProgram(0)
或 for(i in 0 -> max_attributes) glDisableVertexAttribArray(i);
,以還原到已知的固定配置。相反地,在從一個繪圖呼叫轉換到另一個呼叫時,僅延遲變更需要的 GL 狀態即可。
考慮僅在需要生效時才延遲設定 GL 狀態。例如,在以下呼叫串流中
// First draw glBindBuffer(...); glVertexAttribPointer(...); glActiveTexture(0); glBindTexture(GL_TEXTURE_2D, texture1); glActiveTexture(1); glBindTexture(GL_TEXTURE_2D, texture2); glDrawArrays(...); // Second draw (back-to-back) glBindBuffer(...); glVertexAttribPointer(...); glActiveTexture(0); // (*) glBindTexture(GL_TEXTURE_2D, texture1); // (*) glActiveTexture(1); // (*) glBindTexture(GL_TEXTURE_2D, texture2); // (*) glDrawArrays(...);
所有標記星號的四個 API 呼叫都是冗餘的,但是簡單的狀態快取不足以偵測到這一點。更延遲的狀態快取機制將能夠偵測到這些類型的變更。但是,在實作深度延遲狀態快取時,建議僅在擁有效能分析資料來激勵優化之後才進行,因為在渲染之前對所有 GL 狀態應用延遲快取技術也可能由於其他原因而變得昂貴,並且如果渲染器已經擅長避免重新提交冗餘呼叫,則可能會浪費效能。適量的快取可能需要一些微調才能找到平衡。
一個好的經驗法則是,透過高層級設計從一開始就避免冗餘狀態呼叫的渲染器通常比嚴重依賴低層級狀態快取的渲染器更有效率。
除了刪除完全冗餘的 API 呼叫之外,還應該注意如何使用其他技術來減少狀態變更。以下清單提供了一些可能性。
當渲染到離屏渲染目標時,請使用多個 FBO,以便切換渲染目標僅需要單個 glBindFramebuffer() 呼叫。這避免了每幀執行多次呼叫來設定 FBO 狀態。
避免修改 FBO 狀態,但最好設定多個不可變/靜態 FBO,它們不會變更狀態。變更 FBO 狀態會導致瀏覽器重新驗證該 FBO 組合,但是不可變的 FBO 僅需要在建立時驗證一次。
盡可能使用 VAO,以避免必須呼叫多個 GL 函式來設定用於渲染的頂點屬性。
將 glUniform* 呼叫批次化為統一變數陣列,並在一個 glUniform4fv()
陣列呼叫中更新它們,而不是多次呼叫 glUniform4f()
來單獨更新每個統一變數。或者更好的是,在 WebGL 2 中使用統一變數緩衝區物件。
不要在渲染時呼叫 glGetUniformLocation()
,而是在啟動時為每個著色器程式查詢位置並快取它們。
在適用的情況下使用實例渲染。
考慮將多個紋理合併為一個圖集,以實現更好的幾何批次化和實例化機會。
如果還沒有盡可能緊密,請考慮比原生 GL 平台更積極地剔除可渲染物件。
高效使用 GPU 最重要的方面是確保 CPU 在渲染時永遠不需要被 GPU 阻塞,反之亦然。這些類型的停頓會產生極為昂貴的 CPU-GPU 同步點,導致兩種資源的利用率不佳。通常,透過觀察整體 GPU 和 CPU 利用率,可以偵測到此類情況發生的跡象。如果 GPU 分析器聲稱 GPU 在大部分時間內處於閒置狀態,但 CPU 分析器聲稱 CPU 反而處於閒置狀態,或者某些 GL 函式需要很長時間才能完成,則表示影格沒有有效地提交到 GPU,而是在繪圖呼叫提交期間的某處發生了 GPU-CPU 同步。不幸的是,OpenGL 規範沒有提供任何關於哪些 GL 呼叫可能會導致停頓的效能保證,因此請注意以下行為,並透過變更這些行為和重新分析效果來進行實驗。
避免在渲染時建立新的 GL 資源。這意味著在渲染時優化對
glGen*()
和glCreate*()
函式(glGenTextures()
、glGenBuffers()
、glCreateShader()
等)的呼叫。如果需要新的資源,請嘗試在嘗試使用它們進行渲染之前建立和上傳它們幾個影格。同樣地,不要刪除剛剛渲染過的任何 GL 資源。
glDelete*()
函式如果驅動程式偵測到任何資源正在使用中,則可能會導致整個管線刷新。最好僅在載入時刪除資源。永遠不要在渲染時呼叫
glGetError()
或glCheckFramebufferStatus()
。這些函式應僅限於在載入時進行檢查,因為這兩者都可能執行完整的管線同步。類似地,不要在渲染時呼叫任何
glGet*()
API 函式,而是在啟動和載入時查詢它們,並在渲染時參考快取結果。嘗試避免在渲染時編譯著色器,
glCompileShader()
和glLinkProgram()
都可能非常慢。不要呼叫
glReadPixels()
在渲染時將紋理內容複製回主記憶體。如有必要,請改用 WebGL 2GL_PIXEL_PACK_BUFFER
綁定目標,先將 GPU 表面複製到離屏目標,然後才使用glReadPixels()
將該表面的內容複製回主記憶體。
在 CPU 和 GPU 之間傳輸記憶體是 GL 效能問題的常見來源。這是因為建立新的 GL 資源可能會很慢,並且如果資料尚未準備好,或者在能夠用新版本覆蓋資料之前仍然需要舊版本的資料,則上傳或下載資料可能會阻塞 CPU。
比起包含平面屬性的多個 VBO,最好在單個 VBO 中使用交錯的頂點資料。這改善了 GPU 頂點快取行為,並避免了在設定用於渲染的頂點屬性指標時多次冗餘的 glBindBuffer()
呼叫。
避免呼叫 glBufferData()
或 glTexImage2D/3D()
在執行時調整緩衝區或紋理的內容大小。在增加或減少動態 VBO 大小時,請使用 std::vector 風格的幾何陣列成長語義,以避免每幀都必須調整大小。
在更新緩衝區紋理資料時,即使紋理或緩衝區的整個內容都發生變更,也最好呼叫 glBufferSubData()
和 glTexSubImage2D/3D()
。如果緩衝區的大小會縮小,請不要急於重新建立儲存,而只需忽略多餘的大小即可。
對於動態頂點緩衝區資料,請考慮每幀對 VBO 進行雙重甚至三重緩衝,以避免上傳仍在使用的 VBO。比起 GL_STREAM
,最好使用 GL_DYNAMIC
頂點緩衝區。
在確認沒有發生 CPU-GPU 管線同步氣泡,並且渲染仍然受 GPU 限制後,以下優化可能會很有用。
在正向照明渲染器中對幾何體進行多個疊加照明繪圖通道可以很容易地實現,但是這產生的 GL API 呼叫數量可能太過昂貴。在這種情況下,請考慮在一個著色器通道中計算多個光照貢獻,即使這會在某些物件不受某些光照影響時在著色器中產生無效的算術運算。
在足夠的情況下使用最低的片段著色器精度(lowp)。預先在離線編寫時積極優化著色器,不要期望 GPU GLSL 驅動程式會動態執行任何優化。這對於行動 GPU 驅動程式尤其重要。
首先按目標 FBO、其次按著色器程式對可渲染物件進行排序,第三個排序是為了最小化任何其他所需的 GL 狀態變更或最小化過度繪製,具體取決於程式是否受 CPU 或 GPU 限制。這有助於基於瓦片的渲染器。當不再需要 FBO 的內容時,請呼叫 WebGL 2 glDiscardFramebuffer()
。
使用 GPU 分析器,或實作自訂片段著色器,這些工具可以幫助分析渲染場景的過度繪製量。大量的過度繪製不僅會產生額外的工作,而且渲染到同一顯示記憶體區塊之間的循序相依性會減慢平行渲染的速度。如果渲染已啟用深度緩衝的 3D 場景,請考慮將場景從前到後排序,以盡量減少過度繪製和多餘的每像素填充頻寬。如果在 3D 場景中使用非常複雜的片段著色器,請考慮先執行深度預處理,以將實際光柵化的色彩片段數量減少到絕對最小值。
最後,許多雜項最佳化已被證明有效。
在網路上,通常無法預期哪些壓縮紋理格式可用。請為多個壓縮紋理組合撰寫紋理,例如每個格式一個,並在執行階段下載適當的組合,以盡量減少過度下載。將紋理和其他資產儲存到 IndexedDB,以避免在後續執行時必須重新下載。Emscripten 連結器旗標 -sGL_PREINITIALIZED_CONTEXT
有助於撰寫預先執行紋理格式檢查的 html 外殼頁面。
考慮在下載其他資產時平行編譯著色器。這有助於隱藏慢速的著色器編譯時間。
在下載大量資產之前,在頁面載入過程的早期測試使用者瀏覽器是否支援 WebGL。使用者必須等待下載數 MB 的資產,然後在等待後才收到 WebGL 無法使用的錯誤訊息,這可能會讓人感到沮喪。
如果 WebGL 初始化失敗,請使用 "webglcontextcreationerror"
回呼檢查 WebGL 環境錯誤原因。瀏覽器可以在環境建立錯誤處理常式中提供良好的診斷,以協助診斷根本原因。
密切注意畫布的顯示大小(DOM 元素的 CSS 像素大小)與畫布上已初始化的 WebGL 環境的實體渲染目標大小,並確保這兩者符合,以便渲染 1:1 像素完美內容。
使用 failIfMajorPerformanceCaveat
旗標探查環境建立,以偵測是否在軟體上渲染,並在這種情況下減少圖形保真度。
請確保使用所需的最小功能量初始化 WebGL 環境。WebGL 環境建立參數包括對 alpha、深度、樣板和 MSAA 的支援,而且通常例如不需要支援將畫布與 HTML 頁面背景進行 alpha 混合,因此應該停用。
避免使用任何 *glGetProcAddress()
API 函式。Emscripten 提供所有 GL API 函式的靜態連結,甚至適用於所有 WebGL 擴充功能。*glGetProcAddress()
API 僅為了相容性而提供,以簡化現有程式碼的移植,但是透過呼叫動態取得的函式指標來存取 WebGL 會明顯慢於直接函式呼叫,因為動態調度必須在 asm.js/WebAssembly 中進行額外的函式指標安全驗證。由於 Emscripten 提供所有以靜態連結的 GL 進入點,建議利用此優勢來獲得最佳效能。
請務必使用 requestAnimationFrame()
迴圈來渲染動畫,而不是 setTimeout()
API。這可在動畫滴答時提供最順暢的排程。
與 WebGL 1 相比,新的 WebGL 2 API 提供了基本上是免費的 API 最佳化,這些最佳化只需以 WebGL 2 為目標即可啟用。此加速來自 WebGL 2 API 是從 JavaScript 繫結的角度進行修訂的事實,現在可以不用配置會導致 JS 垃圾收集器壓力的暫時性物件來使用 WebGL。這些新的進入點與 asm.js 和 WebAssembly 應用程式配合得更好,並使 WebGL API 的使用更加精簡。以案例研究來說,在不進行其他引擎修改的情況下,更新 Unreal Engine 4 以 WebGL 2 為目標,可產生 7% 更快的輸送量效能。
由於這種免費效能的來源,強烈建議所有開發人員都移轉以 WebGL 2 為目標,即使不需要其他 WebGL 2 功能,效能也是一項考量。WebGL 2 從 Firefox 51 和 Chrome 58 開始提供(請參閱#4945)。另請參閱caniuse:WebGL 2 表格。只要稍加留意,就可以同時以 WebGL 1 和 WebGL 2 API 為目標,並在可用時利用最佳效能,但在相容性較低的 GPU 上順利回溯。
在處理這兩個規格時,請務必記住 WebGL 1 是基於 OpenGL ES 2.0 規格,而 WebGL 2 是基於 OpenGL ES 3.0 規格。
移轉至 WebGL 2 的複雜性稍微高了一些,因為 WebGL 與 OpenGL ES 一樣,不是向後相容的 API。也就是說,WebGL 1/OpenGL ES 2 應用程式通常無法透過僅初始化較新版本的 GL 環境以在 WebGL 2/OpenGL ES 3.0 上執行來運作。原因是在兩個版本之間導入了一些向後不相容的變更。但是,這些變更更多是表面/外觀上的變更,而不是功能上的變更,而且在功能方面,WebGL2/OpenGL ES 3.0 包含 WebGL 1/OpenGL ES 2 中存在的所有功能。只有叫用不同 API 函式的方式已變更。
若要從 WebGL 1 移轉到 WebGL 2,請注意以下已知的不向後相容性清單。
在 WebGL 2 中,許多 WebGL 1.0 擴充功能已併入到核心 WebGL 2 API 中,並且在查詢不同 WebGL 擴充功能的清單時,不再宣告這些擴充功能存在。例如,WebGL 1 中實例化渲染的存在是由 ANGLE_instanced_arrays 擴充功能提供,但這是 WebGL 2 核心功能,因此不再在 GL 擴充功能清單中報告。如果應用程式中同時以 WebGL 1 和 WebGL 2 為目標,請記住在偵測功能是否存在時檢查擴充功能和核心環境版本號碼。
上述情況的副作用是,當功能合併到核心時,呼叫功能所用的特定函式名稱已變更,也就是說,在 WebGL1/GLES 2 環境中,會呼叫函式 glDrawBuffersEXT()
,但是在 WebGL2/GLES 3.0 中,應呼叫未加字尾的函式 glDrawBuffers()
。
已採用至核心 WebGL 2 規格的 WebGL 1 擴充功能完整清單為
ANGLE_instanced_arrays EXT_blend_minmax EXT_color_buffer_half_float EXT_frag_depth EXT_sRGB EXT_shader_texture_lod OES_element_index_uint OES_standard_derivatives OES_texture_float OES_texture_half_float OES_texture_half_float_linear OES_vertex_array_object WEBGL_color_buffer_float WEBGL_depth_texture WEBGL_draw_buffers
這些擴充功能是在沒有任何功能變更的情況下採用,因此在初始化 WebGL2/GLES 3.0 環境時,可以直接使用這些擴充功能,而無需檢查是否有擴充功能。
一個值得注意的添加是,WebGL 2 引入了新的 GLSL 著色器語言格式。在 WebGL 1 中,使用 #version 100
版本編譯指示詞在著色器程式碼中以 OpenGL ES 著色語言,版本 1.00 撰寫著色器。WebGL 2 引入了新的著色器語言版本OpenGL ES 著色語言,版本 3.00,其由著色器程式碼中的編譯指示詞 #version 300 es
識別。
在 WebGL 2/GLES 3.0 中,可以繼續使用 WebGL 1/GLES 2 #version 100
著色器,或移轉到使用 WebGL 2/GLES 3.0 #version 300 es
著色器。但請注意,WebGL 2 有一個向後不相容性,也就是 WebGL 擴充功能 OES_standard_derivatives
和 EXT_shader_texture_lod
不再在 #version 100
著色器中可用,因為這些功能不再以擴充功能的形式存在。使用這些擴充功能的 #version 100
著色器必須重寫為 #version 300 es
格式。Emscripten 提供一個連結器旗標 -sWEBGL2_BACKWARDS_COMPATIBILITY_EMULATION
,當偵測到其中一個擴充功能時,會執行基於字串搜尋取代的 #version 100
著色器自動移轉到 #version 300 es
格式,以嘗試隱藏向後相容性的這種中斷情況。
在 WebGL 2/GLES 3.0 中,許多由擴展引入的紋理格式的列舉值發生了變化。不再可能使用 WebGL 1/GLES 2 擴展中所謂的無大小紋理格式,而是必須為 internalFormat
欄位使用新的具大小變體格式。例如,不再使用 format=GL_DEPTH_COMPONENT, type=GL_UNSIGNED_INT, internalFormat=GL_DEPTH_COMPONENT
來創建紋理,而是需要在 internalFormat
欄位中指定大小,即 format=GL_DEPTH_COMPONENT, type=GL_UNSIGNED_INT, internalFormat=GL_DEPTH_COMPONENT24
。
WebGL 2/GLES 3.0 紋理格式的一個特別需要注意的問題是,當 WebGL 1/GLES 2 擴展 OES_texture_half_float
被納入 WebGL 2/GLES 3.0 核心規範時,半浮點 (float16) 紋理類型的列舉值發生了變化。在 WebGL1/GLES 2 中,半浮點數由值 GL_HALF_FLOAT_OES=0x8d61
表示,但在 WebGL2/GLES 3.0 中,則使用列舉值 GL_HALF_FLOAT=0x140b
,這與其他紋理類型擴展不同,後者通常在納入核心規範時會保留所使用的列舉值。
總體而言,為了簡化同時針對 WebGL1/GLES 2 和 WebGL2/GLES 3.0 上下文,Emscripten 提供了一個連結器標誌 -sWEBGL2_BACKWARDS_COMPATIBILITY_EMULATION
,它將上述差異隱藏在自動偵測的遷移之後,以允許現有的 WebGL 1 內容透明地也針對 WebGL 2,從而提供免費的速度提升。
如果您在此模擬中發現遺漏項目,或有意見可以改進本指南,請將回饋提交至 Emscripten 錯誤追蹤器。