编译着色器后程序停止绘制

JET*_*ETM 8 opengl-es opengl-es-2.0 egl emscripten

我正在研究要编译为WASM并在浏览器中显示图像的C程序。该程序的重​​点是学习使用EGL进行设置,因此,我对涉及SDL,GLFW等的任何答案都不感兴趣。

此代码可将屏幕清除为蓝色(我省略了错误检查以减小尺寸):

#include <GLES2/gl2.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "emscripten.h"

struct Environment
{
    EGLint majorVersion;
    EGLint minorVersion;

    EGLDisplay display;
    EGLSurface surface;
};

static struct Environment g_env = {};

bool initGL(struct Environment* env)
{
    env->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

    eglInitialize(env->display, &env->majorVersion, &env->minorVersion);

    EGLint numConfigs = 0;
    EGLint attribList[] = 
    {
        EGL_RED_SIZE, 5,
        EGL_GREEN_SIZE, 6,
        EGL_BLUE_SIZE, 5,
        EGL_DEPTH_SIZE, 1,
        EGL_NONE
    };
    EGLConfig config;
    eglChooseConfig(env->display, attribList, &config, 1, &numConfigs);

    env->surface = eglCreateWindowSurface(env->display, config, 0, NULL);

    static const EGLint contextAttribList[] = 
    {
        EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE
    };
    EGLContext context = eglCreateContext(env->display, config, EGL_NO_CONTEXT, contextAttribList);


    eglMakeCurrent(env->display, env->surface, env->surface, context);


    glClearColor(0.0f, 0.0f, 1.0f, 1.0f);


    return true;
}

void draw()
{
    glViewport(0, 0, 300, 150);
    glClear(GL_COLOR_BUFFER_BIT);
    eglSwapBuffers(g_env.display, g_env.surface);
}

int main(int argc, char *argv[])
{
    if (!initGL(&g_env))
    {
        return 1;
    }
    emscripten_set_main_loop(clearScreen, 0, 1);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,一旦在后面添加以下内容glClearColor(...),浏览器将不再显示蓝屏:

const GLuint vertex_shader = load_shader(GL_VERTEX_SHADER, VERTEX_SHADER);
const GLuint fragment_shader = load_shader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
Run Code Online (Sandbox Code Playgroud)

我怀疑着色器代码根本与问题无关,只是为了以防万一,这是的代码load_shader,取自OpenGL ES 2书(省略了错误检查)

GLuint load_shader ( GLenum type, const char *shaderSrc )
{
   GLuint shader;
   GLint compiled;

   // Create the shader object
   shader = glCreateShader ( type );

   // Load the shader source
   glShaderSource ( shader, 1, &shaderSrc, NULL );

   // Compile the shader
   glCompileShader ( shader );

   // Check the compile status
   glGetShaderiv ( shader, GL_COMPILE_STATUS, &compiled );

   return shader;
}
Run Code Online (Sandbox Code Playgroud)

着色器本身:

char VERTEX_SHADER[] =  
  "attribute vec4 vPosition;    \n"
  "void main()                  \n"
  "{                            \n"
  "   gl_Position = vPosition;  \n"
  "}                            \n";

char FRAGMENT_SHADER[] =  
  "precision mediump float;\n"\
  "void main()                                  \n"
  "{                                            \n"
  "  gl_FragColor = vec4 ( 1.0, 0.0, 0.0, 1.0 );\n"
  "}   
Run Code Online (Sandbox Code Playgroud)

这是我的编译方式:

EMSCRIPTEN_OPTS = \
-s WASM=1 \
-s FULL_ES2=1 \
-s MODULARIZE=1
${EMCC} main_web.c -o hello.js ${EMSCRIPTEN_OPTS}
Run Code Online (Sandbox Code Playgroud)

glGetError() 没有返回错误代码。

这是我的HTML:

<html>
<body>
<p id="output" />
<canvas id="canvas"></canvas>
<script type="application/javascript" src="hello.js"></script>
<script type="application/javascript">
    Module({
        canvas: (() => document.getElementById('canvas'))(),
        print: (() => {
            var element = document.getElementById('output');
            return function(text) {
                element.innerHTML += text + "<br>";
            };
        })()
    })
</script>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)

为何仅加载着色器时为何停止清除屏幕?

小智 3

问题出在 HTML 上。当打印到标准输出时,内联元素与块<canvas>元素相互引用。

通过包裹<p id="output"/>在 div 中解决了问题。