int main(int argc, const char **arg)
{
if(!glfwInit()) {
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
auto window = glfwCreateWindow(1024, 768, "OpenGL Test", nullptr, nullptr);
if(!window) {
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetWindowSizeCallback(window, resizeWindow);
glfwSetKeyCallback(window, keyEvent);
// glewExperimental = GL_TRUE;
GLuint code = glewInit();
if(code != GLEW_OK)
{
std::cout << "GLEW Init Failed for reason: " << glewGetErrorString(code)<< std::endl;
return 1;
}
initGL();
while (!glfwWindowShouldClose(window)) {
/* Render here */
paintGL();
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
1️⃣ 初始化glfw
if(!glfwInit()) {
return -1;
}
2️⃣ 为glfw设置一些不能缺少的重要参数
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
3️⃣ 创建OpenGL窗体
auto window = glfwCreateWindow(1024, 768,
"OpenGL Test", nullptr, nullptr);
if(!window) {
glfwTerminate();
return -1;
}
4️⃣ 将上一步创建成功的窗体设置为OpenGL的Context
glfwMakeContextCurrent(window); // 设置窗体到当前的OpenGL Context
glfwSetWindowSizeCallback(window, resizeWindow); // 设置窗体尺寸改变的回调, 可选
glfwSetKeyCallback(window, keyEvent); //设置按键处理回调,可选
5️⃣ 初始化glew
// glewExperimental = GL_TRUE;
GLuint code = glewInit();
if(code != GLEW_OK)
{
std::cout << "GLEW Init Failed for reason: " << glewGetErrorString(code)<< std::endl;
return 1;
}
其中
// glewExperimental = GL_TRUE;
在不同平台会有不同的差异,Ubuntu环境下可能需要加上,笔者测试macOS环境下加不加这一句都没什么大的区别,因此在此处不做特别要求
6️⃣ 用户代码的OpenGL渲染初始化
initGL();
这里是由用户自己定义的初始化渲染环境的代码,具体可以参考《OpenGL编程指南(第8版)》的第一章的第一个OpenGL程序
7️⃣ glfw事件循环
while (!glfwWindowShouldClose(window)) {
/* Render here */
paintGL();
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
这里就是glfw和glut最大的区别, glut是设置显示回调函数后调用glutMainLoop(); 来启动事件循环, 而此处的glfw却是有个用户自己定义循环,而循环的结束标志是由glfw提供的api
glfwWindowShouldClose(GLFWwindow *window);
来判断窗体是否关闭
paintGL();
相当于glut设置的显示回调, 此处由用户自己在事件循环中主动调用
glfwSwapBuffers(GLFWwindow *window);
此处调用表示交换前后台缓冲区(使用双缓冲技术时会用到, 默认情况下会开启创缓冲技术)
glfwPollEvents();
这里是用来更新窗体事件的,主要用来搜集系统产生的各种事件,然后派发至用户自定义的各种事件回调中,如:
glfwSetWindowSizeCallback(window, resizeWindow); // 设置窗体尺寸改变的回调
glfwSetKeyCallback(window, keyEvent); //设置按键处理回调,可选
这两行注册的两个回调就会被调用