着色器自动转换:桌面 GLSL 到 GLSL ES 的处理
为什么需要转换
Minecraft Java 生态的所有光影包都是用桌面 OpenGL 的 GLSL 写的。直接把这些着色器丢到 Android OpenGL ES 上会遇到三类编译错误:
layout(binding)语法在 ES 中不存在- 某些桌面版 version 指令 ES 不认识
- ES 要求显式精度声明,桌面 GLSL 不需要
如果没有自动转换能力,几乎所有现成的光影包都无法直接在 MobileGlues 上运行,开发者必须逐个手动改写——工作量极大,而且光影更新一次就要改一次。
MobileGlues 的自动转换逻辑
MobileGlues 在着色器进入 OpenGL ES 驱动之前,自动完成以下处理:
- 移除
layout(binding)语法块 - 处理 version 指令(桌面版
#version 430 core转换为 ES 兼容版本) - 注入精度声明:
precision highp float; precision highp int; - 把 GLSL 函数名、内置变量等转换成 ES 等价形式
整个过程对光影包作者和玩家都是透明的——不需要做任何特殊处理就能在 MobileGlues 上使用现成的桌面端光影包。
转换不能解决的问题
自动转换解决的是语法层面的差异。如果一个光影包使用了桌面 OpenGL 特有的行为(比如桌面端独有的帧缓冲格式、特定的渲染管线特性),转换层无法自动抹平。这种情况下光影可能能编译通过但渲染结果不正确,或者出现图形 glitch。这也是为什么光影兼容性需要逐个测试而不是"理论上全兼容"。
给光影开发者的平台宏
MobileGlues 自 V1.2.6 起向着色器注入两个平台宏,让开发者可以针对 MobileGlues 做条件编译:
#define MG_MOBILEGLUES // 表示处于 MobileGlues 环境
#define MG_MOBILEGLUES_VERSION 2000 // 版本号(2000 = V2.0.0)
用法示例:
#ifdef MG_MOBILEGLUES
#if MG_MOBILEGLUES_VERSION >= 2000
// MobileGlues V2.0.0 及以上的逻辑
#else
// MobileGlues V2.0.0 以下的逻辑
#endif
#else
// 桌面端的逻辑
#endif
详细的开发者指南见 光影开发者。