OpenGL入门学习笔记(二)---- 创建窗口

本文介绍了如何使用LearnOpenGL教程进行OpenGL3.3版本的学习,包括准备工作如设置GLFW和GLEW库,创建窗口对象、视口,以及配置窗口选项。着重讲解了游戏循环和窗口事件处理,如键盘回调函数的实现。
摘要由CSDN通过智能技术生成

学习参考网站Learn OpenGL, extensive tutorial resource for learning Modern OpenGL

准备工作

在创建窗口之前,先进行一些必要的准备工作,这里我们采用的是OpenGL3.3版本,事实上这个版本已经可以基本满足初学者的要求,

// GLEW
#define GLEW_STATIC
#include <GL/glew.h>

// GLFW
#include <GLFW/glfw3.h>

首先先引入了glew和glfw两个库,在glew之前我们进行了静态链接,定义GLEW_STATIC宏,因为使用的是glew静态链接库。需要注意的是,有必要在glfw之前引入glew库,因为在包含glew时也同时会引入许多OpenGL必要的依赖文件。

接下来就是对于main中的准备:

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    return 0;
}

在main函数当中,首先,我们调用glfwInit进行初始化,接下来用glfwWindow来配置GLFW(glfw本身是一个开源的语言库,用来创建窗口并处理用户输入,在这里笔者配置好的glfw认为是一个抽象的对象,负责创建以及管理窗口,并针对用户输入进行窗口框架的操作)。对于glfwWindowHint函数,第一个参数代表当前设置选项的名称,很多是以GLFW_为开头的枚举值,第二个参数则是设置这些选项的状态,比如第一第二行我们设置OpenGL版本为3.3,第三个告诉了GLFW使用的是核心模式,第四个则告诉了我们创建的窗口之后不可以被手动放大或缩小。

创建窗口对象

接下来创建一个窗口对象,需要了解的是,这个窗口对象是一个框架的对象,它与后面所说的视口有所差异。

GLFWwindow* window = glfwCreateWindow(1920,1080,"learnOpenGL",glfwGetPrimaryMonitor(), nullptr);
if (window == nullptr)
{
	std::cout << "Failed to create GLFW window" << std::endl;
	glfwTerminate();
	return -1;
}

首先用glfwCreateWindow创建了一个窗口对象,因为我想要一个全屏的效果和原屏幕保持一致,所以我在他的前两个参数设置为1920 * 1080,分别代表了窗口的宽和高占多少个像素。接下来为这个窗口的名称,第四个设置显示器,意思为当前主显示器,也可以设置为nullptr默认为当前显示器,最后一个暂且设置为nullptr,想要进一步了解的可以专门去文档中查看。返回的指针储存在新创建的window当中。

根据创建的窗口对象创建一个视口(viewport)

int width, height;
glfwGetFramebufferSize(window, &width, &height);

glViewport(0, 0, width, height);

通过调用glViewport函数,我们告诉了需要渲染的窗口的大小,其中前两个是窗口左下角的信息, 而对于后两个参数则设定了这个窗口的大小,可以直接设定为具体的数值,在这里通过调用函数glfwGetFramebufferSize获取指定窗口对象的尺寸,并把信息指定到width和height,需要注意的是这里的window是我们先前已经创建的GLFWwindow*类型的窗口对象。

我们不希望窗口在运行后就立刻结束,希望窗口能一直保持并持续响应用户输入,我们需要在程序中添加一个while循环,我们可以把它称之为游戏循环(Game Loop),它能在我们让GLFW退出前一直保持运行。下面几行的代码就实现了一个简单的游戏循环

