为什么我在 emscripten 使用“#version 300 es”得到 "unsupported shader version"?

Why do I get "unsupported shader version" using "#version 300 es" at emscripten?

我不知道为什么我在使用最新的 emscripten 1.39 的顶点着色器中使用 #version 300 es 时收到 "unsupported shader version" 错误消息。使用 #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_WINDOW_OPENGL。

SDL_CreateWindowAndRenderer(CANVAS_WIDTH, CANVAS_HEIGHT, SDL_WINDOW_OPENGL, &window, &renderer);

没有你的完整程序,很难看出所有错误。您需要使用正确的选项进行构建,从 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>

如果一切正常,您应该会在浏览器中看到黑色背景上的红色三角形 window。

HTH.