当我尝试运行这个简单的OpenGL测试程序时,我遇到了分段错误。只有在使用核心配置文件标志创建上下文时才会发生这种情况。如果我使用兼容性配置文件标志,程序运行没有问题。
编辑:我检查了指向函数glGenVertexArrays
的指针,并返回NULL
。如果glfwCreateWindow
未返回NULL
,并且glGetString(GL_VERSION)
确认上下文为版本4.3且glewInit
返回GLEW_OK
,那么为什么glGenVertexArrays == NULL
?
我的操作系统是64位Windows 7,而我的GPU是带有331.82 WHQL驱动程序的Nvidia GTX 760。
代码:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdlib.h>
#include <stdio.h>
#define GLSL(src) "#version 430 core\n" #src
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GL_TRUE);
}
GLuint create_program(const char* vertex_source, const char* fragment_source)
{
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vertex_source, NULL);
glCompileShader(vs);
unsigned int fs = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fs, 1, &fragment_source, NULL);
glCompileShader(fs);
GLuint shader_program = glCreateProgram();
glAttachShader(shader_program, fs);
glAttachShader(shader_program, vs);
glLinkProgram(shader_program);
return shader_program;
}
const char* vertex_shader = GLSL(
layout(location = 0) in vec3 vertex_position;
void main()
{
gl_Position = vec4(vertex_position, 1.0);
}
);
const char* fragment_shader = GLSL(
out vec4 frag_color;
void main()
{
frag_color = vec4(1.0, 0.0, 0.0, 1.0);
}
);
int main(int argc, char* argv[])
{
if(!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
//if we set GLFW_OPENGL_PROFILE to GLFW_OPENGL_CORE_PROFILE
//instead of GLFW_OPENGL_COMPAT_PROFILE the program will
//segfault at line 98, call to glGenVertexArrays
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
GLFWwindow* window = glfwCreateWindow(512, 512, "OpenGL", NULL, NULL);
if(!window)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
glfwSetKeyCallback(window, key_callback);
glfwMakeContextCurrent(window);
GLenum glewError = glewInit();
if(glewError != GLEW_OK)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
printf("OpenGL Version: %s\n\n", glGetString(GL_VERSION));
float position[] =
{
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, -1.0f, 0.0f
};
unsigned short indices[] =
{
1, 0, 2,
3, 1, 2
};
GLuint vao = 0;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint index_buffer = 0;
GLuint vertex_buffer = 0;
glGenBuffers(1, &index_buffer);
glGenBuffers(1, &vertex_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), &indices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(position), &position, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
GLuint shader_program = create_program(vertex_shader, fragment_shader);
glUseProgram(shader_program);
while(!glfwWindowShouldClose(window))
{
glClear(GL_COLOR_BUFFER_BIT);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, NULL);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}
答案 0 :(得分:7)
在您致电Invalid Enum [1280]
之后,您实际上是从OpenGL获得了glewInit()
。
glewExperimental = GL_TRUE;
在此之前致电glewInit()
。
glewExperimental = GL_TRUE;
GLenum glewError = glewInit();
if (glewError != GLEW_OK)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
为什么呢?好吧,它与GLEW如何加载扩展,函数等有关。默认情况下,GLEW会将某些功能设置为不支持,从而绕过你需要设置glewExperimental = GL_TRUE;
或者否则它会产生一个像你一样的错误。
实验动力
GLEW从图形驱动程序获取有关受支持的扩展的信息。但是,实验或预发布驱动程序可能不会通过标准机制报告每个可用的扩展,在这种情况下,GLEW将报告它不受支持。为了避免这种情况,可以在调用glewInit()之前将glewExperimental全局开关设置为GL_TRUE,从而确保所有具有有效入口点的扩展都将被公开。
永远记住要检查OpenGL错误,它们通常会告诉您错误和/或帮助您找到问题。
GLenum error = glGetError();
if (error != GL_NO_ERROR)
{
std::cout << "OpenGL Error: " << error << std::endl;
}
您可以阅读有关不同错误here的信息。
答案 1 :(得分:0)
输出glGenVertexArrays
的值。现在可能是0
或null
。我发现即使在核心配置文件中我也必须首先设置某些功能。
答案 2 :(得分:0)
如果您创建核心配置文件,我遇到了类似的问题,即glew没有正确初始化所有函数指针。我打算研究一下glew实现,看看为什么会出现这种情况,但是还没有解决它,因为兼容性上下文为我提供了帮助。
但是,您可以尝试的一种可能性是使用GLFW创建兼容性上下文,初始化GLEW,销毁GLFW窗口并使用核心上下文创建一个新窗口。