I'm using emscripten with C++ 17 and WebGL 1.0 to try to draw some basic things in OpenGL. But I can't seem to go past shader compilation. I tried many different types of shaders to eliminate the possibility of shader being the issues.
My assumption is that it is the encoding of the shader text but I can't seem to figure it out. Maybe someone already faced this and can provide a solution.
Compiled with:
-s ENVIRONMENT=web
-s TOTAL_MEMORY=2147483648
-s MODULARIZE=1
-s EXPORT_ES6=1
-s DEMANGLE_SUPPORT=1
-s USE_PTHREADS=0
-s GL_ASSERTIONS=1
-s GL_DEBUG=1
--preload-file ./assets@/
If you're trying to build a minimal program, the file names in assets
are standard.vert
and standard.frag
Vertex shader:
precision mediump float;
attribute vec2 vertPosition;
attribute vec3 vertColor;
varying vec3 fragColor;
void main() {
fragColor = vertColor;
gl_Position = vec4(vertPosition, 0.0, 1.0);
}
Fragment Shader:
precision mediump float;
varying vec3 fragColor;
void main() {
gl_FragColor = vec4(fragColor, 1.0);
}
readFile
std::string readFile( FILE* file )
{
fseek( file, 0L, SEEK_END );
long buffSize = ftell( file );
rewind( file );
std::string buffer( buffSize, '\0' );
fread( (void*)buffer.c_str(), 1, buffSize, file );
return buffer;
}
GLenum ErrorCheckValue = glGetError();
GLint gl_shader_result = GL_FALSE;
int InfoLogLength;
std::string vertex_src;
std::string frag_src;
FILE* fp = nullptr;
fp = fopen( "/standard.vert", "r" );
if ( !fp )
{
emscripten_console_error( "No file found for vertex shader" );
return;
}
vertex_src = readFile( fp );
emscripten_console_logf( "Vertex Shader:\n%s", vertex_src.c_str() );
fclose( fp );
fp = fopen( "/standard.frag", "r" );
if ( !fp )
{
emscripten_console_error( "No file found for fragment shader" );
return;
}
frag_src = readFile( fp );
emscripten_console_logf( "Fragment Shader:\n%s", frag_src.c_str() );
fclose( fp );
const char* vertexCode = vertex_src.c_str();
const char* fragCode = frag_src.c_str();
u32 vertexShaderId = glCreateShader( GL_VERTEX_SHADER );
glShaderSource( vertexShaderId, 1, (const GLchar* const*)vertexCode, NULL );
glCompileShader( vertexShaderId );
// check for vertex shader errors
glGetShaderiv( vertexShaderId, GL_COMPILE_STATUS, &gl_shader_result );
glGetShaderiv( vertexShaderId, GL_INFO_LOG_LENGTH, &InfoLogLength );
if ( InfoLogLength > 0 )
{
std::string msg( InfoLogLength + 1, '\0' );
glGetShaderInfoLog( vertexShaderId, InfoLogLength, NULL, (GLchar*)msg.c_str() );
emscripten_console_error( ( "WASM:: Vertex shader error: " + msg ).c_str() );
return;
}
u32 fragmentShaderId = glCreateShader( GL_FRAGMENT_SHADER );
glShaderSource( fragmentShaderId, 1, (const GLchar* const*)fragCode, NULL );
glCompileShader( fragmentShaderId );
// check for vertex shader errors
glGetShaderiv( fragmentShaderId, GL_COMPILE_STATUS, &gl_shader_result );
glGetShaderiv( fragmentShaderId, GL_INFO_LOG_LENGTH, &InfoLogLength );
if ( InfoLogLength > 0 )
{
std::string msg( InfoLogLength + 1, '\0' );
glGetShaderInfoLog( fragmentShaderId, InfoLogLength, NULL, (GLchar*)msg.c_str() );
emscripten_console_error( ( "WASM:: Fragment shader error: " + msg ).c_str() );
return;
}
u32 shaderProgramId = glCreateProgram();
glAttachShader( shaderProgramId, vertexShaderId );
glAttachShader( shaderProgramId, fragmentShaderId );
glLinkProgram( shaderProgramId );
// Check the program
glGetProgramiv( shaderProgramId, GL_LINK_STATUS, &gl_shader_result );
glGetProgramiv( shaderProgramId, GL_INFO_LOG_LENGTH, &InfoLogLength );
if ( InfoLogLength > 0 )
{
std::string msg( InfoLogLength + 1, '\0' );
glGetProgramInfoLog( shaderProgramId, InfoLogLength, NULL, (GLchar*)msg.c_str() );
emscripten_console_error( ( "WASM:: Shader compilation error: " + msg ).c_str() );
return;
}
emscripten_console_log( "WASM:: Compiled shaders" );
glDetachShader( shaderProgramId, vertexShaderId );
glDetachShader( shaderProgramId, fragmentShaderId );
glDeleteShader( vertexShaderId );
glDeleteShader( fragmentShaderId );
And ofcourse the error: glCompileShader: ERROR: 1:1: '' : syntax error
Thank you for your patience to read all this. Any comment, suggestion or solution are always better none so thank you.
I am not sure if this is due to WebGL 1.0/2.0 being OpenGL ES2/ES3, but in order for WebGL to correctly read the shader code, it needs to the pointer to the char[] pointer containing the shader code.
The correction to be made for vertex and fragment shaders is:
glShaderSource( vertexShaderId, 1, (const GLchar**)&vertexCode, NULL );
glShaderSource( fragmentShaderId, 1, (const GLchar**)&fragCode, NULL );