while(!glfwWindowShouldClose(window))
{
    glfwPollEvents();
    glfwSwapBuffers(window);
}
  • glfwWindowShouldClose函数在我们每次循环的开始前检查一次GLFW是否被要求退出,如果是的话该函数返回true然后游戏循环便结束了,之后为我们就可以关闭应用程序了。
  • glfwPollEvents函数检查有没有触发什么事件(比如键盘输入、鼠标移动等),然后调用对应的回调函数(可以通过回调方法手动设置)。我们一般在游戏循环的开始调用事件处理函数。需要注意这个回调将会在后边得以使用。
  • glfwSwapBuffers函数会交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色的大缓冲),它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上。

    需要注意的是为了规避图像顺序渲染可能出现的闪烁问题,目前的应用程序采用的是双缓冲机制,前缓冲会显示在屏幕上,而所有的渲染指令在后缓冲进行,之后执行完毕后,前后交换(swap),而这个正是我们调用glfwSwapBuffers所实现的。

    最后,在程序结束后,我们需要正确释放删除之前调用GLFW的所有资源,这个通过函数glfwTerminate来实现


     

  • 输入

  • 对于对窗口的键盘输入响应,可以通过glfw的回调函数来实现,当我们设置了按键回调之后,当我们有键盘输入时,会调用对应的回调函数进行处理,
    void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
    {
        // 当用户按下ESC键,我们设置window窗口的WindowShouldClose属性为true
        // 关闭应用程序
        if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
            glfwSetWindowShouldClose(window, GL_TRUE);
    } 

    我们可以定义一个这样的按键回调函数,当用户进行按键输入时调用这个函数,检查如果键入为escape(esc)时,设置窗口WindowShouldClose属性为GL_TRUE,当进行下一次while更新时检测到此属性窗口关闭,之后通过glfwSetKeyCallback注册我们的函数至合适的回调,他接受两个参数,第一个是窗口对象,第二个是要调用的函数指针,当用户有键盘相应时调用指定的函数。
    除了按键回调函数之外,我们还能我们自己的函数注册其它的回调。例如,我们可以注册一个回调函数来处理窗口尺寸变化、处理一些错误信息等。我们可以在创建窗口之后,开始游戏循环之前注册各种回调函数。

    整体代码如下:

    // GLEW
    #define GLEW_STATIC
    #include <GL/glew.h>
    // GLFW
    #include <GLFW/glfw3.h>
    #include<iostream>
    
    //回调函数的声明
    void call_back(GLFWwindow* window, int key, int scancode, int action, int mode);
    int main() {
    	//Init GLFW
    	glfwInit();
    	//Set all options for GLFW
    	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
    	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//设置语言规范版本3.3
    	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//显示模式为核心模式
    	glfwWindowHint(GLFW_RESIZABLE,GL_FALSE);//We can not resize the window we have created.
    
    
    	//Create a window object that we can use for GLFW's functions. 
    	GLFWwindow* window = glfwCreateWindow(1920,1080,"learnOpenGL",glfwGetPrimaryMonitor(), nullptr);
    	if (window == nullptr)
    	{
    		std::cout << "Failed to create GLFW window" << std::endl;
    		glfwTerminate();
    		return -1;
    	}
    	glfwMakeContextCurrent(window);//一直设置窗口为当前环境,直到更换当前环境或者窗口消失
    	//注册键盘回调函数,键盘相应时调用
    	glfwSetKeyCallback(window, call_back);
    
    	// Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
    	//glew让OpenGL能够实现一些扩展功能,但是和glfw一样,使用前需要先初始化
    	glewExperimental = GL_TRUE;
    	if(glewInit() != GLEW_OK)
    	{
    		std::cout << "Failed to initialize GLEW" << std::endl;
    		return -1;
    	}
    	//针对的是已经创建的窗口对象
    	int width, height;
    	glfwGetFramebufferSize(window, &width, &height);
    	glViewport(0, 0, width,height);
    
    	while (!glfwWindowShouldClose(window)) {
    		glfwPollEvents();
    
    		//在这里我们设置了一个屏幕显示的颜色为绿色,
    		glClearColor(0.0,1.0f, 0.0,0.0);//起设置的作用,设置了清除屏幕时使用的颜色,四个参数相当于RGBA
    		glClear(GL_COLOR_BUFFER_BIT);//当调用glClear函数,清除颜色缓冲之后,整个颜色缓冲都会被填充为glClearColor里所设置的颜色,在这里为用绿色来清除屏幕。
    		glfwSwapBuffers(window);
    	}
    
    	glfwTerminate();
    
    	
    	return 0;
    }
    //实现
    void call_back(GLFWwindow* window, int key, int scancode, int action, int mode) {//设置回调函数
    	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
    		glfwSetWindowShouldClose(window, GL_TRUE);
    }

    最终显示结果为一个覆盖全屏的绿色。

  • 20
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值