GLSL WebGL2 错误多行宏 Safari 12 和 ios12,WebGL:INVALID_VALUE:shaderSource:字符串不是 ASCII

GLSL WebGL2 Error Multi-line Macros Safari 12 and ios12, WebGL: INVALID_VALUE: shaderSource: string not ASCII

我正在尝试编译一个使用多行预处理器宏的 WebGL2 300 es 着色器,例如这个玩具示例:

#define FOO() \
    do { } while (false);

同样适用

#define FOO \
    do { } while (false);

    #define FOO() \
        do { } while (false); \

这适用于最新版本的 Chrome 和 Firefox,但 Safari returns 在我调用 gl.shaderSource 时出现以下错误:

WebGL: INVALID_VALUE: shaderSource: string not ASCII

我使用以下循环检查输入源字符串中是否有任何字符代码的值大于 127:

for (char c = 0; c < src.length; c += 1) {
    if (src.charCodeAt(c) > 127) {
       console.error(src.charAt(c), src.charCodeAt(c));
    }
}

循环没有打印错误。 此外,当我在我的文本编辑器中启用不可见字符时,我没有看到无关的隐藏字符。

Safari 的 GLSL 编译器是否根本无法处理反斜杠字符?

这是一个由于反斜杠而失败的最小示例片段着色器:

#version 300 es
precision highp float;

out vec4 fragColor;

    #define FOO() \
        true

void main() {
    fragColor = vec4(1.0);
}

Safari 在 2021 年 9 月发布的 Safari 15 中发布了 WebGL2

Safari 似乎终于获得了 WebGL2。至少截至 2020 年 9 月,Safari 技术预览版 113 支持 WebGL2。

截至 2019 年 10 月,Safari 不支持 WebGL2。它只是桌面版 Safari 上的一项实验性功能,甚至没有通过 20% 的 WebGL2 一致性测试。 See the source。搜索“NOT IMPLEMENTED”,您会看到超过 80 个 WebGL2 API 函数未实现,这只是未完成工作的一个例子。

void WebGL2RenderingContext::uniform1ui(WebGLUniformLocation*, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniform1ui()");
}

void WebGL2RenderingContext::uniform2ui(WebGLUniformLocation*, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniform2ui()");
}

void WebGL2RenderingContext::uniform3ui(WebGLUniformLocation*, GC3Duint, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniform3ui()");
}

void WebGL2RenderingContext::uniform4ui(WebGLUniformLocation*, GC3Duint, GC3Duint, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniform4ui()");
}

void WebGL2RenderingContext::uniform1uiv(WebGLUniformLocation*, Uint32List&&, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniform1uiv()");
}

void WebGL2RenderingContext::uniform2uiv(WebGLUniformLocation*, Uint32List&&, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniform2uiv()");
}

void WebGL2RenderingContext::uniform3uiv(WebGLUniformLocation*, Uint32List&&, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniform3uiv()");
}

void WebGL2RenderingContext::uniform4uiv(WebGLUniformLocation*, Uint32List&&, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniform4uiv()");
}

void WebGL2RenderingContext::uniformMatrix2x3fv(WebGLUniformLocation*, GC3Dboolean, Float32List&&, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniformMatrix2x3fv()");
}

void WebGL2RenderingContext::uniformMatrix3x2fv(WebGLUniformLocation*, GC3Dboolean, Float32List&&, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniformMatrix3x2fv()");
}

void WebGL2RenderingContext::uniformMatrix2x4fv(WebGLUniformLocation*, GC3Dboolean, Float32List&&, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniformMatrix2x4fv()");
}

void WebGL2RenderingContext::uniformMatrix4x2fv(WebGLUniformLocation*, GC3Dboolean, Float32List&&, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniformMatrix4x2fv()");
}

void WebGL2RenderingContext::uniformMatrix3x4fv(WebGLUniformLocation*, GC3Dboolean, Float32List&&, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniformMatrix3x4fv()");
}

void WebGL2RenderingContext::uniformMatrix4x3fv(WebGLUniformLocation*, GC3Dboolean, Float32List&&, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] uniformMatrix4x3fv()");
}

void WebGL2RenderingContext::vertexAttribI4i(GC3Duint, GC3Dint, GC3Dint, GC3Dint, GC3Dint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] vertexAttribI4i()");
}

void WebGL2RenderingContext::vertexAttribI4iv(GC3Duint, Int32List&&)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] vertexAttribI4iv()");
}

void WebGL2RenderingContext::vertexAttribI4ui(GC3Duint, GC3Duint, GC3Duint, GC3Duint, GC3Duint)
{
    LOG(WebGL, "[[ NOT IMPLEMENTED ]] vertexAttribI4ui()");
}

否则在 WebGL1 中它对我有用。在装有 MacOS 10.14.6 的 2014 Macbook Pro 和装有 iOS 13.1

的 iPhoneX 上测试

const fs = `
precision highp float;

    #define FOO() \
        true

void main() {
    gl_FragColor = vec4(1.0);
}
`;

const gl = document.createElement('canvas').getContext('webgl');
const sh = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(sh, fs);
gl.compileShader(sh);
const success = gl.getShaderParameter(sh, gl.COMPILE_STATUS);
if (success) {
  console.log('pass: shader compiled successfully');
} else {
  console.error('fail: shader failed to compile');
}

建议您测试 >= 32 和 <= 127 或使用十六进制编辑器或 hexdump 查看您的文件。

至于#define本身,JavaScript中的#define确实没有太大意义,因为JavaScript,不像C/C++有很好的字符串操作。

const subs = {
  width: 100,
  height: 200,
}

const fs = `
void main() {
  vec2 thingSize = vec2(${subs.width}, ${subs.height});
}
`;

console.log(fs);

甚至

function preprocess(s, subs) {
  const re = new RegExp(Object.keys(subs).join('|'), 'g');
  return s.replace(re, m => subs[m] || '');
}

const subs = { WIDTH: 123, HEIGHT: 456 };
const fs = preprocess(`
void main() {
  vec2 thingSize = vec2(WIDTH, HEIGHT);
}
`, subs);

console.log(fs);

并不是说你不应该使用 #define 只是指出在 JavaScript 中有很多简单的方法来操作字符串,因此 GLSL 预处理器并不像它在C(OpenGL是基于C的API)