学习网站:LearnOpenGL CN
配置环境
使用vs2019,点击工具->NuGet包管理->管理解决方案的NuGet包管理程序包->浏览->搜索“glew”和“glfw”进行安装
安装完后,进入属性页,点击“连接器”->”添加库目录”->
添加路径“项目名/packages\glew.1.9.0.1\build\native\lib\v110\x64\Debug\static”
然后点击“输入”->添加依赖项
include头文件
#define GLEW_STATIC
#include<GL/glew.h>
#include<GLFW/glfw3.h>
初始化GLFW
glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
glfwInit():初始化GLFW
GLFW_CONTEXT_VERSION_MAJOR:主版本
GLFW_CONTEXT_VERSION_MINOR:次版本
GLFW_OPENGL_CORE_PROFILE:告诉OpenGL使用核心模式
创建窗口
使用glfwCreateWindow来创建一个窗口,然后使用判断window是否为空,为空则释放内存,结束程序
//创建一个窗口
GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, TITLE, nullptr, nullptr);
if (window == nullptr)
{
//释放内存
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwCreateWindow:创建一个窗口
- 参数一:窗口的宽
- 参数二:窗口的高
- 参数三:窗口的标题
- 参数四:设置全屏模式,设置为NULL则为窗口模式
- 参数五:窗口与其上下文共享资源(还不太明白)
glfwMakeContextCurrent:将窗口的上下文设置为当前线程的主上下文
初始化GLEW
glew用来管理OpenGL的函数指针,所以在调用任何OpenGL的函数之前都需要初始化GLEW。
设置glewExperimental为true,这样就能让GLEW在管理OpenGL的函数指针时使用更多的现代化技术,设置为false,在使用OpenGL的核心模式时会出现一些问题
//glew初始化
glewExperimental = true;
if (glewInit() != GLEW_OK)
{
glfwTerminate();
return -1;
}
渲染视口
在正式渲染之前,需要设置渲染窗口的大小和位置,这是所有渲染对象展示的地方。
glViewport(0, 0, WIDTH, HEIGHT);
glViewPort:视口
- 参数1:x轴位置(左下角开始)
- 参数2:y轴位置(左下角开始)
- 参数3:视口宽
- 参数4:视口高
幕后OpenGL会将glviewPort的坐标和位置映射到屏幕上,OpenGL的坐标范围在[-1,1]之间,因此最后的结果是在范围内将位置映射到屏幕上
开始渲染
通不断的循环将渲染对象生成在屏幕上
while (!glfwWindowShouldClose(window))
{
glClearColor(0.2f, 0.3f, 0.5f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwWindowShouldClose():判断窗口是否被关闭,如果关闭了返回true,如果没关闭返回false
glClearColor(RGBA):自定义颜色清空屏幕,参数是rgba的值范围在[0,1]之间
glClear():清空缓冲,上例只关注了颜色,因此值清除颜色缓冲,可能的缓冲位还有,GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT,GL_STENCIL_BUFFER_BIT
glfwSwapBuffers():交换前后缓冲(双缓冲的概念)
glfwPollEvents():检查有没有触发什么事件(如键盘输入,鼠标移动等),更新窗口状态,并调用对应的回调函数(可以通过回调方式手动设置)
最后
清理所有资源并退出
glfwTerminate();
return 0;
最后的呈现结果
一些概念
什么是双缓冲
如果是单缓冲,图像会出现闪烁,生成的图像不是一下子绘制出来的,而是按照从左到右,从上到下逐像素地绘制的。使用双缓冲可以解决这个问题,前缓冲用来保存最终输出的图像,它最终会在屏幕上显示。后缓冲,所有渲染指令执行的地方。当所有渲染指令执行完毕后,我们会让前后缓冲进行交换,让后缓冲交换到前缓冲在屏幕上进行显示,让前缓冲交换到后缓冲执行渲染指令。
设置视口大小
当窗口大小被改变时,视口不会发生改变,因此可以对窗口注册一个回调函数,它会在窗口每次被改变时,调用
void framesize_buffersize_callback(GLFWwindow* window, int width, int height)
{
glViewport(0,0, width, height);
}
使用glfwSetFramebufferSizeCallback进行调用
//当窗口大小改变时,就改变视口大小
glfwSetFramebufferSizeCallback(window, framesize_buffersize_callback);
注意:当窗口第一次显示的时候framesize_buffersize_callback也会被调用