当我尝试运行这个简单的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);
}
Run Code Online (Sandbox Code Playgroud)
Invalid Enum [1280]在你打电话glewInit()给最简单的修复之后,你实际上是从OpenGL 获得的.
glewExperimental = GL_TRUE;
Run Code Online (Sandbox Code Playgroud)
在你打电话之前glewInit().
glewExperimental = GL_TRUE;
GLenum glewError = glewInit();
if (glewError != GLEW_OK)
{
glfwTerminate();
exit(EXIT_FAILURE);
}
Run Code Online (Sandbox Code Playgroud)
为什么?好吧它与GLEW如何加载扩展,函数等有关.默认情况下,GLEW会将某些函数等设置为不受支持,从而绕过你需要设置的内容glewExperimental = GL_TRUE;,否则它会产生类似于你获取的错误.
实验动力
GLEW从图形驱动程序获取有关受支持的扩展的信息.但是,实验或预发布驱动程序可能不会通过标准机制报告每个可用的扩展,在这种情况下,GLEW将报告它不受支持.为了避免这种情况,可以通过在调用glewInit()之前将其设置为GL_TRUE来打开glewExperimental全局开关,这将确保将公开具有有效入口点的所有扩展.
永远记住要检查OpenGL错误,它们通常会告诉您错误和/或帮助您找到问题.
GLenum error = glGetError();
if (error != GL_NO_ERROR)
{
std::cout << "OpenGL Error: " << error << std::endl;
}
Run Code Online (Sandbox Code Playgroud)