JavaScript — Emscripten OpenGL (3) дает версии ошибок

OS X — Chrome.

Я новичок в OpenGL / emscripten и пытаюсь настроить простой скрипт, который использует WebGL 2, OpenGL 3+ и получает сборку через emscripten в веб-сборку.

Компиляция WebGL 1 / OpenGL 2 работала без проблем. И установка холста на WebGL 2 / OpenGL 3 также, кажется, работает. Когда я проверяю текущую версию, которая работает, она информирует меня об OpenGL 3.0 и WebGL2 (но, может быть, она не используется ..?).

Но emcc по-прежнему кричит об ошибках шейдера, который я предоставляю, который совместим только с версией 3.0+ и, следовательно, подразумевает, что я использую openGL 1/2?

Установка нового контекста через emscripten

EmscriptenWebGLContextAttributes ctxAttrs;
emscripten_webgl_init_context_attributes(&ctxAttrs);
ctxAttrs.alpha = GL_TRUE;
ctxAttrs.depth = GL_TRUE;
ctxAttrs.stencil = GL_TRUE;
ctxAttrs.antialias = 4;
ctxAttrs.premultipliedAlpha = false;
ctxAttrs.preserveDrawingBuffer = false;
ctxAttrs.minorVersion = 0;
ctxAttrs.majorVersion = 2; // WebGL2

this->context = emscripten_webgl_create_context(0, &ctxAttrs);
assert(this->context > 0); // Must have received a valid context.
int res = emscripten_webgl_make_context_current(this->context);
assert(res == EMSCRIPTEN_RESULT_SUCCESS);
assert(emscripten_webgl_get_current_context() == this->context);

шейдеры :

const char *vertexShaderSource = "#version 300 core\n""layout (location = 0) in vec3 aPos;\n""void main()\n""{\n""   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n""}\0";

const char *fragmentShaderSource = "#version 300 core\n""out vec4 FragColor;\n""void main()\n""{\n""   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n""}\n\0";

Когда я делаю журнал текущей версии OpenGL сразу после создания контекста,

printf("OpenGL version supported by this platform : %s\n", glGetString(GL_VERSION));

Я получаю это:

Версия OpenGL, поддерживаемая этой платформой OpenGL ES 3.0 (WebGL 2.0
(OpenGL ES 3.0 Chromium))

Консоль Chrome говорит об этом

ERROR::SHADER::VERTEX::COMPILATION_FAILEDERROR: 0:1: 'core' : invalid version directive
00:53:19.828 index.js:1 ERROR: 0:2: 'layout' : syntax error
00:53:19.829 index.js:1
00:53:19.830 index.js:1 ERROR::SHADER::FRAGMENT::COMPILATION_FAILEDERROR: 0:1: 'core' : invalid version directive
00:53:19.831 index.js:1 ERROR: 0:2: 'out' : storage qualifier supported in GLSL ES 3.00 and above only
00:53:19.832 index.js:1 ERROR: 0:2: '' : No precision specified for (float)
00:53:19.833 index.js:1 ERROR: 0:5: '1.0f' : Floating-point suffix unsupported prior to GLSL ES 3.00
00:53:19.834 index.js:1 ERROR: 0:5: '1.0f' : syntax error
00:53:19.835

Я называю emscripten таким образом, с включенными FULL_ES3 и WEBGL2.

emcc src/main.cpp src/lib/Chart.cpp -s SAFE_HEAP=1 --bind  -s WASM=1 -O3 -o index.js -s LEGACY_GL_EMULATION=0  -s GL_UNSAFE_OPTS=0 --pre-js pre-module.js --post-js post-module.js -s GL_ASSERTIONS=1 -s INVOKE_RUN=0  -std=c++11 -s USE_WEBGL2=1 -s FULL_ES3=1 -s USE_GLFW=3 -s OFFSCREENCANVAS_SUPPORT=1

введите описание изображения здесь

Спасибо!

1

Решение

#version 300 core для OpenGL 3. WebGL не поддерживает это.

#version 300 es для OpenGL ES 3. Это то, что вы хотите.

3

Другие решения

Я просто хотел добавить, что мое решение состояло в том, чтобы изменить библиотеку emscripten как таковую

  1. копия emscripten/src/library_gl.js в ваш проект

  2. отредактируйте свою копию и добавьте эти строки в конец getSource

      getSource: function(shader, count, string, length) {
    
    ...
    
    const isFragmentShader = GLctx.getShaderParameter(GL.shaders[shader], 0x8B4F /* GL_SHADER_TYPE */) === 0x8B30 /* GL_FRAGMENT_SHADER */;
    const header = isFragmentShader ? "#version 300 es\nprecision mediump float;\n" : "#version 300 es\n";
    source = source.replace(/#version.*?\n/, header);
    
    return source;
    },
    
  3. скомпилировать мой код с чем-то вроде

    emcc -std=c++11 -s WASM=1 -s USE_WEBGL2=1 --js-library library_gl.js myprogram.cpp
    

В основном поиск и замена частей GLSL в GLSL ES. Таким образом, мне не нужно изменять шейдеры, в зависимости от шейдера.

Кроме того, если ваш C ++ не печатает компиляцию шейдеров и ошибки ссылок, вы можете добавить их из JavaScript следующим образом.

Перед включением вашего кода emscripten включите этот скрипт

WebGL2RenderingContext.prototype.compileShader = (function(origFn) {
return function(shader) {
origFn.call(this, shader);
const status = this.getShaderParameter(shader, this.COMPILE_STATUS);
if (!status) {
console.error(this.getShaderInfoLog(shader));
}
};
}(WebGL2RenderingContext.prototype.compileShader));

WebGL2RenderingContext.prototype.linkProgram = (function(origFn) {
return function(program) {
origFn.call(this, program);
const status = this.getProgramParameter(program, this.LINK_STATUS);
if (!status) {
console.error(this.getProgramInfoLog(program));
}
};
}(WebGL2RenderingContext.prototype.compileShader));

Это выведет ошибки компиляции на консоль JavaScript и показало бы ошибку

Пример:

WebGL2RenderingContext.prototype.compileShader = (function(origFn) {
return function(shader) {
origFn.call(this, shader);
const status = this.getShaderParameter(shader, this.COMPILE_STATUS);
if (!status) {
console.error(this.getShaderInfoLog(shader));
}
};
}(WebGL2RenderingContext.prototype.compileShader));

WebGL2RenderingContext.prototype.linkProgram = (function(origFn) {
return function(program) {
origFn.call(this, program);
const status = this.getProgramParameter(program, this.LINK_STATUS);
if (!status) {
console.error(this.getProgramInfoLog(program));
}
};
}(WebGL2RenderingContext.prototype.compileShader));

function main() {
const gl = document.createElement("canvas").getContext("webgl2");
if (!gl) {
alert("need webgl2");
return;
}

const vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, `#version 300 core
void main() {
gl_Position = vec4(0);
}
`);
gl.compileShader(vs);
}
main();

Когда я запускаю код выше, я получаю

ERROR: 0:1: 'core' : invalid version directive
1

По вопросам рекламы [email protected]