diff --git a/README.md b/README.md index 395cd0f..5c18a71 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,40 @@ **MobileGlues**, which stands for "(on) Mobile, GL uses ES", is a GL implementation running on top of host OpenGL ES 3.x (best on 3.2, minimum 3.0), with running Minecraft: Java Edition in mind. +# For Shader Developers + +1. MobileGlues automatically: + - Converts desktop GLSL → GLSL ES + - Removes `layout(binding)` syntax + - Handles version directives + - Always declare precision explicitly: + ```glsl + precision highp float; + precision highp int; + ``` + +2. MobileGlues (since V1.2.6.0) injects these macros into your shaders: + ```glsl + #define MG_MOBILEGLUES // Indicates MobileGlues environment + #define MG_MOBILEGLUES_VERSION 1260 // Version number (e.g. 1260 = V1.2.6) + ``` + + Use these macros for platform-specific logic: + ```glsl + #ifdef MG_MOBILEGLUES + #if MG_MOBILEGLUES_VERSION >= 1270 + // Logic for MobileGlues (version >= V1.2.7) + #else + // Logic for MobileGlues (version < V1.2.7) + #endif + #else + // ... + #endif + ``` + +3. If encountering issues: + - Enable `Ignore shader/program error`, and check the logs (located at `/sdcard/MG/latest.log`). + # License MobileGlues is licensed under **GNU LGPL-2.1 License**. diff --git a/src/main/cpp/gl/glsl/glsl_for_es.cpp b/src/main/cpp/gl/glsl/glsl_for_es.cpp index 158ca39..5f7bf8d 100644 --- a/src/main/cpp/gl/glsl/glsl_for_es.cpp +++ b/src/main/cpp/gl/glsl/glsl_for_es.cpp @@ -525,6 +525,28 @@ vec4 GI_TemporalFilter() { glsl.insert(main_loc, "\n" + GI_TemporalFilter + "\n"); } +void inject_mg_macro_definition(std::string& glslCode) { + std::stringstream macro_stream; + macro_stream << "\n#define MG_MOBILEGLUES\n" + << "#define MG_MOBILEGLUES_VERSION " + << MAJOR << MINOR << REVISION << PATCH << "\n"; + std::string macro_definitions = macro_stream.str(); + + size_t lastExtensionPos = glslCode.rfind("#extension"); + size_t insertionPos = 0; + + if (lastExtensionPos != std::string::npos) { + size_t nextNewline = glslCode.find('\n', lastExtensionPos); + insertionPos = (nextNewline != std::string::npos) ? nextNewline + 1 : glslCode.length(); + } else { + size_t firstNewline = glslCode.find('\n'); + insertionPos = (firstNewline != std::string::npos) ? firstNewline + 1 : 0; + } + + glslCode.insert(insertionPos, macro_definitions); +} + + std::string preprocess_glsl(const std::string& glsl) { std::string ret = glsl; // Remove lines beginning with `#line` @@ -540,10 +562,13 @@ std::string preprocess_glsl(const std::string& glsl) { // GI_TemporalFilter injection inject_temporal_filter(ret); - + // textureQueryLod injection inject_textureQueryLod(ret); + // MobileGlues macros injection + inject_mg_macro_definition(ret); + return ret; } diff --git a/src/main/cpp/gles/loader.cpp b/src/main/cpp/gles/loader.cpp index 7896392..e7620a5 100644 --- a/src/main/cpp/gles/loader.cpp +++ b/src/main/cpp/gles/loader.cpp @@ -145,10 +145,6 @@ void InitGLESCapabilities() { GLES.glGetIntegerv(GL_MAJOR_VERSION, &g_gles_caps.major); GLES.glGetIntegerv(GL_MINOR_VERSION, &g_gles_caps.minor); -// int has_GL_EXT_buffer_storage = 0; -// int has_GL_ARB_timer_query = 0; -// int has_GL_QCOM_texture_lod_bias = 0; - GLint num_es_extensions = 0; GLES.glGetIntegerv(GL_NUM_EXTENSIONS, &num_es_extensions); LOG_D("Detected %d OpenGL ES extensions.", num_es_extensions) @@ -184,6 +180,8 @@ void InitGLESCapabilities() { g_gles_caps.GL_EXT_texture_norm16 = 1; } else if (strcmp(extension, "GL_EXT_texture_rg") == 0) { g_gles_caps.GL_EXT_texture_rg = 1; + } else if (strcmp(extension, "GL_EXT_texture_query_lod") == 0) { + g_gles_caps.GL_EXT_texture_query_lod = 1; } } else { LOG_D("(nullptr)") diff --git a/src/main/cpp/gles/loader.h b/src/main/cpp/gles/loader.h index 95a0a00..fd82de8 100644 --- a/src/main/cpp/gles/loader.h +++ b/src/main/cpp/gles/loader.h @@ -157,6 +157,7 @@ struct gles_caps_t { int GL_OES_depth_texture_float; int GL_EXT_texture_norm16; int GL_EXT_texture_rg; + int GL_EXT_texture_query_lod; }; extern struct gles_caps_t g_gles_caps;