Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using emscripten with opengl shaders

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?

like image 634
jmoggr Avatar asked Feb 10 '23 14:02

jmoggr


2 Answers

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.

like image 108
user1906 Avatar answered Feb 12 '23 05:02

user1906


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

like image 31
gman Avatar answered Feb 12 '23 05:02

gman