4.5 扩展补丁 vs WebGL2 内置


文档摘要

4.5 扩展补丁 vs WebGL2 内置 本节摘要:WebGL1 用扩展把一批 ES 3 能力提前塞进浏览器:VAO、实例化、深度纹理、多绘制缓冲、浮点纹理、元素索引 32 位。WebGL2 把其中多数收进核心,着色器升到 300 es,并补上变换反馈、三维纹理、UBO 这些扩展补不全的洞。继续在 1.0 上堆扩展,是在维护一张会漂的能力矩阵;迁 2.0 是换合同。能锁 2.0 就少写检测。必须兼容 1.0 时,把扩展失败映射成效果降级,而不是同一条路径硬跑。 本节导航 阅读完本节,你应当能够: 把常用 WebGL1 扩展对应到 WebGL2 核心对象或函数 列出扩展补不上、必须 2.

4.5 扩展补丁 vs WebGL2 内置

本节摘要:WebGL1 用扩展把一批 ES 3 能力提前塞进浏览器:VAO、实例化、深度纹理、多绘制缓冲、浮点纹理、元素索引 32 位。WebGL2 把其中多数收进核心,着色器升到 300 es,并补上变换反馈、三维纹理、UBO 这些扩展补不全的洞。继续在 1.0 上堆扩展,是在维护一张会漂的能力矩阵;迁 2.0 是换合同。能锁 2.0 就少写检测。必须兼容 1.0 时,把扩展失败映射成效果降级,而不是同一条路径硬跑。

本节导航

阅读完本节,你应当能够:

  1. 把常用 WebGL1 扩展对应到 WebGL2 核心对象或函数
  2. 列出扩展补不上、必须 2.0 或放弃的能力
  3. 设计“检测失败则降级效果”而不是“检测失败则崩溃”
  4. 说明 getExtension 返回的函数入口为何不能缓存到错误的上下文上
  5. 解释为什么教学同时覆盖两套合同时,着色器资产要分目录而不是正则替换

扩展是临时合同,核心是稳定合同

getExtension("OES_vertex_array_object") 成功时,你得到另一套函数名。失败时,你仍停在全局属性指针时代。浏览器可以改扩展支持,用户可以关硬件加速。把产品建立在一长串扩展上,等于把测试矩阵交给组合爆炸。WebGL2 的 createVertexArray 写在规范核心路径,测试从“各扩展是否存在”变成“上下文是否 2”。

补丁的价值是历史过渡:在 2.0 覆盖不足时,让 1.0 也能实例化草地。过渡期结束后,内部工具继续测扩展是亏的。面向老设备的营销页可以留在 1.0 加两三个最稳的扩展,而不是把 2.0 特性表用扩展逐条追。

WebGL1 核心 + 扩展矩阵 ≈ 部分 WebGL2 WebGL2 核心 ≈ ES 3.0 合同,仍无计算着色器

映射表:能补的和补不上的

能力 WebGL1 WebGL2
VAO OES_vertex_array_object 核心
实例化 ANGLE_instanced_arrays 核心
深度纹理 WEBGL_depth_texture 核心
多颜色附件 WEBGL_draw_buffers 核心 MRT
浮点纹理 OES_texture_float 等,过滤另扩 更完整
标准导数 OES_standard_derivatives 核心
32 位索引 OES_element_index_uint 核心
sRGB EXT_sRGB 更完整
各向异性 EXT_texture_filter_anisotropic 仍常是扩展
压缩纹理 一堆平台扩展 仍是扩展矩阵
三维纹理 基本无 核心
变换反馈 核心
UBO 核心
整数纹理 核心

各向异性与压缩纹理提醒我们:2.0 不是“所有扩展退休”。资产压缩仍要按 GPU 家族回退。2.0 收编的是绘图对象模型,不是整个生态。

function tryVAO(gl) { if (gl.createVertexArray) return { create: gl.createVertexArray.bind(gl), native: true }; const ext = gl.getExtension("OES_vertex_array_object"); if (!ext) return null; return { create: ext.createVertexArrayOES.bind(ext), native: false }; }

注意 bind 到正确对象。把扩展函数接到丢失的 gl 上会在上下文恢复后炸掉。恢复流程要重新 getExtension。

图:补丁覆盖与永久缺口

图:补丁覆盖与永久缺口

降级表要写进产品,而不是写进 if 的深渊

检测代码可以深。产品表必须浅:无实例化则草地密度降成静态合批;无浮点 FBO 则 Bloom 关;无深度纹理则平面影。每一条扩展对应一条用户能感知的损失。没有表,程序员会嵌套六层 if 还以为有回退。

着色器不要用宏在一份字符串里同时服务 1.00 与 300 es,除非你有编译器。两套资产,CPU 按版本选。扩展启用的导数、instanced 输入,也要在着色器里用对应的扩展指令。漏指令则编译失败,表现为“这台机能拿扩展却画不出来”。

⚠️ 常见坑:开发机扩展齐全,CI 无头浏览器缺扩展,测试全绿、用户全黑。能力检测要在启动时打日志或遥测,而不是假设。

💡 关键直觉:扩展是租来的能力,核心是买来的能力。租约能应急,不能当房本。

各向异性过滤常常仍要扩展,2.0 里也是。地面材质可以检测,失败则 LINEAR_MIPMAP_LINEAR。这是画质档,不是功能档。功能档是“能不能画阴影贴图”;画质档是“斜看清不清”。分清两档,产品才知道哪条失败必须关功能,哪条只降一级过滤。

问题:WebGPU 出来了,还要不要管扩展?

