GLSL WebGL2 Ошибка Многострочные макросы Safari 12 и ios12, WebGL: INVALID_VALUE: shaderSource: строка не ASCII - PullRequest
0 голосов
/ 04 октября 2019

Я пытаюсь скомпилировать шейдер WebGL2 300 es, который использует многострочные макросы препроцессора, как, например, в следующем примере:

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

то же самое относится к

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

или

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

Это работает в последних версиях Chrome и Firefox, но Safari возвращает следующую ошибку, когда я звоню gl.shaderSource:

WebGL: INVALID_VALUE: shaderSource: string not ASCII

Iиспользовал следующий цикл, чтобы проверить, имеет ли какой-либо из кодов символов во входной исходной строке значения больше 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);
}

1 Ответ

1 голос
/ 05 октября 2019

Safari не поддерживает WebGL2 по состоянию на октябрь 2019 года. Это экспериментальная функция только для настольного Safari, и она не проходит даже 20% тестов на соответствие WebGL2. См. Источник . Выполните поиск «НЕ РЕАЛИЗОВАНО», и вы увидите, что более 80 функций API WebGL2 не реализованы, а всего лишь один пример того, сколько работы не выполнено.

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 это работает для меня. Протестировано на Macbook Pro 2014 года с MacOS 10.14.6 и iPhoneX с iOS 13.1

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 для просмотра вашего файла. </p>

Что касается #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 - это API на основе C)

...