编译着色器后程序停止绘制
Program stops drawing after compiling shaders
我正在编写一个要编译为 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;
}
但是在 glClearColor(...)
之后添加以下内容后,我就不再在浏览器中看到蓝屏了:
const GLuint vertex_shader = load_shader(GL_VERTEX_SHADER, VERTEX_SHADER);
const GLuint fragment_shader = load_shader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
我怀疑着色器代码与问题完全无关,但为了以防万一,这里是 load_shader
的代码,摘自 OpenGL ES 2 book(省略了错误检查)
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;
}
以及着色器本身:
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"
"}
以下是我的编译方式:
EMSCRIPTEN_OPTS = \
-s WASM=1 \
-s FULL_ES2=1 \
-s MODULARIZE=1
${EMCC} main_web.c -o hello.js ${EMSCRIPTEN_OPTS}
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>
为什么我刚加载着色器时就停止清屏了?
问题出在 HTML。打印到标准输出时,内联元素与块 <canvas>
元素发生冲突。
通过将 <p id="output"/>
包装在 div 中解决了问题。
我正在编写一个要编译为 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;
}
但是在 glClearColor(...)
之后添加以下内容后,我就不再在浏览器中看到蓝屏了:
const GLuint vertex_shader = load_shader(GL_VERTEX_SHADER, VERTEX_SHADER);
const GLuint fragment_shader = load_shader(GL_FRAGMENT_SHADER, FRAGMENT_SHADER);
我怀疑着色器代码与问题完全无关,但为了以防万一,这里是 load_shader
的代码,摘自 OpenGL ES 2 book(省略了错误检查)
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;
}
以及着色器本身:
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"
"}
以下是我的编译方式:
EMSCRIPTEN_OPTS = \
-s WASM=1 \
-s FULL_ES2=1 \
-s MODULARIZE=1
${EMCC} main_web.c -o hello.js ${EMSCRIPTEN_OPTS}
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>
为什么我刚加载着色器时就停止清屏了?
问题出在 HTML。打印到标准输出时,内联元素与块 <canvas>
元素发生冲突。
通过将 <p id="output"/>
包装在 div 中解决了问题。