有没有办法在着色器中测试 GLSL-ES 版本?
Is there a way to test the GLSL-ES version in the shader?
在 shadertoy 等网络工具中,我的片段着色器源包含在我无法控制或看到的 main() 中。如果我正在分发一些 GLSL 库,那将是相同的。
我的问题是确保 webGL2 和 1 之间的兼容性:如果浏览器或 OS 仅支持 WebGL1,我想编写 GLSL 回退来模拟缺少的内置 webGL2。
->
有没有办法从着色器测试当前的 webGL/GLSL 版本,就像我们为扩展的可用性所做的那样?
( 顺便说一句,测试扩展变得越来越复杂,因为语言中包含一些扩展:例如,尽管函数存在,但 webGL2 中未定义 GL_EXT_shader_texture_lod。因此能够测试 GLSL 版本至关重要。 )
AFAICT 没有好的测试方法。规范说预处理器宏 __VERSION__
将设置为 GLSL 3.00 版的整数 300
中的版本
#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
在 shadertoy 等网络工具中,我的片段着色器源包含在我无法控制或看到的 main() 中。如果我正在分发一些 GLSL 库,那将是相同的。
我的问题是确保 webGL2 和 1 之间的兼容性:如果浏览器或 OS 仅支持 WebGL1,我想编写 GLSL 回退来模拟缺少的内置 webGL2。 -> 有没有办法从着色器测试当前的 webGL/GLSL 版本,就像我们为扩展的可用性所做的那样?
( 顺便说一句,测试扩展变得越来越复杂,因为语言中包含一些扩展:例如,尽管函数存在,但 webGL2 中未定义 GL_EXT_shader_texture_lod。因此能够测试 GLSL 版本至关重要。 )
AFAICT 没有好的测试方法。规范说预处理器宏 __VERSION__
将设置为 GLSL 3.00 版的整数 300
中的版本
#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