如果 OpenGL 3+ 请求,glfw3 不绘图?
Posted
技术标签:
【中文标题】如果 OpenGL 3+ 请求,glfw3 不绘图?【英文标题】:glfw3 not drawing if OpenGL 3+ requested? 【发布时间】:2017-10-09 07:30:21 【问题描述】:下面我包含了glfw-quick-test.c
,它基本上是从http://www.glfw.org/docs/latest/quick.html 逐字复制的——除了删除了glad
的使用、添加了背景颜色、几个定义,因此它可以在 Ubuntu 14.04(64 位)上编译,以及预处理器#ifdef
开关(宏DO_OPENGL_THREE
)来更改请求的OpenGL 版本。
当我编译时:
gcc -g -o glfw-quick-test.exe glfw-quick-test.c -lglfw -lGLU -lGL -lm
./glfw-quick-test.exe
...然后我收到消息“GLFW Requesting OpenGL 2.1
”并且绘图很好:
当我编译时:
gcc -g -DDO_OPENGL_THREE -o glfw-quick-test.exe glfw-quick-test.c -lglfw -lGLU -lGL -lm
./glfw-quick-test.exe
...然后我收到消息“GLFW Requesting OpenGL 3.2
”并且根本没有绘制旋转三角形 - 只保留了背景颜色:
谁能解释为什么会这样?即使请求了 OpenGL 3.2,我能否以某种方式让 GLFW3 进行绘制,如果可以,如何绘制?
(我知道原始源代码显示“// NOTE: OpenGL error checks have been omitted for brevity
”,但我不确定应该添加什么样的错误检查,看看 OpenGL 3.2 绘图会出现什么问题......)
代码,glfw-quick-test.c
(编辑:现在有错误检查):
// http://www.glfw.org/docs/latest/quick.html
#define UBUNTU14
#ifdef UBUNTU14 // assume Ubuntu 14.04
// strange; Ubuntu 14 GLFW/glfw3.h doesn't have GLFW_TRUE, GLFW_FALSE, mentions GL_TRUE GL_FALSE
#define GLFW_TRUE GL_TRUE
#define GLFW_FALSE GL_FALSE
#endif
//~ #include <glad/glad.h> // "GL/GLES/EGL/GLX/WGL Loader-Generator based on the official specs."
#include <GLFW/glfw3.h>
#include "linmath.h"
#include <stdlib.h>
#include <stdio.h>
static const struct
float x, y;
float r, g, b;
vertices[3] =
-0.6f, -0.4f, 1.f, 0.f, 0.f ,
0.6f, -0.4f, 0.f, 1.f, 0.f ,
0.f, 0.6f, 0.f, 0.f, 1.f
;
static const char* vertex_shader_text =
"uniform mat4 MVP;\n"
"attribute vec3 vCol;\n"
"attribute vec2 vPos;\n"
"varying vec3 color;\n"
"void main()\n"
"\n"
" gl_Position = MVP * vec4(vPos, 0.0, 1.0);\n"
" color = vCol;\n"
"\n";
static const char* fragment_shader_text =
"varying vec3 color;\n"
"void main()\n"
"\n"
" gl_FragColor = vec4(color, 1.0);\n"
"\n";
static void error_callback(int error, const char* description)
fprintf(stderr, "Error: %s\n", description);
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
void checkGLerrors(char *label)
// check OpenGL error
GLenum err;
while ((err = glGetError()) != GL_NO_ERROR)
char* errorstr = "";
switch(err)
case GL_INVALID_OPERATION: errorstr="INVALID_OPERATION"; break;
case GL_INVALID_ENUM: errorstr="INVALID_ENUM"; break;
case GL_INVALID_VALUE: errorstr="INVALID_VALUE"; break;
case GL_OUT_OF_MEMORY: errorstr="OUT_OF_MEMORY"; break;
case GL_INVALID_FRAMEBUFFER_OPERATION: errorstr="INVALID_FRAMEBUFFER_OPERATION"; break;
printf("OpenGL error ('%s'): %d %s\n", label, err, errorstr);
int main(void)
GLFWwindow* window;
GLuint vertex_buffer, vertex_shader, fragment_shader, program;
GLint mvp_location, vpos_location, vcol_location;
glfwSetErrorCallback(error_callback);
if (!glfwInit())
exit(EXIT_FAILURE);
// NB: Ubuntu will not draw if 3.2 (just black screen) - only if 2.0 or 2.1?
#ifdef DO_OPENGL_THREE
printf("GLFW Requesting OpenGL 3.2\n");
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // only 3.2+
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE); //only 3.0+
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE); // https://***.com/q/23834680/
#else
printf("GLFW Requesting OpenGL 2.1\n");
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2); // 2);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1); // 0);
#endif
checkGLerrors("post hint");
window = glfwCreateWindow(640, 480, "Simple example", NULL, NULL);
if (!window)
glfwTerminate();
exit(EXIT_FAILURE);
checkGLerrors("post glfwCreateWindow");
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
//~ gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSwapInterval(1);
// NOTE: OpenGL error checks have been omitted for brevity
glGenBuffers(1, &vertex_buffer);
checkGLerrors("post glGenBuffers");
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
vertex_shader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex_shader, 1, &vertex_shader_text, NULL);
glCompileShader(vertex_shader);
fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment_shader, 1, &fragment_shader_text, NULL);
glCompileShader(fragment_shader);
program = glCreateProgram();
glAttachShader(program, vertex_shader);
glAttachShader(program, fragment_shader);
glLinkProgram(program);
checkGLerrors("post glLinkProgram");
mvp_location = glGetUniformLocation(program, "MVP");
vpos_location = glGetAttribLocation(program, "vPos");
vcol_location = glGetAttribLocation(program, "vCol");
checkGLerrors("post gl locations");
glEnableVertexAttribArray(vpos_location);
checkGLerrors("post gl EnableVertexAttribArray");
glVertexAttribPointer(vpos_location, 2, GL_FLOAT, GL_FALSE,
sizeof(float) * 5, (void*) 0);
checkGLerrors("post glVertexAttribPointer");
glEnableVertexAttribArray(vcol_location);
checkGLerrors("post glEnableVertexAttribArray");
glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE,
sizeof(float) * 5, (void*) (sizeof(float) * 2));
checkGLerrors("post glVertexAttribPointer");
while (!glfwWindowShouldClose(window))
float ratio;
int width, height;
mat4x4 m, p, mvp;
glfwGetFramebufferSize(window, &width, &height);
ratio = width / (float) height;
glViewport(0, 0, width, height);
glClearColor(0.784314, 0.780392, 0.305882, 1.0); // add background color
glClear(GL_COLOR_BUFFER_BIT);
mat4x4_identity(m);
mat4x4_rotate_Z(m, m, (float) glfwGetTime());
mat4x4_ortho(p, -ratio, ratio, -1.f, 1.f, 1.f, -1.f);
mat4x4_mul(mvp, p, m);
glUseProgram(program);
glUniformMatrix4fv(mvp_location, 1, GL_FALSE, (const GLfloat*) mvp);
glDrawArrays(GL_TRIANGLES, 0, 3);
glfwSwapBuffers(window);
glfwPollEvents();
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
【问题讨论】:
您检查过glGetError
告诉您的内容吗?在核心配置文件中,您必须使用 VAO。
谢谢@BDL - 不,不知道我应该这样做,现在会尝试这样做......编辑:做到了,凌晨3.2点得到“OpenGL error ('post glVertexAttribPointer'): 1282 INVALID_OPERATION
”......
【参考方案1】:
感谢@BDL 和他对 VAO(顶点数组对象)的评论,我找到了How to use VBOs without VAOs with OpenGL core profile? - 通过尝试那里的东西,我发现上面 OP 代码的唯一更改是需要的,所以绘图显示在OpenGL 3.2,是这样的吗:
...
//~ gladLoadGLLoader((GLADloadproc) glfwGetProcAddress);
glfwSwapInterval(1);
#ifdef DO_OPENGL_THREE
// https://***.com/a/30057424/277826:
// "You can however just create and bind a VAO and forget about it (keep it bound)."
GLuint VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
#endif
// NOTE: OpenGL error checks have been omitted for brevity
glGenBuffers(1, &vertex_buffer);
...
一旦这个带有 VAO 的部分进入,就不会再打印 OpenGL 错误,并且绘图就可以了。
【讨论】:
以上是关于如果 OpenGL 3+ 请求,glfw3 不绘图?的主要内容,如果未能解决你的问题,请参考以下文章
使用 GLFW3 在 OpenGL 上下文之间共享纹理不起作用
使用 glfw3 glew 和 opengl 在 Visual Studio 社区中获取访问冲突异常
如何在 imgui 窗口中使用 opengl glfw3 渲染?