Emscripten 中的 OpenGL 支援

Emscripten 提供三種 OpenGL 模式

本主題提供有關模式以及如何啟用它們的資訊。

提示

我們強烈建議新程式碼使用與 WebGL 相容的 OpenGL ES 2.0/3.0 子集,如果可能,將現有程式碼移植到此子集。其他兩種模式效率較低,僅應考慮用於嚴重依賴這些功能的程式碼庫。

與 WebGL 相容的 OpenGL ES 2.0/3.0 子集

預設情況下,Emscripten 的目標是與 WebGL 相容的 OpenGL ES 2.0 子集。這是直接對應到 WebGL 的 GL ES 命令集,因此每個 GL 命令都大致直接對應到 WebGL。它包含幾乎所有 OpenGL ES 2.0,但值得注意的是客戶端陣列以及 WebGL 1.0 規格/第 6 章中列出的一些其他功能除外。

為了針對 OpenGL ES 的 WebGL 子集進行程式設計,可以使用 GL ES 2.0 標頭檔和 GL ES 2.0 API,同時遵守 WebGL 規格第 6 章中指定的限制。

預設使用此模式,因為它最符合瀏覽器提供的 WebGL 功能。

為了針對 WebGL 2,請傳遞連結器旗標 -sMAX_WEBGL_VERSION=2。指定此旗標會在執行時啟用 (並預設為,除非在建立內容時另行指定) 建立 WebGL 2 內容,但仍然可以建立 WebGL 1 內容,因此應用程式可以選擇是否需要 WebGL 2 或是否支援回退到 WebGL 1。

為了僅針對 WebGL 2 並完全放棄對 WebGL 1 的支援以節省程式碼大小,請傳遞連結器旗標 -sMIN_WEBGL_VERSION=2-sMAX_WEBGL_VERSION=2

OpenGL ES 2.0/3.0 模擬

此建置模式模擬 OpenGL ES 2.0/3.0 的一些功能,這些功能不是核心 WebGL 1 規格的一部分。

特別是,此模式模擬缺少 1 的客戶端陣列與 WebGL 相容的 OpenGL ES 2.0/3.0 子集

這讓您可以使用 glDrawArraysglDrawElements 等函式,而無需繫結緩衝區,Emscripten 的 GL 繫結會自動設定緩衝區 (WebGL 需要繫結緩衝區)。

注意

此建置模式有一個限制,即客戶端索引緩衝區中最大的索引必須小於該緩衝區中的索引總數。如需詳細資訊,請參閱issue #4214

若要啟用OpenGL ES 2.0 模擬,請在連結專案的最終可執行檔 (.js/.html) 時指定emcc 選項 -sFULL_ES2

若要啟用OpenGL ES 3.0 模擬,請在連結專案的最終可執行檔 (.js/.html) 時指定emcc 選項 -sFULL_ES3。這會新增將記憶體區塊對應至客戶端記憶體的模擬。旗標 -sFULL_ES2-sFULL_ES3 是正交的,因此可以指定其中一個或兩個來模擬不同的功能。

舊版桌面 OpenGL API 功能的模擬

此 OpenGL 模式支援許多舊版桌面 OpenGL 1.x 功能和命令 (例如「立即模式」和 glNormalPointer)。

雖然模擬絕非完整,但它已足以使用 Emscripten 移植 Sauerbraten 3D 遊戲 (BananaBread 專案) 和其他一些真實世界的程式碼庫。

若要啟用此模式,請在連結專案的最終可執行檔 (.js/.html) 時指定emcc 選項 -sLEGACY_GL_EMULATION

最佳化設定

在此模式 (-sLEGACY_GL_EMULATION) 中,有一些額外的旗標可用於調整 GL 模擬層的效能

  • -sGL_UNSAFE_OPTS 嘗試略過多餘的 GL 工作和清除。此最佳化是不安全的,因此預設不會啟用。

  • -sGL_FFP_ONLY 告知 GL 模擬層您的程式碼完全不會使用可程式化管線/著色器。這讓 GL 模擬程式碼可以在知道安全的情況下執行額外的最佳化。

  • Module.GL_MAX_TEXTURE_IMAGE_UNITS 整數新增到您的 shell .html 檔案,以表示程式碼使用的紋理單位最大數量。這可確保 GL 模擬層在檢查要執行的固定函式管線 (FFP) 模擬著色器時,不會浪費時脈週期來迭代未使用的紋理單位。

如果我的程式碼庫依賴目前不受支援的桌面 OpenGL 功能,該怎麼辦?

您可以考慮針對 Regal 桌面 OpenGL 模擬程式庫建置程式碼庫,該程式庫旨在支援基於 OpenGL ES 2.0 的桌面 OpenGL 功能。根據專案的不同,這可能比 Emscripten 的 GL 模擬更好或更差。另一種選擇是使用 gl4es,它旨在快速將 OpenGL 轉換為 GLES 以用於遊戲。它的目標是基於 OpenGL ES 2.0 的 OpenGL 2.1 設定檔,並且已經使用 Emscripten 移植了一些遊戲。

OpenGL ES 擴充功能

在移植程式碼時,應注意桌面 OpenGL、OpenGL ES 和 WebGL 各自擁有自己的擴充功能登錄。這表示桌面 OpenGL 或 OpenGL ES 擴充功能都不會自動成為 WebGL 擴充功能,儘管確實存在一定程度的對等性。請參閱 WebGL 1.0 擴充功能登錄以取得完整已註冊擴充功能清單。

此外,在 WebGL 中,與桌面或行動 OpenGL 不同,必須先啟用擴充功能,它們所公開的功能才會生效。如果您使用原生 API SDL、EGL、GLUT 或 GLFW 來建立 GL 內容,則對於大多數擴充功能,會自動完成此操作。如果您改為使用 HTML5 WebGL 內容建立 API,則必須明確選擇是否自動啟用 WebGL 擴充功能。如果未在內容建立時自動啟用擴充功能,則可以使用 HTML5 API 函式 emscripten_webgl_enable_extension 來啟用它。偵錯相關的擴充功能、草稿擴充功能和廠商前置字元擴充功能 (MOZ_*, WEBKIT_*) 永遠不會在內容建立時自動啟用,而是必須一律手動啟用。

從 WebGL 1 遷移到 WebGL 2 時,請注意一些 WebGL 1 擴充功能會遷移到核心 WebGL 2,因此它們的功能不再宣傳為 GL 擴充功能。這並不表示缺少這些功能,而是可以在 WebGL 2 中利用這些功能,而無需先進行功能測試以確認是否存在 GL 擴充功能。

測試程式碼/範例

test/third_party/glbook 中的檔案提供了一些僅使用與 WebGL 相容的 OpenGL ES 2.0/3.0 子集的簡單範例。

其他模式已在各種測試中涵蓋,包括 test/test_browser.py 中的幾個測試。 找到這些測試的最佳方法是搜尋原始碼中適當的編譯器標誌: FULL_ES2LEGACY_GL_EMULATION 等。

錯誤回報

Emscripten 的 錯誤追蹤器 有專用於 OpenGL 和 OpenGL 模擬的標籤,用於追蹤各種與 GL 相關的問題。

腳註

1

WebGL 中缺少客戶端陣列,因為它們不如正確使用 GPU 端資料有效率。