( 本文为LearnOpenGL教程的学习记录及拓展学习,教程链接:https://learnopengl-cn.github.io/ )
0、前言
创建OpenGL上下文通常需要编写特定于平台的代码才能创建窗口。它还需要从该上下文手动加载OpenGL函数。这些工具在大多数情况下提供了跨平台的解决方案,极大地简化了这些任务。LearnOpenGL教程使用GLFW创建上下文和窗口,使用GLAD来访问OpenGL规范接口。
GLFW是继GLUT、FreeGLUT之后,一个新的用于创建窗口,上下文和表面,接收输入和事件的第三方库,支持OpenGL,OpenGL ES和Vulkan,它提供了一些渲染物体所需的最低限度的接口。
GLAD是继GL3W,GLEW之后,一个新的用来访问OpenGL规范接口的第三方库
1、在MSVC2019中配置GLFW
(其他环境的配置请自行搜索)
打开GLFW的官网(https://www.glfw.org/),因为官方提供了MSVC的二进制文件,我们可以直接点击标题栏下载:
进入下载页后,我们可以看到Windows的二进制下载选项,分32/64位,根据个人需求我选的32位:
下下来之后,解压,可以看到VS个版本对应的文件夹,里面是编译好的库文件:
我们只需要把include和lib配置到VS中去就行了。创建一个C++项目,打开项目属性页,可以在 VC++目录 中配置include和lib,不过这里我还是配置在 C/C++ 和 链接器 中。需要修改三个地方:
(附加依赖项填入opengl32.lib和glfw3.lib)
这里我们就把GLFW配置好了,由于直接使用的编译好的二进制文件,所以很简单。
2.在MSVC2019中配置GLAD
打开GLAD的官方下载页:https://glad.dav1d.de/ ,根据需求选择配置,教程里只写了选择gl3.3以上版本,选择核心模式,所以这里我把全部都选了最高的:
点击右下角生成按钮后会进入下载页,我们直接点击zip文件进行下载:
解压之后包含include和src文件夹。再次打开VS属性页,把include放到附加包含目录中去:
右键添加现有项,把src文件夹中的glad.c文件包含进去:
至此,OpenGL最简单的环境就配置好了,其实VS2015/2017的配置也和VS2019差不多。
3.第一个OpenGL窗口程序
#include <iostream>
#include <glad/glad.h>
#include <GLFW/glfw3.h>
void error_callback(int error, const char* description); //声明
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods);
void bufferresize_callback(GLFWwindow* window, int width, int height);
int main()
{
if (!glfwInit()) {
return -1; //初始化GLFW库失败
}
//注册错误回调,大多数事件都是通过回调报告的
glfwSetErrorCallback(error_callback);
//设置最低主版本号
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); //mac系统加这一句
//创建窗口对象,如果要销毁窗口则glfwDestroyWindow(window)
GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
//创建失败则返回NULL,退出程序
if (window == NULL)
{
std::cout << "Failed to create GLFW window" << std::endl;
glfwTerminate();
return -1;
}
//窗口位置,试了下不包含标题栏
glfwSetWindowPos(window, 100, 100);
//注册按键按下的回调
glfwSetKeyCallback(window, key_callback);
//注册帧缓冲区大小改变的回调
glfwSetFramebufferSizeCallback(window, bufferresize_callback);
//通知GLFW将我们窗口的上下文设置为当前线程的主上下文
//必须先具有当前的OpenGL上下文,然后才能使用OpenGL API,加载程序需要当前上下文才能加载
glfwMakeContextCurrent(window);
//在调用任何OpenGL的函数之前我们需要初始化GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "Failed to initialize GLAD" << std::endl;
glfwTerminate();
return -1;
}
//检查GLFW是否被要求退出
while (!glfwWindowShouldClose(window))
{
//设置清空屏幕所用的颜色
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
//清空颜色缓冲
glClear(GL_COLOR_BUFFER_BIT);
//交换颜色缓冲
//默认情况下,GLFW窗口使用双缓冲。这意味着每个窗口都有两个渲染缓冲区。
//前缓冲区和后缓冲区。前缓冲区是要显示的缓冲区,后缓冲区是要渲染的缓冲区。
//渲染完整个帧后,需要相互交换缓冲区,因此后缓冲区将变为前缓冲区,反之亦然。
glfwSwapBuffers(window);
//检查有没有触发什么事件(比如键盘输入、鼠标移动等)
//并调用对应的回调函数(可以通过回调方法手动设置)
glfwPollEvents();
}
//销毁窗口
glfwDestroyWindow(window);
//使用GLFW的操作后,需要终止GLFW
glfwTerminate();
return 0;
}
void error_callback(int error, const char* description)
{
std::cout << "error:" << error << std::endl;
std::cout << "description:" << description << std::endl;
}
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
//Esc按下则触发WindowShouldClose为true
if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
glfwSetWindowShouldClose(window, GLFW_TRUE);
}
void bufferresize_callback(GLFWwindow* window, int width, int height)
{
//glViewport函数前两个参数控制渲染窗口左下角的位置
glViewport(0, 0, width, height);
}
4.参考
OpenGL学习:https://learnopengl-cn.github.io/
OpenGL了解:https://www.khronos.org/opengl/wiki/Getting_Started
OpenGL相关工具包和API:https://www.khronos.org/opengl/wiki/Related_toolkits_and_APIs
GLFW官网:https://www.glfw.org/
GLAD下载页:https://glad.dav1d.de/
GLFW入门:https://blog.csdn.net/zjz520yy/article/details/83000081
GLAD入门:https://blog.csdn.net/zjz520yy/article/details/83000096