GLFW入门教程

前言

本文章是总结了自己在学习OpenGL的glfw库时的一些理解,主要参考了glfw的官方文档及教程,以及OpenGL教程,作者也是新手,有理解偏差的地方还请大家指正和谅解。

一.简单窗口的创建

包含头文件

#include 

这里定义了glfw库所有的常量、类型以及函数原型,包含了glfw后,就不需要再包含opengl头文件,也不需要包含或者其它平台的头文件,除非你要用到它们特定的api。

int glfwinit(void) /void glfwTerminate(void)

功能:用于初始化glfw库,在绝大多数glfw的函数使用前,都要先初始化glfw库,但是在程序结束前,必须要终止glfw(如果你运行之后vs卡死,很可能是忘了终止glfw),目的是为了释放资源,glfwTerminate会销毁窗口释放资源,因此在调用该函数后,如果想使用glfw库函数,就必须重新初始化。

如果初始化失败,就会返回GLFW_FALSE,在返回前会自动调用glfwTermiate,如果初始化成功,就必须在程序退出前自己手动调用。

线程安全:这个函数只能在主线程上被调用。

在写第一行代码之前,我们需要一个函数glfwSetErrorCallback(error_callback),当其它函数出现fails时,错误就会报告给回调函数,这个函数是为数不多的可以在glfw库初始化前调用的函数。

设置error callback

void error_callback(int error,const char* description) {
	cout << "Error:" << error+description << endl;
}

glfwCreateWindow创建了一个窗口,它可以指定窗口的类型以及尺寸。

GLFWwindow* glfwCreateWindow(int width, int height, const char* title, GLFWmonitor* monitor, GLFWwidnow* share);

glfwDestroyWindow销毁了一个窗口,

void glfwDestroyWindow(GLFWwindow* window);

GLFWwindow* window = glfwCreateWindow(800,600,"first window",NULL,NULL);
//注意要对窗口的返回结果做检查。
if (!window) {
			//窗口创建失败
}

 

void glfwWindowHint(int hint,int value)

功能:这个函数为下一次glfwCreateWindow函数的调用设置hints(hint中文意为暗示),也就是对该函数所创建的上下文环境进行相应的配置,所以这个函数的调用通常在创建窗口的函数glfwCreateWindow前,而且这些hints,设置以后将会保持不变,只能由glfwWindowHint、glfwDefaultWindowHints或者glfwTerminate修改。

列举一下常见的一些window creation hints,官方文档:https://www.glfw.org/docs/latest/window_guide.html#window_hints

GLFW入门教程_第1张图片

void glfwMakeContextCurrent(GLFWwindow* window);

GLFWwindow* glfwGetContextCurrent(void);

当调用opengl的函数时,必须要有一个正确类型的当前上下文,而且在同一时间只有一个上下文可以被设置为一个单线程的当前上下文,每个线程在同一时间只能拥有一个当前上下文(current context),glfwCreateWindow函数可以帮助我们创建一个上下文。

glfw如何能够创建一个正确类型的上下文呢,比如对一个OpenGL3.3版本来说,我们需要明确告诉OpenGL我们使用的是Core-Profile,这部分的设置就需要用到上面的glfwWindowHint:

glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);

这里的参数3我理解的是OpenGL的3.0版本,不知道对不对。。。

对上下文不了解的可以看一些这篇博客:https://mp.csdn.net/postedit/85100637

int glfwWindowShouldClose(GLFWwindow* window);

void glfwSetWindowShouldClose(GLFWwindow* window,int value);

返回指定窗口是否关闭的flag变量,可以在任何线程中被调用。

void glfwSwapBuffers(GLFWwindow* window);

opengl采用双缓冲机制,该函数用于交换前后颜色缓冲区的内容。

双缓冲(Double Buffer)

应用程序使用单缓冲绘图时可能会存在图像闪烁的问题。 这是因为生成的图像不是一下子被绘制出来的,而是按照从左到右,由上而下逐像素地绘制而成的。最终图像不是在瞬间显示给用户,而是通过一步一步生成的,这会导致渲染的结果很不真实。为了规避这些问题,我们应用双缓冲渲染窗口应用程序。缓冲保存着最终输出的图像,它会在屏幕上显示;而所有的的渲染指令都会在缓冲上绘制。当所有的渲染指令执行完毕后,我们交换(Swap)前缓冲和后缓冲,这样图像就立即呈显出来,之前提到的不真实感就消除了。

void glfwPollEvents(void);这个函数主要用来处理已经在事件队列中的事件,通常处理窗口的回调事件,包括输入,窗口的移动,窗口大小的改变等,回调函数可以自己手动设置,比如之前所写的设置窗口大小的回调函数;如果没有该函数,则不会调用回调函数,同时也不会接收用户输入,例如接下来介绍的按键交互就不会被响应

线程安全:该函数只能在主线程被调用。

按键交互

int glfwGetKey(GLFWwindow window,int value);

返回值:GLFW_PRESS/GLFW_RELEASE

关于按键的宏定义,文档如下:https://www.glfw.org/docs/latest/group__keys.html

综合以上知识就可以创建第一个黑色窗口了,代码如下:

#include 
#include 
#include 

using namespace std;

void error_callback(int error, const char* description) {
	cout << "Error:" << error + description << endl;
}

//处理用户输入
void process_input(GLFWwindow* window) {
	if (glfwGetKey(window, GLFW_KEY_ESCAPE)==GLFW_PRESS) {
		glfwSetWindowShouldClose(window,GLFW_TRUE);
	}
}

int main() {
	glfwSetErrorCallback(error_callback);
	if (glfwInit()) {
		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
		glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);

		GLFWwindow* window = glfwCreateWindow(800,600,"first window",NULL,NULL);
		if (!window) {
			cout << "Failed to create window!!!" << endl;
			glfwTerminate();
			return -1;
		}
		glfwMakeContextCurrent(window);

		while (!glfwWindowShouldClose(window))
		{
			process_input(window);
			glfwSwapBuffers(window);
			glfwPollEvents();
		}
		glfwTerminate();
		return 0;
	}
	return -1;
}

在这段代码中,有一些函数是可以去除的,但是在之后的学习中会遇到,读者可以自行删减。

你可能感兴趣的:(OpenGL)