【OpenGL实战二】完整步骤Window环境初始化OpenGL并创建渲染窗口(亲测!)

这篇是【OpenGL实战一】文章结尾代码的具体详解,也是进入OpenGL编程的第一步!!

在上一节,我们使用glfw和glad创建一个基于VS2015的OpenGL开发环境(Windows)。

在测试代码中,我们并没有搞清楚,这些代码是干什么的。

这一节,我们来仔细分析,并讲解上一节中提到的代码。


思考:想调用OpenGL应该怎么做呢?很简单,请继续往下看

因为我们用到了GLFW和GLAD所以,所以我们需要包含引用它。(没有的请返回看上一节)

#include "glad\glad.h"  
#include "glfw3.h" 

【第一步】初始化GLFW和版本指定。

int main() {

	//初始化GLFW
	glfwInit();									
	//定义OPEN的版本为3.3
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);		//主版本			
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);		//次版本
	//使用核心模式
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	
}

在main函数中,我们调用glfwInit来初始化glfw库。openGL发展到今天已经有非常多的版本。

我们需要在代码中定义我们想用的opengl版本为3.3,采用核心模式Core。这样就完成了。

其实你可以想像,把OpenGL的绘图环境比喻成一块黑板,我们可以在上面画任何内容。

那么,如何创建一块黑板?因为是基于Windows的,哪这块黑板也应该基于Win窗口。



【第二步】创建Window渲染窗口。

用glfw库创建一个windows窗口也非常的简单,指定宽,高,和窗口标题然后make就出来了。

	//创建一个Win窗口
	GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL_01", NULL, NULL);
	if (window==NULL) {
		printf("无法创建 GLFW 窗口 !");
		glfwTerminate();//释放
		return -1;
	}
	glfwMakeContextCurrent(window);

现在Win窗口有了,那么黑板呢?现在我们继续创建一块“黑板”指定这块黑板有多大。

用到的函数就是glViewport(0, 0, width, height); 

但是,窗口万一调整了大小,咱们这块黑板,也应该跟着调整,所以我们定义一个调整尺寸的方法

//渲染尺寸调整
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
	glViewport(0, 0, width, height);
}
把这个方法注册关联到window上,每当窗口尺寸发生变化时,都调用一下重设渲染尺寸,像这样

glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

关于这块黑板,咱们不能直接用它,因为在opengl中规格很多,我们需要交给glad来统一管理。

这时候,glad出场了,初始化一下就可以了

	//加载GLAD
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		printf("初始化GLAD失败 !");
		return -1;
	}


* 小技巧,每次启动时窗口的位置都不固定,对于强迫症来说设置窗口居中是最好的选择:

        //设置窗口居中
	int* winWidth=new int;
	int* winHeight= new int;
	glfwGetWindowSize(window, winWidth, winHeight);
	GLFWmonitor* monitor = glfwGetPrimaryMonitor();
	const GLFWvidmode* mode = glfwGetVideoMode(monitor);
	glfwSetWindowPos(window, (mode->width - *winWidth) / 2, (mode->height - *winHeight) / 2);


【第三步】永不停止的循环。

为什么需要循环?想像我们在黑板上画一个小人,只代表了一帧的图像,并不会动起来。

我们是想要和放电影一样的效果,这就需要将很多帧不停的画出来,在人眼里表现出连续运动的画面。

所以我们定义一个while循环,这个循环一直坚持到等到glfw发出的退出close指令为止。像这样

	// 渲染循环
	while (!glfwWindowShouldClose(window))
	{
	}




【第四步】接受键盘指令和缓冲交换

我们在第三步提到,while循环会一直等到close指令的发出就会退出。

这个指令,可以由很多情况触发,最常见的就是我们按键盘的ESC键,然后退出程序。

接下来,我们在window上绑定ESC,侦听键盘的输入,如果是按下了ESC,咱们就让它退出。


//按下ESC键退出
void processInput(GLFWwindow *window)
{
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);
}

因为这个侦听是持续的,所以我们把它放在while循环中进行调用。processInput(window);

下面科普一下小知识,什么是双缓冲?

双缓冲(Double Buffer)

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


可以发现,如果不使用双缓冲,咱们画到窗口的东西,会产生闪烁的情况。

所以,接下来要调用一下API来交换缓冲区。glfwSwapBuffers(window);


最后,见证奇迹的时候到了!!

该搞的都准备好了。黑板有了,到底要怎么画??别急,在画之前,首先你要学会" 擦黑板 "。

OpenGL中就有“擦黑板”的方法。glClear

而且,除了擦掉黑板里的东西,还可以指定默认把黑板填充成什么底色。glClearColor

接下来,我们用深蓝绿色来填充这块黑板。代码如下:

		// 渲染指令
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

在VS2015中,按调试运行。


好了,这节运行的效果和第一节虽然是一模一样的。但是我相信你已经明白了其中的原理了。

完整C++代码如下,我已经用中文注释好了:

#include "glad\glad.h"  
#include "glfw3.h" 

#include <iostream>

void framebuffer_size_callback(GLFWwindow* window, int width, int height);
void processInput(GLFWwindow *window);



int main() {

	//初始化GLFW
	glfwInit();									
	//定义OPEN的版本为3.3
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);		//主版本			
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);		//次版本
	//使用核心模式
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);


	//创建一个Win窗口
	GLFWwindow* window = glfwCreateWindow(800, 600, "OpenGL_01", NULL, NULL);
	if (window==NULL) {
		printf("无法创建 GLFW 窗口 !");
		glfwTerminate();//释放
		return -1;
	}
	glfwMakeContextCurrent(window);


	//每当窗口尺寸发生变化时,重设渲染尺寸
	glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

	//加载GLAD
	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
	{
		printf("初始化GLAD失败 !");
		return -1;
	}


	// 渲染循环
	while (!glfwWindowShouldClose(window))
	{
		// 输入
		processInput(window);

		// 渲染指令
		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);
	

		// 检查并调用事件
		glfwPollEvents();
		// 交换缓冲
		glfwSwapBuffers(window);
	}

	//释放
	glfwTerminate();
	return 0;
}

//渲染尺寸调整
void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
	glViewport(0, 0, width, height);
}

//按下ESC键退出
void processInput(GLFWwindow *window)
{
	if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
		glfwSetWindowShouldClose(window, true);
}

既然画板都有了,是不是应该在上面画点像样的东西了呢??

你说的对,接下的文章,就将和你一起用OpenGL学画画。

敬请关注吧~

猜你喜欢

转载自blog.csdn.net/sjt223857130/article/details/80038636
今日推荐