现有 WebGL 存量代码仍要管。新项目若锁现代浏览器,可直接 WebGL2 或评估 WebGPU。本文集合同停在 WebGL。把 WebGPU 当 WebGL3 扩展会误导:那是另一套对象模型。对照思维可迁移:仍问数据在哪一端、哪份合同。检测表不能迁移。

测试矩阵怎么缩小,以及调试扩展

扩展组合爆炸时,用“能力包”而不是单点。包 A:VAO+实例化+深度纹理,对应 1.0 增强前向。包 B:再加 draw buffers 与浮点,对应简易后处理。包 C:2.0 核心,对应延迟与反馈。产品只承诺包,不承诺单个扩展名。某扩展缺了就整包降级,避免五层嵌套。遥测上报包等级,美术按包做三档资源。这是版本轴的运营化。

调试扩展如 WEBGL_debug_renderer_info、WEBGL_debug_shaders 不要在生产依赖。它们能帮你看 GPU 名与转译后的源码,转译源码对查移动端编译器很有用。但用户可以没有它们。生产路径只依赖绘图合同。

上下文属性 failIfMajorPerformanceCaveat 会在软件渲染时拒绝给上下文。要不要拒绝是产品问题:给软件渲染一张静图,还是让它以 2 帧运行。不要 silently 拿到软件渲染还按 60 帧做粒子。检测 renderer 字符串里的 SwiftShader 一类,降到静态。这不是扩展表,是创建合同,和 1.1 的 getContext 策略连在一起。

扩展启用指令在 GLSL 里必须匹配。GL_OES_standard_derivatives 在 1.0 FS 用 fwidth 做抗锯齿或法线,忘了指令就编译失败。2.0 里导数是核心。同一份抗锯齿逻辑,两套源码或用预处理器由 CPU 注入第一行。注入要测试,不要假设桌面编译器会忽略未知指令。

软件渲染与无 GPU 的产品路径

拿不到任何上下文时,产品应有静图或 CSS 方案。这不是 WebGL 失败,是设备合同。检测放在第一帧之前。给用户一句人话:三维预览不可用,而不是控制台 invalid。扩展失败同理,用人话对应降级表。遥测记包等级。没有静图路径的营销页,会在关键渠道全白。全白比低配 3D 更伤转化。版本选择从这里已经是产品,不只是图形。

对照问答:开发机谎言、降级空、软件渲染

为何只有这台安卓黑屏?

缺扩展或 300 es 编译失败。启动打能力包与着色器日志。黑屏用人话静图。不要假设 ANGLE 桌面等于 Adreno。抽样四类机。黑屏优先当合同失败,不当随机。

写了 fallback 仍调用 2.0 函数?

else 分支复制粘贴漏改。降级表要测:强制 1.0 跑一遍 CI。空 fallback 比没有更危险,因为它给人已兼容的错觉。测失败路径与测成功路径同等重要。

帧率只有两帧还很烫?

可能落到软件渲染。检测 renderer,改静图或降粒子到零。继续跑完整 PBR 是在用 CPU 模拟 GPU,电量与体验双杀。创建时可 failIfMajorPerformanceCaveat。拿到 caveat 上下文要当失败处理。

工程备忘:能力包 CI

CI 至少跑两档:强制 webgl2、强制 webgl1 无扩展。1.0 无扩展那档必须走降级表,调用到 2.0 符号即失败。能力包枚举写进启动日志与遥测。软件渲染当失败。静图路径有自动截图对比。扩展指令与 GLSL 版本由模板注入,禁止手写散落。新效果合入要声明依赖哪一包。声明缺失则按低包裁效果,不许裸调用扩展。这是把 1.1 与 4.5 接成门禁。门禁比 wiki 有效。

能力包 CI 是本节的牙齿。没有牙齿,降级表是摆设。强制 1.0 跑用例,碰到 createVertexArray 以外的 2.0 符号就失败。着色器模板注入 version 与扩展指令,散落的手写指令审查打回。软件渲染当失败走静图。静图要和产品经理签过,避免临时决定在渠道全白。遥测包等级,运营按等级看转化,而不是按“支不支持 WebGL”二值。二值会把 1.0 增强档与软件渲染混成一堆。调试扩展只在开发构建启用。生产依赖 debug_renderer_info 会在隐私模式或策略下缺数据,逻辑不应依赖它。依赖能力对象。对象是合同,字符串是八卦。

降级表每条要有强制失败用例。没有用例的 else 视为不存在。存在幻觉比缺失更危险。幻觉会让市场承诺兼容,渠道却全白。全白时程序说有 fallback。有用例的 fallback 才会真的画简化场景。简化场景要截图进 CI。截图是合同的照片,文字不是。

现场对照时只改一个变量。同时改版本、封装、通道,归因会消失。消失之后只能靠感觉,感觉正是本书要拆掉的东西。把改动写成一条,测完再写下一条。一条一条,四组对照才用得上。用不上的对照表只是装饰。装饰填不满格子,格子空着就不要标完工。能力包这一格改完,强制 1.0 跑失败用例,不要只在开发机点一次。

一节小结

  • 扩展会漂:适合过渡与画质档,不适合当唯一架构基础。
  • 映射可查:VAO、实例化、深度纹理、MRT 大多进了 2.0 核心。
  • 永久缺口:变换反馈、三维、UBO、整数纹理不是堆扩展能齐的。
  • 入口绑定:扩展函数属于扩展对象与当前上下文。
  • 降级表:失败要对应可感知损失,禁止空 if。
  • 着色器分套:两代 GLSL 分开维护。

下一节对照谁来实现这些合同:完整引擎、2D 引擎,还是裸 API 加独立加载器。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U