Emscripten 无法编译着色器
Posted
技术标签:
【中文标题】Emscripten 无法编译着色器【英文标题】:Emscripten fails to compile shader 【发布时间】:2021-12-31 21:18:25 【问题描述】:我正在使用带有 C++ 17 和 WebGL 1.0 的 emscripten 来尝试在 OpenGL 中绘制一些基本的东西。但我似乎无法超越着色器编译。我尝试了许多不同类型的着色器来消除着色器成为问题的可能性。
我的假设是它是着色器文本的编码,但我似乎无法弄清楚。也许有人已经面临这个问题并且可以提供解决方案。
编译:
-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@/
如果您尝试构建一个最小程序,assets
中的文件名是standard.vert
和standard.frag
着色器
顶点着色器:
precision mediump float;
attribute vec2 vertPosition;
attribute vec3 vertColor;
varying vec3 fragColor;
void main()
fragColor = vertColor;
gl_Position = vec4(vertPosition, 0.0, 1.0);
片段着色器:
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 );
当然还有错误:glCompileShader: ERROR: 1:1: '' : syntax error
感谢您耐心阅读所有内容。任何意见、建议或解决方案总是更好,所以谢谢。
【问题讨论】:
readFile
是做什么的?您的着色器文件是否可能有 BOM?以十六进制打印它们的前 3 个字节。
我无法正确显示十六进制。我用这行代码来打印它。 emscripten_console_logf( "Vert: %.2x, %.2x, %.2x", vertex_src[0], vertex_src[1], vertex_src[2] );
输出为:70, 72, 65
70h, 72h, 65h 是'pre'
这是precision mediump float;
的一部分所以没错。
【参考方案1】:
我不确定这是否是因为 WebGL 1.0/2.0 是 OpenGL ES2/ES3,但为了让 WebGL 正确读取着色器代码,它需要指向包含着色器代码的 char[] 指针的指针。
对顶点和片段着色器的修正是:
glShaderSource( vertexShaderId, 1, (const GLchar**)&vertexCode, NULL );
glShaderSource( fragmentShaderId, 1, (const GLchar**)&fragCode, NULL );
【讨论】:
以上是关于Emscripten 无法编译着色器的主要内容,如果未能解决你的问题,请参考以下文章