簡體   English   中英

支持 WebGL1 + WebGL2

[英]Supporting WebGL1 + WebGL2

我有一個使用 WebGL1 來渲染事物的庫。 它大量使用浮動紋理和實例化渲染。

現在,對 WebGL1 的支持似乎很奇怪,一些設備支持例如 WebGL2,這些擴展是核心,但不支持 WebGL1,或者支持它,但不支持擴展。

同時,對 WebGL2 的支持並不令人驚奇。 也許有一天它會是,但事實並非如此。

我開始研究支持這兩個版本需要什么。

對於着色器,我想我基本上可以擺脫#define東西。 例如, #define texture2D texture等類似的東西。

當涉及到擴展時,問題就更大了,因為擴展對象不再存在。 作為實驗,我嘗試將擴展屬性復制到上下文對象中,例如gl.drawArraysInstanced = (...args) => ext.drawArraysInstancedANGLE(...args)

說到紋理,不需要太多改變,也許在 WebGL1 中運行時添加gl.RGBA8 = gl.RGBA類的東西,因此在 WebGL2 中運行時它會“正常工作”。

那么問題來了……有人試過嗎? 我擔心它會損害性能,尤其是函數調用的額外間接性。 如果假設它可以在 WebGL1 中運行,它也會使閱讀代碼變得不那么明顯。 畢竟,沒有 WebGL1 上下文具有drawArraysInstancedRGBA8 這也困擾 Typescript 打字和其他小事。

另一種選擇是在代碼中設置分支。 兩個版本的着色器(或#ifdef技巧),每個需要紋理格式的地方都有大量的支撐,以及每個完成實例化的地方。 到處都是類似的東西是非常丑陋的:

if (version === 1) {
  instancedArrays.vertexAttribDivisorANGLE(m0, 1);
  instancedArrays.vertexAttribDivisorANGLE(m1, 1);
  instancedArrays.vertexAttribDivisorANGLE(m2, 1);
  instancedArrays.vertexAttribDivisorANGLE(m3, 1);
} else {
  gl.vertexAttribDivisor(m0, 1);
  gl.vertexAttribDivisor(m1, 1);
  gl.vertexAttribDivisor(m2, 1);
  gl.vertexAttribDivisor(m3, 1);
}

最后,也許還有第三種方式我沒有想到。

有什么建議嗎?

不幸的是,我認為大多數答案將主要基於意見。

第一個問題是為什么兩者都支持? 如果您的想法在 WebGL1 上運行良好,那么只需使用 WebGL1。 如果您絕對必須擁有 WebGL2 功能,那么請使用 WebGL2 並意識到許多設備不支持 WebGL2,並且 Safari 尚不支持 WebGL2(2020 年 9 月)並且可能永遠不會支持 WebGL2,盡管它似乎終於到來了

如果您打算這樣做, twgl 會嘗試通過提供將所有 WebGL1 擴展復制到它們的 WebGL2 API 位置的函數來使其更容易。 就像你提到的那樣,而不是

ext = gl.getExtension('ANGLE_instanced_arrays');
ext.drawArraysInstancedANGLE(...)

你反而做

twgl.addExtensionsToContext(gl);
gl.drawArraysInstanced(...);

我不相信會有任何明顯的性能差異。 特別是因為這些函數每幀只被調用幾百次,所以包裝不會成為代碼中的瓶頸。

重點並不是真正同時支持 WebGL1 和 WebGL2。 相反,它只是為了使您編寫代碼的方式對於兩個 API 是相同的。

盡管如此,這 2 個 API 確實存在差異。 例如要在 WebGL1 中使用 FLOAT RGBA 紋理,您使用

gl.texImage2D(target, level, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, ...)

在 WebGL2 中

gl.texImage2D(target, level, gl.RGBA32F, width, height, 0, gl.RGBA, gl.FLOAT, ...)

在這種情況下,如果您嘗試像 WebGL1 一樣調用 WebGL2,它將失敗。 還有其他差異

在 WebGL1 和 WebGL2 中可以正常工作。 該規范明確指出,WebGL2 上的組合會產生 RGBA8。

請注意,您需要 RGBA8 的示例不正確。

gl.texImage2D(target, level, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, ...)

但最大的區別是,如果您可以使用 WebGL1,則沒有理由使用 WebGL2。 或者,反之亦然,如果您需要 WebGL2,那么您可能無法輕松回退到 WebGL1

例如,您提到對着色器使用定義,但您將如何處理 WebGL2 中未包含在 WebGL1 中的功能。 textureFetch或mod %運算符,或整數屬性等功能。如果您需要這些功能,您通常需要編寫一個僅限WebGL2 的着色器。 如果您不需要這些功能,那么首先使用 WebGL2 真的沒有意義。

當然,如果你真的想要去做,也許你想制作一個更高級的渲染器,如果用戶有 WebGL2,如果用戶有 WebGL1,則回退到更簡單的渲染器。

TD;LR IMO 選擇一個或另一個

我在編寫我的庫的文檔時發現了這個問題,它有很多目標,但其中之一正是這樣 - 同時支持 WebGL1 和 WebGL2 以獲得更高的跨設備兼容性。

https://xemantic.github.io/shader-web-background/

例如,我使用BrowserStack發現三星手機不支持在 WebGL1 中渲染到浮點紋理,而在 WebGL2 中對它們來說完全沒問題。 同時,WebGL2 永遠不會出現在 Apple 設備上,但渲染到半浮點紋理得到了很好的支持。

我的庫沒有提供完整的 WebGL 抽象,而是為片段着色器配置管道。 以下是 GitHub 上的源代碼,其中包含取決於版本的 WebGL 策略代碼:

https://github.com/xemantic/shader-web-background/blob/main/src/main/js/webgl-utils.js

因此,要回答您的問題,這是可行且可取的,但是對於每個 WebGL 功能,以完全通用的方式進行操作可能會非常具有挑戰性。 我想首先要問的問題是“共同點是什么?” 在支持的擴展方面。

暫無
暫無

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

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