OpenGL+GLFW glGenVertexArrays returns GL_INVALID_OPERATION
OpenGL+GLFW glGenVertexArrays returns GL_INVALID_OPERATION
在尝试使用 "modern" OpenGL(基本上是 3.2+)时,我 运行 遇到了一些麻烦 运行ning 基本代码(来自 here and here) 使用 GLFW、GLEW 和 OpenGL。
我的第一个问题是使用以下代码:
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
const GLchar* vertexSource =
"#version 150 core\n"
"in vec2 position;"
"void main()"
"{"
" gl_Position = vec4(position, 0.0, 1.0);"
"}";
const GLchar* fragmentSource =
"#version 150 core\n"
"out vec4 outColor;"
"void main()"
"{"
" outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"}";
void checkErr(const char* msg) {
GLenum err = glGetError();
if (err != 0) {
printf("@ \"%s\": %d\n", msg, err);
exit(EXIT_FAILURE);
} else {
printf("@ \"%s\": successful\n", msg);
}
}
int main(int argc, char* argv[]) {
GLFWwindow* window;
// Initialize GLFW
if (!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
// Make the window's context current
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = GL_TRUE;
glewInit();
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER);
const GLubyte* version = glGetString(GL_VERSION);
const GLubyte* glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);
printf ("Renderer: %s\n", renderer);
printf ("OpenGL version: %s\n", version);
printf ("GLSL version: %s\n", glslVersion);
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
checkErr("Gen VAO");
glBindVertexArray(vao);
checkErr("Bind VAO");
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers(1, &vbo);
checkErr("Gen VBO");
GLfloat vertices[] = {
0.0f, 0.5f,
0.5f, -0.5f,
-0.5f, -0.5f
};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
checkErr("Bind VBO");
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
checkErr("VBO data");
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
checkErr("Compile vert shader");
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
checkErr("Compile frag shader");
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
checkErr("Link program");
glUseProgram(shaderProgram);
checkErr("Use program");
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
checkErr("Enable vertex attrib");
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
checkErr("Describe vert data");
// Loop until the user closes the window
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
exit(EXIT_SUCCESS);
}
我在设置顶点数组对象的第一步中立即 运行 陷入 GL_INVALID_OPERATION
错误。
我已经对 OS X 脆弱的 OpenGL 支持做了相当多的研究,但到目前为止,我在这段代码中修改的大部分内容除了产生一个完全黑屏之外什么也没做(也就是说,当我删除 checkError
辅助函数的崩溃行为时)。
作为参考,我 运行正在使用 2015 年初的 MacBook Pro w/Retina、OS X v10.11.3,以及上述程序的版本信息输出榜单如下:
Renderer: Intel(R) Iris(TM) Graphics 6100
OpenGL version: 4.1 INTEL-10.12.13
GLSL version: 4.10
非常感谢任何帮助!
您只是假设您的错误是由glGenVertexArrays
产生的。但事实并非如此。它是由 glewInit
生成的。这是因为 GLEW 刚刚在核心配置文件 opengl 上损坏:它使用 glGetString(GL_EXTENSIONS)
查询扩展字符串,这在核心配置文件中不可用并生成 GL_INVALID_ENUM
错误 (1280)。
通常,glewInit
然后会以 return 代码 GL_FALSE
中止。但是,设置 glewExperimental=GL_TRUE
的 "workaround" 将使其继续,忽略错误,并无论如何查询所有扩展指针。现在至少在 3 个不同方面被打破:
- 所有用于查询特定扩展可用性的 GLEW 变量 return false 即使扩展可用。
- 它将检索扩展函数的函数指针,这些函数的可用性尚未由实现公布。不能保证这些指针将是
NULL
,但调用它们将是未定义的行为。与 1 一起,这意味着您无法检查任何扩展的可用性,除非手动执行 glew 实际上可以为您做的事情。
- 它将使 GL 上下文处于错误状态。
作为一种快速而肮脏的 hack,您可以在 glewInit
之后添加一个 glGetError()
,以消除错误。在我这样做之后,您的代码在我的实现中生成了预期的白色三角形 (NVIDIA/Linux)。
更好的解决方法可能是切换到另一个可以正确处理核心配置文件的 GL 加载器,例如 glad。切换并不难,因为只需要替换 init 函数。请注意,glad 不是一个加载器库,而是一个 python 脚本,它根据您的需要生成一个加载器 source 文件,因此您不需要 link 另一个库,但只需将另一个源文件添加到您的项目中。
在尝试使用 "modern" OpenGL(基本上是 3.2+)时,我 运行 遇到了一些麻烦 运行ning 基本代码(来自 here and here) 使用 GLFW、GLEW 和 OpenGL。
我的第一个问题是使用以下代码:
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
const GLchar* vertexSource =
"#version 150 core\n"
"in vec2 position;"
"void main()"
"{"
" gl_Position = vec4(position, 0.0, 1.0);"
"}";
const GLchar* fragmentSource =
"#version 150 core\n"
"out vec4 outColor;"
"void main()"
"{"
" outColor = vec4(1.0, 1.0, 1.0, 1.0);"
"}";
void checkErr(const char* msg) {
GLenum err = glGetError();
if (err != 0) {
printf("@ \"%s\": %d\n", msg, err);
exit(EXIT_FAILURE);
} else {
printf("@ \"%s\": successful\n", msg);
}
}
int main(int argc, char* argv[]) {
GLFWwindow* window;
// Initialize GLFW
if (!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
// Create a windowed mode window and its OpenGL context
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
// Make the window's context current
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = GL_TRUE;
glewInit();
// get version info
const GLubyte* renderer = glGetString(GL_RENDERER);
const GLubyte* version = glGetString(GL_VERSION);
const GLubyte* glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);
printf ("Renderer: %s\n", renderer);
printf ("OpenGL version: %s\n", version);
printf ("GLSL version: %s\n", glslVersion);
// Create Vertex Array Object
GLuint vao;
glGenVertexArrays(1, &vao);
checkErr("Gen VAO");
glBindVertexArray(vao);
checkErr("Bind VAO");
// Create a Vertex Buffer Object and copy the vertex data to it
GLuint vbo;
glGenBuffers(1, &vbo);
checkErr("Gen VBO");
GLfloat vertices[] = {
0.0f, 0.5f,
0.5f, -0.5f,
-0.5f, -0.5f
};
glBindBuffer(GL_ARRAY_BUFFER, vbo);
checkErr("Bind VBO");
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
checkErr("VBO data");
// Create and compile the vertex shader
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &vertexSource, NULL);
glCompileShader(vertexShader);
checkErr("Compile vert shader");
// Create and compile the fragment shader
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &fragmentSource, NULL);
glCompileShader(fragmentShader);
checkErr("Compile frag shader");
// Link the vertex and fragment shader into a shader program
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glBindFragDataLocation(shaderProgram, 0, "outColor");
glLinkProgram(shaderProgram);
checkErr("Link program");
glUseProgram(shaderProgram);
checkErr("Use program");
// Specify the layout of the vertex data
GLint posAttrib = glGetAttribLocation(shaderProgram, "position");
glEnableVertexAttribArray(posAttrib);
checkErr("Enable vertex attrib");
glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, 0, 0);
checkErr("Describe vert data");
// Loop until the user closes the window
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 3);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
exit(EXIT_SUCCESS);
}
我在设置顶点数组对象的第一步中立即 运行 陷入 GL_INVALID_OPERATION
错误。
我已经对 OS X 脆弱的 OpenGL 支持做了相当多的研究,但到目前为止,我在这段代码中修改的大部分内容除了产生一个完全黑屏之外什么也没做(也就是说,当我删除 checkError
辅助函数的崩溃行为时)。
作为参考,我 运行正在使用 2015 年初的 MacBook Pro w/Retina、OS X v10.11.3,以及上述程序的版本信息输出榜单如下:
Renderer: Intel(R) Iris(TM) Graphics 6100
OpenGL version: 4.1 INTEL-10.12.13
GLSL version: 4.10
非常感谢任何帮助!
您只是假设您的错误是由glGenVertexArrays
产生的。但事实并非如此。它是由 glewInit
生成的。这是因为 GLEW 刚刚在核心配置文件 opengl 上损坏:它使用 glGetString(GL_EXTENSIONS)
查询扩展字符串,这在核心配置文件中不可用并生成 GL_INVALID_ENUM
错误 (1280)。
通常,glewInit
然后会以 return 代码 GL_FALSE
中止。但是,设置 glewExperimental=GL_TRUE
的 "workaround" 将使其继续,忽略错误,并无论如何查询所有扩展指针。现在至少在 3 个不同方面被打破:
- 所有用于查询特定扩展可用性的 GLEW 变量 return false 即使扩展可用。
- 它将检索扩展函数的函数指针,这些函数的可用性尚未由实现公布。不能保证这些指针将是
NULL
,但调用它们将是未定义的行为。与 1 一起,这意味着您无法检查任何扩展的可用性,除非手动执行 glew 实际上可以为您做的事情。 - 它将使 GL 上下文处于错误状态。
作为一种快速而肮脏的 hack,您可以在 glewInit
之后添加一个 glGetError()
,以消除错误。在我这样做之后,您的代码在我的实现中生成了预期的白色三角形 (NVIDIA/Linux)。
更好的解决方法可能是切换到另一个可以正确处理核心配置文件的 GL 加载器,例如 glad。切换并不难,因为只需要替换 init 函数。请注意,glad 不是一个加载器库,而是一个 python 脚本,它根据您的需要生成一个加载器 source 文件,因此您不需要 link 另一个库,但只需将另一个源文件添加到您的项目中。