【问题标题】:Is there a way to test the GLSL-ES version in the shader?有没有办法在着色器中测试 GLSL-ES 版本?
【发布时间】:2017-04-27 19:46:01
【问题描述】:

shadertoy 等网络工具中,我的片段着色器源包含在我无法控制或查看的 main() 中。如果我分发一些 GLSL 库也是一样的。

我的问题是确保 webGL2 和 1 之间的兼容性:如果浏览器或操作系统仅支持 WebGL1,我想编写 GLSL 后备来模拟缺少的内置 webGL2。 -> 有没有办法从着色器测试当前的 webGL/GLSL 版本,就像我们为扩展的可用性所做的那样?

(顺便说一句,由于语言中包含了一些扩展,测试扩展变得越来越复杂:例如,尽管有功能,但 GL_EXT_shader_texture_lod 在 webGL2 中未定义。因此能够测试 GLSL 版本至关重要。)

【问题讨论】:

    标签: webgl glsles webgl-extensions webgl2


    【解决方案1】:

    AFAICT 没有很好的测试方法。规范说预处理器宏 __VERSION__ 将设置为整数 300 对于 GLSL 版本 3.00 的版本所以

    #if __VERSION__ == 300
       // use 300 es stuff
    #else  
       // use 100 es tuff
    #endif
    

    问题在于 WebGL2 在使用 300 es 着色器时,着色器的第一行必须是

     #version 300 es
    

    所以你不能这样做

     #if IMAGINARY_WEBGL2_FLAG
         #version 300 es         // BAD!! This has to be the first line
         ...
     #else 
         ...
     #
    

    所以,鉴于您已经必须更新第一行,为什么不只使用 2 个着色器,一个用于 WebGL1,另一个用于 WebGL2。否则所有主要引擎都会生成它们的着色器,所以如果你想沿着这条路走下去,在你的代码中生成 WebGL1 或 WebGL2 应该是非常简单的。

    首先,如果您可以使用 WebGl1,则没有理由使用 WebGL2 着色器功能,如果您正在使用 WebGL2 功能,那么它们就不再是同一个着色器了,是吗?他们需要不同的设置、不同的输入等等……

    假设我们可以在 GLSL 中完成这一切,您希望它是什么样子?

     // IMAGINARY WHAT IF EXAMPLE ....
    
     #if WEBGL2
       #version 300 es
       #define texture2D texture
       #define textureCube texture
     #else
       #define in varying
       #define out varying
     #endif
    
     in vec4 position;
     in vec2 texcoord;
    
     out vec2 v_texcoord;
    
     uniform sampler2D u_tex;
     uniform mat4 u_matrix;
    
     void main() {
        gl_Position = u_matrix * (position + texture2D(u_tex, texcoord));
        v_texcoord = texcoord;
     }
    

    假设您想这样做。你可以用 JavaScript 做(不建议这样,只是展示一个例子)

     const webgl2Header = `#version 300 es
       #define texture2D texture
       #define textureCube texture
     `;
     const webglHeader = `
       #define in varying
       #define out varying
     `;
    
     function prepShader(gl, source) {
       const isWebGL2 = gl.texImage3D !== undefined
       const header = isWebGL2 ? webgl2Header : webglHeader;
       return header + source;
     }
    
     const vs = `
     in vec4 position;
     in vec2 texcoord;
    
     out vec2 v_texcoord;
    
     uniform sampler2D u_tex;
     uniform mat4 u_matrix;
    
     void main() {
        gl_Position = u_matrix * (position + texture2D(u_tex, texcoord));
        v_texcoord = texcoord;
     }
     `;
    
     const vsSrc = prepSource(gl, vs);
    

    您可以根据需要使 JavaScript 替换变得复杂。例如this library

    【讨论】:

    • 谢谢,VERSION 是我可以使用的标志!但是您的其他建议对我不起作用:请记住,我在第三方 webGl 应用程序中,我只能访问着色器。不过,这面旗帜应该可以。通常,要进行一些仿真,或者至少是简化版本,在手机上工作而不是“不编译”,并且在 PC 上仍然具有完整的外观。
    猜你喜欢
    • 2015-05-09
    • 2012-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多