I am having trouble getting emscripten to work with openGL shaders. The project compiles just fine with both emscripten and gcc but fails when I try to run the emscripten output.
The errors I get from compiling the vertex shader:
ERROR: 0:1: 'core' : invalid version directive
ERROR: 0:3: 'layout' : syntax error
The errors I get from compiling the fragment shader:
ERROR: 0:1: 'core' : invalid version directive
ERROR: 0:3: 'in' : storage qualifier supported in GLSL ES 3.00 only
ERROR: 0:3: '' : No precision specified for (float)
ERROR: 0:5: 'out' : storage qualifier supported in GLSL ES 3.00 only
ERROR: 0:5: '' : No precision specified for (float)
I'm compiling this project with the command:
em++ src/*.cpp -Iinclude/ -o test.html -std=c++11 -s USE_GLFW=3 -s FULL_ES3=1
Vertex shader source:
#version 330 core
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 in_color;
uniform mat4 model;
uniform mat4 projection;
out vec3 out_color;
void main()
{
gl_Position = projection * model * vec4(position, 1.0f);
out_color = in_color;
}
Fragment shader source:
#version 330 core
in vec3 out_color;
out vec4 color;
void main()
{
color = vec4(out_color, 1.0);
}
The shaders are loaded as char arrays from output provided by xxd -i
I'm working in c++11 on linux. The program works just fine when I run it natively and I've tried running the emscripten output in both Firefox and chromium.
It seems to be a problem between different versions. Is there a way to make emscripten work with what I currently have, or do I have to write my shaders differently? And if I do have to rewrite my shaders, how should I write them?
The shader code will have to be WebGL shader code to work on the browser. I don't think emscripten converts shader code (GLSL 3.3 in this case) to a GLSL ES 1.0 that is compatible with webGL.
You'll have to use attribute
instead of in
in the vertex shader, varying
for out/in in the vertex/fragment shaders and use gl_FragColor
as the output variable of the fragment shader. layout
is not supported either, and the variables need a precision definition. Check the WebGL cheat sheet here.
In current emscripten you can use WebGL2 and GLSL ES 3.00. You need to change your #version
lines to
#version 300 es
You will also need to add a default precision to your fragment shaders.
If it was me I'd just wrap my code to glShaderSource
to be something like
GLint shaderSourceWrapper(GLint shader, const std::string src) {
#ifdef __EMSCRIPTEN__
// replace '#version.*' with '#version 300 es'
// if it's a fragment shader add 'precision highp float'
// do anything else relevant like warn if there are
// unsupported #extension directives
#endif
glShaderSource(shader, ... )
Or even do that at the JavaScript level like this
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With