OpenGL的整体框架
个人理解:OpenGL从代码的理解角度就是一个大型的状态机,不同的渲染指令,就是设定不同区域buffer的值,最后OpenGL统一根据这些buffer计算得出一个最终结果
OpenGL使用的库
- OpenGL的源码是使用C编写的,并且OpenGL只是一个标准,只是确定了函数名还有输入输出结果,具体的函数内容都是各个显卡厂商自己实现的,所以如果我们想要使用其他的编程语言进行调用的话,就需要使用一些第三方集成好的库。
- 上面教程中使用的库GLFW就是可以处理创建OpenGL Context和接受窗口的创建和外部输入的处理。
- glad库是管理OpenGL函数指针的库,方便调用不同的OpenGl函数。
VS2017 库的配置
具体库的资源百度查找,下面指出具体配置
- 包含目录 包括GLfw的include目录 还有glad的include目录
- 库目录 包含GLfw对应版本的lib库目录
- 链接器 添加glfw opengl
- 工程中添加glad.c文件
上面的配置设置完毕后,可以通过下面的包含测试一下,没有错误的话说明配置正确
这里要注意一点,就是你的VS配置的debug x64版本要和你下载的库的版本相对应,否则就算include正常,编译的时候会出现glfw函数的链接错误
#include <glad/glad.h>
#include <GLFW/glfw3.h>
创建简单的Windows窗口
思路
glfw初始化–>窗口创建–>glad初始化–>渲染循环(这里添加键盘输入判定,渲染相关指令)–>关闭
分段解析
//glfw初始化
if (!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //设置opengl为立即渲染模式
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //mac系统需要设置
- glfwInit()初始化glfw,glfwWindowHint主要是设置窗口属性,这里面设置了OpenGL Context版本是3.3,同时渲染模式为立即渲染模式,即不支持旧的固定渲染管线函数,注释掉的是在mac上需要单独添加的代码,否则会报错。
//窗口大小回调
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, 800, 600);
}
//创建窗口
GLFWwindow* window = glfwCreateWindow(800, 600, "Template", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to Create glfw window!" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
- 大部分都能猜得到,这里说明一个注意事项,就是这里存在两个分辨率,其中glfwCreateWindow是实际的窗口大小分辨率,glViewport是OpenGL视口的分辨率,这两个分辨率是可以不一致的,不一致的后果就是OpenGl会绘制部分内容在你的实际窗口外,或者内部。OpenGL内部的分辨率是-1~1,对于横向0·800来说,假如OpenGL的坐标位置是(0.5,0.5),那么它的实际视口位置是(200, 150)。
- glfwSetFramebufferSizeCallback 从名字就可以看出这是当窗口大小发生变化时的回调。
//glad初始化
if (!gladLoadGLLoader(((GLADloadproc))glfwGetProcAddress))
{
std::cout << "glad Init error" << std::endl;
return -1;
}
- glad初始化 固定写法没什么好讲的
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
while (!glfwSetWindowShouldClose(window))
{
processInput(window);
//设置背景颜色
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
-
processInput 处理我们的输入事件,这里只判断了esc键按下的话,设置glfw为退出状态,那么下面的循环中就会判断失败,然后执行glfwTerminate 清空点相关资源,退出程序
-
glfwSwapBuffers 交换屏幕的前后buffer,屏幕的渲染是有两块buffer的,front是当前显示,back是根据OpenGl 进行计算渲染,每次切换帧就是不停切换前后两块buffer
-
glPollEvents 是触发glfw相关回调事件的,例如我们这里的窗口回调,输入回调
-
glClearColor glfwClear 从这两个函数就能看出OpenGL的状态机思想,glClearColor 设置清除颜色状态信息,而glfwClear就是通过GL_COLOR_BUFFER_BIT 这个Target上使用上面的state进行清除,如果修改GL_COLOR_BUFFER_BIT改成其他的Target,那么对应的Target同样会使用设置好的ClearColor
-
最后附上效果图的最终的完整代码
#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
glViewport(0, 0, 800, 600);
}
void processInput(GLFWwindow* window)
{
if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
glfwSetWindowShouldClose(window, true);
}
int main()
{
//glfw初始化
if (!glfwInit())
return -1;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); //设置opengl为立即渲染模式
//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); //mac系统需要设置
//创建窗口
GLFWwindow* window = glfwCreateWindow(800, 600, "Template", NULL, NULL);
if (window == NULL)
{
std::cout << "Failed to Create glfw window!" << std::endl;
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
//glad初始化
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
std::cout << "glad Init error" << std::endl;
return -1;
}
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);
while (!glfwWindowShouldClose(window))
{
processInput(window);
//设置背景颜色
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwTerminate();
return 1;
}