无法在 OpenGL 中更改背景颜色
Can't change background color in OpenGL
我刚刚开始尝试使用 OpenGL(使用 freeglut 和 GLEW)。我可以让 window 弹出,但没有任何东西被吸引,我什至不能让它改变背景颜色。
主函数如下所示:
int
main(int argc, char **argv)
{
GLenum err;
/* Initialize GLUT library */
glutInit(&argc, argv);
/* Set window mode */
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
/* Choose OpenGL version */
glutInitContextVersion(3, 3);
/* Choose OpenGL profile */
glutInitContextFlags(GLUT_CORE_PROFILE);
/* Create a GLUT window */
glutCreateWindow("OpenGL 2D");
/* Initialize GLEW library */
glewExperimental = GL_TRUE;
err = glewInit();
if(err != GLEW_OK) {
printf("Cannot initialize GLEW: %s\n",
glewGetErrorString(err));
return 1;
}
/* WORKAROUND: Ignore all GLEW errors */
while(glGetError() != GL_NO_ERROR)
;
(void) printf("OpenGL vendor: \"%s\"\n"
" renderer: \"%s\"\n"
" version: \"%s\"\n"
" SL version: \"%s\"\n",
glGetString(GL_VENDOR),
glGetString(GL_RENDERER),
glGetString(GL_VERSION),
glGetString(GL_SHADING_LANGUAGE_VERSION));
/* Set up callback function for "reshape" event */
printf("Setting callback functions\n");
glutReshapeFunc(canvas_reshape);
/* Set up callback function for "display" event */
glutDisplayFunc(canvas_display);
/* Set up callback function for "keyboard" event */
glutKeyboardFunc(canvas_keyboard);
/* Set up callback function for "timer" event */
glutTimerFunc(30, canvas_timer, 0);
/* Initialize OpenGL */
init();
/* Choose the window's position */
glutPositionWindow(100, 100);
/* Choose the window's size */
glutReshapeWindow(800, 600);
/* Start main loop */
printf("Entering main loop\n");
glutMainLoop();
return 0;
}
这是初始化的样子:
init()
{
const GLchar *vertex_shader_source[] = {
"#version 330 core\n",
"\n",
"layout(location=0) in vec4 position;\n",
"out vec4 color;\n",
"uniform mat4 viewtrans;\n",
"\n",
"void\n",
"main()\n",
"{\n",
" gl_Position = viewtrans * position;\n"
" color = vec4(1.0, 1.0, 1.0, 1.0);\n"
"}\n" };
const GLchar *fragment_shader_source[] = {
"#version 330 core\n",
"in vec4 color;\n",
"layout(location=0) out vec4 fcolor;\n",
"void\n",
"main()\n",
"{\n",
" fcolor = color;\n",
"}\n" };
char compiler_log[LOGSIZE];
/* Obtain an unused name for our vertex array */
printf("Creating vertex array\n");
glGenVertexArrays(1, &vertex_array);
check_error("glGenVertexArrays");
/* Tell OpenGL to use the new vertex array */
glBindVertexArray(vertex_array);
check_error("glBindVertexArray");
/* Obtain an unused name for our vertex buffer */
printf("Creating vertex buffer\n");
glGenBuffers(1, &vertex_buffer);
check_error("glGenBuffers");
/* Tell OpenGL to use the new vertex buffer as the
* vertex array */
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
check_error("glBindBuffer");
/* We want to get two coordinates from the vertex buffer and
* feed them as the first parameter to the vertex shader */
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, 0);
/* Create vertex shader */
printf("Creating vertex shader\n");
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
check_error("glCreateShader");
/* Assign vertex shader source code */
glShaderSource(vertex_shader, sizeof(vertex_shader_source) / sizeof(GLchar *),
vertex_shader_source, 0);
check_error("glShaderSource");
/* Compile vertex shader */
glCompileShader(vertex_shader);
check_error("glCompileShader");
/* Get compiler log *//* Set up callback function for "timer" event */
glGetShaderInfoLog(vertex_shader, LOGSIZE, 0, compiler_log);
printf(" Compiler log: \"%s\"\n", compiler_log);
/* Create fragment shader */
printf("Creating fragment shader\n");
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
check_error("glCreateShader");
/* Assign fragment shader source code */
glShaderSource(fragment_shader, sizeof(fragment_shader_source) / sizeof(GLchar *),
fragment_shader_source, 0);
check_error("glShaderSource");
/* Compile fragment shader */
glCompileShader(fragment_shader);
check_error("glCompileShader");
/* Get compiler log */
glGetShaderInfoLog(fragment_shader, LOGSIZE, 0, compiler_log);
printf(" Compiler log: \"%s\"\n", compiler_log);
/* Create shader program */
printf("Creating shader program\n");
shader_program = glCreateProgram();
check_error("glCreateProgram");
/* Attach vertex shader */
glAttachShader(shader_program, vertex_shader);
check_error("glAttachShader");
/* Attach fragment shader */
glAttachShader(shader_program, fragment_shader);
check_error("glAttachShader");
/* Link shader program */
glLinkProgram(shader_program);
check_error("glLinkProgram");
/* Get linker log */
glGetProgramInfoLog(shader_program, LOGSIZE, 0, compiler_log);
printf(" Linker log: \"%s\"\n", compiler_log);
/* Get location of "viewtrans" matrix */
viewtrans = glGetUniformLocation(shader_program, "viewtrans");
check_error("glGetUniformLocation");
/* Tell OpenGL to use the new shader program */
glUseProgram(shader_program);
/* Choose background color */
glClearColor(1.0, 0.0, 1.0, 0.0);
}
这是我用来画的:
static void
canvas_display()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
这完全基于教程。实际发生的是一个 300 x 300 的白色 window 出现,被重塑为 800 x 600 的黑色 window,但中间或角落仍然有一个 300 x 300 的白色方块,当调整 window 的大小时,其像素(部分)变黑,使得(部分)正方形消失(手动或通过代码)。我还编写了绘制三角形的代码,但正如人们可能期望的那样,这也不起作用。但无论如何,这里是代码:
static void
canvas_display()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat vertices[] =
{ 0.0, 0.0,
0.5, 0.5,
0.5, 0.0 };
glGenVertexArrays(1, &vertex_array);
glBindVertexArray(vertex_array);
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 2, vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
不要连续指定新的顶点数组对象。 Create 1 Vertex Array Object at initialization. The vertex array is contained in the Vertex Buffer Object. When a named buffer object is bound to the ARRAY_BUFFER
target, then the last parameter of glVertexAttribPointer
被视为缓冲区对象数据存储中的字节偏移量。因此偏移量必须是 NULL
:
void init()
{
// [...]
GLfloat vertices[] =
{ 0.0, 0.0,
0.5, 0.5,
0.5, 0.0 };
glGenVertexArrays(1, &vertex_array);
glBindVertexArray(vertex_array);
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 2, NULL);
}
确保程序已安装,绘制几何时绑定了VAO。默认情况下,制服的值初始化为零。至少你必须设置 Identity matrix 然后矩阵统一 viewtrans
.
因为你使用了双缓冲(GLUT_DOUBLE
),你必须在 glutSwapBuffers
绘制所有几何图形后交换当前 window 的缓冲区
void canvas_display()
{
glClearColor(1.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_program);
GLfloat identity_mat[] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
glUniformMatrix4fv(viewtrans, 1, GL_FALSE, identity_mat);
glBindVertexArray(vertex_array);
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
glutPostRedisplay();
}
我刚刚开始尝试使用 OpenGL(使用 freeglut 和 GLEW)。我可以让 window 弹出,但没有任何东西被吸引,我什至不能让它改变背景颜色。
主函数如下所示:
int
main(int argc, char **argv)
{
GLenum err;
/* Initialize GLUT library */
glutInit(&argc, argv);
/* Set window mode */
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
/* Choose OpenGL version */
glutInitContextVersion(3, 3);
/* Choose OpenGL profile */
glutInitContextFlags(GLUT_CORE_PROFILE);
/* Create a GLUT window */
glutCreateWindow("OpenGL 2D");
/* Initialize GLEW library */
glewExperimental = GL_TRUE;
err = glewInit();
if(err != GLEW_OK) {
printf("Cannot initialize GLEW: %s\n",
glewGetErrorString(err));
return 1;
}
/* WORKAROUND: Ignore all GLEW errors */
while(glGetError() != GL_NO_ERROR)
;
(void) printf("OpenGL vendor: \"%s\"\n"
" renderer: \"%s\"\n"
" version: \"%s\"\n"
" SL version: \"%s\"\n",
glGetString(GL_VENDOR),
glGetString(GL_RENDERER),
glGetString(GL_VERSION),
glGetString(GL_SHADING_LANGUAGE_VERSION));
/* Set up callback function for "reshape" event */
printf("Setting callback functions\n");
glutReshapeFunc(canvas_reshape);
/* Set up callback function for "display" event */
glutDisplayFunc(canvas_display);
/* Set up callback function for "keyboard" event */
glutKeyboardFunc(canvas_keyboard);
/* Set up callback function for "timer" event */
glutTimerFunc(30, canvas_timer, 0);
/* Initialize OpenGL */
init();
/* Choose the window's position */
glutPositionWindow(100, 100);
/* Choose the window's size */
glutReshapeWindow(800, 600);
/* Start main loop */
printf("Entering main loop\n");
glutMainLoop();
return 0;
}
这是初始化的样子:
init()
{
const GLchar *vertex_shader_source[] = {
"#version 330 core\n",
"\n",
"layout(location=0) in vec4 position;\n",
"out vec4 color;\n",
"uniform mat4 viewtrans;\n",
"\n",
"void\n",
"main()\n",
"{\n",
" gl_Position = viewtrans * position;\n"
" color = vec4(1.0, 1.0, 1.0, 1.0);\n"
"}\n" };
const GLchar *fragment_shader_source[] = {
"#version 330 core\n",
"in vec4 color;\n",
"layout(location=0) out vec4 fcolor;\n",
"void\n",
"main()\n",
"{\n",
" fcolor = color;\n",
"}\n" };
char compiler_log[LOGSIZE];
/* Obtain an unused name for our vertex array */
printf("Creating vertex array\n");
glGenVertexArrays(1, &vertex_array);
check_error("glGenVertexArrays");
/* Tell OpenGL to use the new vertex array */
glBindVertexArray(vertex_array);
check_error("glBindVertexArray");
/* Obtain an unused name for our vertex buffer */
printf("Creating vertex buffer\n");
glGenBuffers(1, &vertex_buffer);
check_error("glGenBuffers");
/* Tell OpenGL to use the new vertex buffer as the
* vertex array */
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
check_error("glBindBuffer");
/* We want to get two coordinates from the vertex buffer and
* feed them as the first parameter to the vertex shader */
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 2, 0);
/* Create vertex shader */
printf("Creating vertex shader\n");
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
check_error("glCreateShader");
/* Assign vertex shader source code */
glShaderSource(vertex_shader, sizeof(vertex_shader_source) / sizeof(GLchar *),
vertex_shader_source, 0);
check_error("glShaderSource");
/* Compile vertex shader */
glCompileShader(vertex_shader);
check_error("glCompileShader");
/* Get compiler log *//* Set up callback function for "timer" event */
glGetShaderInfoLog(vertex_shader, LOGSIZE, 0, compiler_log);
printf(" Compiler log: \"%s\"\n", compiler_log);
/* Create fragment shader */
printf("Creating fragment shader\n");
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
check_error("glCreateShader");
/* Assign fragment shader source code */
glShaderSource(fragment_shader, sizeof(fragment_shader_source) / sizeof(GLchar *),
fragment_shader_source, 0);
check_error("glShaderSource");
/* Compile fragment shader */
glCompileShader(fragment_shader);
check_error("glCompileShader");
/* Get compiler log */
glGetShaderInfoLog(fragment_shader, LOGSIZE, 0, compiler_log);
printf(" Compiler log: \"%s\"\n", compiler_log);
/* Create shader program */
printf("Creating shader program\n");
shader_program = glCreateProgram();
check_error("glCreateProgram");
/* Attach vertex shader */
glAttachShader(shader_program, vertex_shader);
check_error("glAttachShader");
/* Attach fragment shader */
glAttachShader(shader_program, fragment_shader);
check_error("glAttachShader");
/* Link shader program */
glLinkProgram(shader_program);
check_error("glLinkProgram");
/* Get linker log */
glGetProgramInfoLog(shader_program, LOGSIZE, 0, compiler_log);
printf(" Linker log: \"%s\"\n", compiler_log);
/* Get location of "viewtrans" matrix */
viewtrans = glGetUniformLocation(shader_program, "viewtrans");
check_error("glGetUniformLocation");
/* Tell OpenGL to use the new shader program */
glUseProgram(shader_program);
/* Choose background color */
glClearColor(1.0, 0.0, 1.0, 0.0);
}
这是我用来画的:
static void
canvas_display()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
这完全基于教程。实际发生的是一个 300 x 300 的白色 window 出现,被重塑为 800 x 600 的黑色 window,但中间或角落仍然有一个 300 x 300 的白色方块,当调整 window 的大小时,其像素(部分)变黑,使得(部分)正方形消失(手动或通过代码)。我还编写了绘制三角形的代码,但正如人们可能期望的那样,这也不起作用。但无论如何,这里是代码:
static void
canvas_display()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
GLfloat vertices[] =
{ 0.0, 0.0,
0.5, 0.5,
0.5, 0.0 };
glGenVertexArrays(1, &vertex_array);
glBindVertexArray(vertex_array);
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 2, vertices);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
不要连续指定新的顶点数组对象。 Create 1 Vertex Array Object at initialization. The vertex array is contained in the Vertex Buffer Object. When a named buffer object is bound to the ARRAY_BUFFER
target, then the last parameter of glVertexAttribPointer
被视为缓冲区对象数据存储中的字节偏移量。因此偏移量必须是 NULL
:
void init()
{
// [...]
GLfloat vertices[] =
{ 0.0, 0.0,
0.5, 0.5,
0.5, 0.0 };
glGenVertexArrays(1, &vertex_array);
glBindVertexArray(vertex_array);
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 2, NULL);
}
确保程序已安装,绘制几何时绑定了VAO。默认情况下,制服的值初始化为零。至少你必须设置 Identity matrix 然后矩阵统一 viewtrans
.
因为你使用了双缓冲(GLUT_DOUBLE
),你必须在 glutSwapBuffers
void canvas_display()
{
glClearColor(1.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUseProgram(shader_program);
GLfloat identity_mat[] = { 1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1 };
glUniformMatrix4fv(viewtrans, 1, GL_FALSE, identity_mat);
glBindVertexArray(vertex_array);
glDrawArrays(GL_TRIANGLES, 0, 3);
glutSwapBuffers();
glutPostRedisplay();
}