本节摘要:OpenGL 家族有三大变体——桌面版、面向移动与嵌入式的 OpenGL ES、运行在浏览器沙箱里的 WebGL,它们共享核心理念但能力与坑各不相同。本节给出变体对照与差异清单、EGL 作为窗口系统胶水的角色、以精度限定符与扩展差异为代表的典型移植坑,以及一套「能力探测加降级路径」的工程骨架。跨平台的本质是管理 1.1 节「规范与实现分离」在更大尺度上的账单。
三变体的分化逻辑从各自的运行环境推得出。桌面 OpenGL:插着独立显卡、内存充裕、驱动持续更新——功能全集(4.6 的计算着色器、SPIR-V、DSA 全都可用),代价是不同厂商实现质量参差。OpenGL ES:手机、嵌入式设备,内存带宽与功耗是硬约束——精简 API(ES 3.x 大致对应桌面 3.x 的子集),删掉了双精度、几何着色器等贵重件,纹理压缩格式转向移动端的块格式(3.2 节的 ETC/ASTC 一线)。WebGL:把 ES 搬进浏览器沙箱——出于安全,禁止读取显存里的「别人的数据」(深度纹理等接口受限或需扩展),着色器强制在字符串里以源码提交,1.2 节的运行期编译在网页环境里被放大成「首次加载卡顿」。
| 维度 | 桌面 OpenGL | OpenGL ES | WebGL |
|---|---|---|---|
| 对标能力 | 4.6 全集 | 3.2 约等于桌面 3.3 子集 | 2.0 约等于 ES 3.0 |
| 精度 | 高精度浮点默认 | 必须显式声明精度限定符 | 着色器里也要声明 |
| 几何着色器 | 有 | ES 3.2 起有,实际罕见 | 无 |
| SPIR-V | 4.6 支持 | 走 GLSL 源码 | 源码字符串 |
| 压缩纹理 | BC 系列 | ETC/ASTC | 依浏览器实现 |
| 上下文创建 | 窗口库代劳 | EGL | 浏览器代劳 |
桌面程序用 GLFW/SDL 建上下文(1.3 节),这些库在移动与嵌入式上退场,接替者是 EGL——Khronos 定义的标准接口,负责「在任意窗口系统上创建 OpenGL ES 上下文与绘图表面」。EGL 的五个核心概念:显示(连接到窗口系统)、配置(描述需要的缓冲格式——位深、采样数)、表面(实际的可绘图目标)、上下文(状态机本体)、以及「当前」绑定(把上下文与线程、表面挂接)。移动引擎的启动代码里那一串 eglChooseConfig、eglCreateContext,干的就是 1.3 节 GLFW 三行的活——理解了「窗口库只是替你调 EGL/WGL/GLX」这层关系,跨平台启动代码就从咒语变成了流程。
坑一:精度限定符。 ES 与 WebGL 的着色器里,浮点默认精度在片元着色器是未定义的——不写 precision mediump float; 直接编译失败。桌面代码移植到移动端,这一行是必补的头等舱。更深的层次是精度策略:mediump 在多数移动 GPU 上是半精度,省带宽省功耗,但「大坐标的 mediump 会抖」——4.3 节大场景拆原点的守则在移动端加倍重要。
坑二:扩展的碎片化。 移动端的纹理压缩格式四分五裂(不同 GPU 世代支持不同格式),深度纹理的可用性各不相同。桌面代码里「写死某个格式」的每一处,都是移植时的雷点。1.3 节的「先查再用」纪律在移动端从好习惯升级为生存法则。
坑三:驱动成熟度。 移动 GPU 的驱动更新节奏与桌面不同,某些实现在特定版本的已知 bug 会陪伴一代设备终身。工程对策是「版本加设备指纹的已知问题清单」——听上去原始,但这是移动图形工程的真实日常,也是大厂引擎内部都维护着的东西。
// 能力探测加降级路径的骨架(伪代码) GLint maxTexUnits; glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxTexUnits); bool hasAniso = 查询扩展字符串包含各向异性过滤扩展; bool hasCompute = (glVersion >= 43) || 查询计算着色器扩展; if (hasCompute) 初始化GPU粒子方案; // 首选路径 else 初始化CPU粒子方案; // 降级路径:功能等价 性能打折 if (hasAniso) 设置各向异性4x; // 无则静默跳过 · 效果降级而非功能缺失
骨架的原则:降级路径给「效果档位」而不是「报错退出」——各向异性过滤没有就少一个画质档,计算着色器没有就用 CPU 方案顶上,用户拿到的是不同档位的体验而不是白屏。每个功能点在初始化阶段探测一次、缓存成能力位图,渲染代码按位图走分支——「运行时逐帧查扩展」是把探测当状态机用的经典反例(成本与 4.2 节的 uniform 查询同罪)。
💡 关键直觉:跨平台工程的重心不在「写三套代码」,而在「一套核心 + 两个薄壳」。渲染核心(着色器、管线逻辑、数据结构)按 ES 3.0 的能力交集写,桌面专属能力(几何着色器、SPIR-V)做成增强件按探测启用——能力交集往上兼容容易,往下翻译难。
其一,着色器编译的网页时延:GLSL 以字符串进驱动编译(4.2 节机制不变),移动浏览器上大材质体系的首次编译能把页面卡住数秒。对策是「按需编译」(首屏只编必需的变体)加分帧编译(每帧编一两个,摊平卡顿峰)。其二,上下文丢失:浏览器在资源紧张或驱动重置时会没收上下文——必须监听上下文丢失事件、把所有资源重建逻辑写成可重入的初始化流程。桌面程序从来不用操心的这条,在 WebGL 是生产环境的一等公民,忽略它的网页会在用户切标签页回来时白屏。
移植关过了,最后是架构关:百万物体的场景怎么组织、渲染器的代码怎么分层——下一节把工程骨架摆上终检台。