为啥我在 emscripten 使用“#version 300 es”得到“不支持的着色器版本”?
Posted
技术标签:
【中文标题】为啥我在 emscripten 使用“#version 300 es”得到“不支持的着色器版本”?【英文标题】:Why do I get "unsupported shader version" using "#version 300 es" at emscripten?为什么我在 emscripten 使用“#version 300 es”得到“不支持的着色器版本”? 【发布时间】:2020-05-12 15:46:55 【问题描述】:我不知道为什么我在使用最新 emscripten 1.39 的顶点着色器中使用 #version 300 es
会收到“不支持的着色器版本”错误消息。使用#version 100
可以正常工作。
const GLchar* vertex_shader_code[] =
"#version 300 es\n"
"precision mediump float; \n"
"void main() \n"
"gl_Position = vec4(0.0, 0.0, 0.0, 1.0); \n"
" \n"
;
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
SDL_version compiled;
SDL_version linked;
SDL_VERSION(&compiled);
SDL_GetVersion(&linked);
printf("Compiled SDL version: %d.%d.%d\n", compiled.major, compiled.minor, compiled.patch);
printf("Linked SDL version: %d.%d.%d\n", linked.major, linked.minor, linked.patch);
SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindowAndRenderer(CANVAS_WIDTH, CANVAS_HEIGHT, 0, &window, &renderer);
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_RenderClear(renderer);
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, vertex_shader_code, 0);
glCompileShader(vertex_shader);
auto compile_success = 0;
auto compile_info_lenght = 0;
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &compile_success);
if(compile_success == GL_FALSE)
glGetShaderiv(vertex_shader, GL_INFO_LOG_LENGTH, &compile_info_lenght);
std::string vertex_shader_log(compile_info_lenght, ' ');
glGetShaderInfoLog(vertex_shader, compile_info_lenght, NULL, &vertex_shader_log[0]);
int n = vertex_shader_log.length();
char char_array[n + 1];
strcpy(char_array, vertex_shader_log.c_str());
printf("%s\n", char_array);
glDeleteShader(vertex_shader);
return 0;
对于构建我使用emcc -s main.cpp -o index.html --shell-file shell.html -s USE_SDL=2 -s FULL_ES3=1
消息:
Compiled SDL version: 2.0.9
Linked SDL version: 2.0.9
ERROR: unsupported shader version
我做错了什么?
【问题讨论】:
你为什么在SDL_Init()
之前打电话给SDL_GL_SetAttribute()
?
嗨@genpfault,我现在直接在 SDL_Init() 之后尝试了它,但不幸的是同样的错误。
另外,如果您要使用 OpenGL ES,为什么还要靠近 SDL_Renderer 的东西?您不能(正式)在两者之间进行互操作,无法查询 SDL_Renderer 的 GL 状态,它可能会或可能不会破坏。
如果您还指定-s MAX_WEBGL_VERSION=2
,有什么变化吗?
可能还需要SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES)
来强制 SDL 使用更多 EGL-y/GLES-y 代码路径。 可能。取决于 Emscripten 端口人员在这一周对 SDL 做了多少暴力 :)
【参考方案1】:
如果没有完整的程序,就很难看到所有错误。您需要使用正确的选项进行构建,从 javascript 正确调用您的 WASM 模块,并在 SDL 和 OpenGL 中正确设置所有内容。
这是一个工作示例:
// main.cpp
#include <stdio.h>
#include <stdarg.h>
#include <emscripten.h>
#include <SDL.h>
#include <SDL_opengles2.h>
SDL_Window *sdlWindow;
static const char *vertexShaderSource[] =
"#version 300 es\n"
"in vec4 position;\n"
"void main(void) \n"
" gl_Position = vec4(position.xyz, 1.0);\n"
"\n"
;
static const char *fragmentShaderSource[] =
"#version 300 es\n"
"precision mediump float;\n"
"out vec4 fragColor;\n"
"void main(void) \n"
" fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
"\n"
;
static void
fatal(const char *const fmt, ...)
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
printf("\n");
va_end(args);
for (;;)
SDL_Delay(1000);
static GLuint
compileShader(GLenum shaderType, const char **shaderSource)
GLuint shdr = glCreateShader(shaderType);
glShaderSource(shdr, 1, shaderSource, nullptr);
glCompileShader(shdr);
GLint isCompiled = 0;
glGetShaderiv(shdr, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
GLint maxLength = 0;
glGetShaderiv(shdr, GL_INFO_LOG_LENGTH, &maxLength);
char *errorString = (char *) malloc(maxLength + 1);
glGetShaderInfoLog(shdr, maxLength, &maxLength, errorString);
fatal("Compile failed: %s", errorString);
return shdr;
static void
_set_SDL_Attribute(SDL_GLattr attr, int value, const char *attrName)
#define set_SDL_Attribute(x, v) _set_SDL_Attribute(x, v, #x)
if (SDL_GL_SetAttribute(attr, value) != 0)
fatal("SDL set attrib failed: %s, %s", attrName, SDL_GetError());
static void
setupSDL(void)
if (SDL_Init(SDL_INIT_VIDEO) != 0)
fatal("Unable to init SDL: %s", SDL_GetError());
SDL_version compiled;
SDL_version linked;
SDL_VERSION(&compiled);
SDL_GetVersion(&linked);
printf("Compiled SDL version: %d.%d.%d\n",
compiled.major, compiled.minor, compiled.patch);
printf("Linked SDL version: %d.%d.%d\n",
linked.major, linked.minor, linked.patch);
set_SDL_Attribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
set_SDL_Attribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
set_SDL_Attribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
set_SDL_Attribute(SDL_GL_DOUBLEBUFFER, 1);
set_SDL_Attribute(SDL_GL_DEPTH_SIZE, 24);
SDL_Renderer *renderer;
if (SDL_CreateWindowAndRenderer(400, 400, SDL_WINDOW_OPENGL,
&sdlWindow, &renderer) < 0)
fatal("Unable to create windown: %s", SDL_GetError());
SDL_GLContext glContext = SDL_GL_CreateContext(sdlWindow);
if (glContext == NULL)
fatal("Unable to create context: %s", SDL_GetError());
printf("GL Version=%s\n", glGetString(GL_VERSION));
printf("GLSL Version=%s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
static void
setupOpenGL(void)
GLuint shaderProgram = glCreateProgram();
GLuint vertexShader = compileShader(GL_VERTEX_SHADER, vertexShaderSource);
GLuint fragmentShader = compileShader(GL_FRAGMENT_SHADER,
fragmentShaderSource);
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
glUseProgram(shaderProgram);
static const GLfloat vertices[] = 0.0f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f ;
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof (vertices), vertices,
GL_STATIC_DRAW);
glEnableVertexAttribArray(0); // Input offset is zero.
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Black
static void
mainLoop(void)
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
SDL_GL_SwapWindow(sdlWindow);
int
main(void)
setupSDL();
setupOpenGL();
emscripten_set_main_loop(mainLoop, 0, true);
return 0;
使用这些选项进行编译:
emcc main.cpp -O3 -Wall -Wextra -Werror -s WASM=1 -s USE_SDL=2 -s MAX_WEBGL_VERSION=2 -s MIN_WEBGL_VERSION=2 -o foo.js
像这样从 HTML 启动:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<h1>Wasm Test Page</h1>
<canvas id=canvas width=400 height=400 oncontextmenu="event.preventDefault()"></canvas>
<script>var Module = canvas: document.getElementById('canvas') ; </script>
<script src="foo.js"></script>
</body>
</html>
如果一切正常,您应该会在浏览器窗口中看到黑色背景上的红色三角形。
HTH。
【讨论】:
【参考方案2】:对于有同样问题的人,解决方案是 SDL_WINDOW_OPENGL。
SDL_CreateWindowAndRenderer(CANVAS_WIDTH, CANVAS_HEIGHT, SDL_WINDOW_OPENGL, &window, &renderer);
【讨论】:
以上是关于为啥我在 emscripten 使用“#version 300 es”得到“不支持的着色器版本”?的主要内容,如果未能解决你的问题,请参考以下文章
emscripten:我该如何解决 UnboundTypeError
您如何在 emscripten 中迭代 Box2D 中的实体列表?