最近研究了一下OpenGL, 总结一下. OpenGL是一揽子图形API接口, 很繁琐, 但不难, 难的是线性代数, 线性变换, 矩阵空间变换.
OpenGL是这个组织 khronos.org 搞的, 如果想深入学习, 可以看他们的原始资料.
查了一下, 一般来讲OpenGL需要两个库: GLFW 和 GLAD.
GLFW用msys2安装即可, 比较简单, 就不叙述了, 直接搜 pacman -Ss glfw
GLAD就比较麻烦, 先查看你显卡支持的OpenGL版本, 我的是GeForce 1050Ti, 支持到最新4.6版本, 记住这个版本,
去 https://glad.dav1d.de/
language选C/C++,
specification选 OpenGL,
API选 4.6 即你的显卡支持的版本,
profile选 Core,
Options选Generate a loader,
生成, 下载到你的项目中,
include 头文件 glad.h,
编译时加上 glad.c 实现文件就OK了
当你引入了这两个库,
#include
#include
需要在链接时加上相应的库文件:
-lopengl32 -lglfw3 glad.c
其中 opengl32.lib 是我clang中自带的, 如果不是windows + msys2 + clang工具链, 需要自己找一下.
创建窗口需要的语句:
初始化, 告知OpenGL版本,
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, verMajor);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, verMinor);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
创建窗口, 并设置窗口为当前进程.
window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, title, nullptr, nullptr);
if (window == nullptr)
{
printf("Failed to create GLFW window\n");
glfwTerminate();
}
// 通知GLFW将我们窗口的上下文设置为当前线程的主上下文
glfwMakeContextCurrent(window);
如果需要更改窗口大小, 需要设置相应的回调函数
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
更改窗口的回调函数
// 回调函数, 调整视口大小
void framebuffer_size_callback(GLFWwindow * /*window*/, int width,
int height)
{
// 视口, OpenGL渲染窗口大小
glViewport(0, 0, width, height);
}
这就是例行公事, 必须要有, 没什么道理, 初始化后就可以调用OpenGL的函数了.
// 初始化GLAD
if (gladLoadGLLoader(
reinterpret_cast<GLADloadproc>(glfwGetProcAddress)) == 0)
{
printf("fail to initialize Glad\n");
return -1;
}
为了不让窗口一闪而过, 需要让它进入死循环, 直至跳出循环条件产生.
while(!glfwWindowShouldClose(window)) // 判断跳出条件
{
glfwSwapBuffers(window); // 交换缓冲, 用于平滑输出
glfwPollEvents(); // 捕获事件, 包括输入, 窗口状态, 并调用相应回调
}
完整程序, 只有一个窗口, 按Esc可以退出.
#include
#include
#include
void framebuffer_size_callback(GLFWwindow *window, int width, int height);
void processInput(GLFWwindow *window);
const unsigned int SCR_WIDTH = 800;
const unsigned int SCR_HEIGHT = 600;
auto main() -> int
{
// 初始化GLFW
glfwInit();
// 配置GLFW
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
GLFWwindow *window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL",
nullptr, nullptr);
if (window == nullptr)
{
printf("Failed to create GLFW window\n");
glfwTerminate();
return -1;
}
// 通知GLFW将我们窗口的上下文设置为当前线程的主上下文
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
// 初始化GLAD
if (gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress)) ==
0)
{
printf("fail to initialize Glad\n");
return -1;
}
// glViewport(0, 0, 800, 600);
while (glfwWindowShouldClose(window) == 0)
{
// 输入
processInput(window);
// 渲染指令
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
// 交换缓冲
glfwSwapBuffers(window);
// 检查并调用事件
glfwPollEvents();
}
glfwTerminate();
return 0;
}
// 回调函数, 调整视口大小
void framebuffer_size_callback(GLFWwindow *window, int width, int height)
{
// 视口, OpenGL渲染窗口大小
glViewport(0, 0, width, height);
}
void processInput(GLFWwindow *window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
{
glfwSetWindowShouldClose(window, true);
}
}
经过上面的设置, OpenGL的环境已经搭建好了, 第一个窗口程序已经建立, 为下面的学习打下了坚实的基础,
不过我还是要给你打个预防针, OpenGL比你想象的要更为繁琐, 但据说仍然比 direct X 12 和 vulkan 也就是下一代 OpenGL 要好得多.
加油.