LearnOpenGL学习笔记—入门02:Hello window

前言

本节笔记对应的内容 你好,窗口
在之前的入门01中我们配置好了环境,下面开始正式的绘制一个窗口。

目标①:打开一个黑窗口

首先我们创建一个main函数,用来实例化glfw的窗口:

int main()
{
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    
    return 0;
}
  • glfwInit函数用来初始化GLFW,
  • glfwWindowHint函数来配置GLFW,
  • MAJOR与MINOR,分别用来指定OpenGL的主版本号和次版本号,
    然后告诉GLFW我们使用的是核心模式(Core-profile)。

接下来创建窗口对象:

	GLFWwindow* window = glfwCreateWindow(800,600,"My OpenGL Game",NULL,NULL);
	if(window == NULL)
	{
		printf("Open window failed.");
		glfwTerminate();
		return - 1;
	}
	glfwMakeContextCurrent(window);

800与600分别是窗口的宽与高,第三个参数为标题。

  • 关于Context
    OpenGL自身是一个巨大的状态机(State Machine):有一系列的变量来描述OpenGL此刻应当如何运行。
    OpenGL的状态通常被称为OpenGL上下文(Context)。
    通常我们使用如下途径去更改OpenGL状态:设置选项,操作缓冲。最后,我们使用当前OpenGL上下文来渲染。

创建完窗口后和错误提醒后,就可以通知GLFW,将我们窗口的上下文设置为当前线程的主上下文了。

接下来初始化GLEW,打开实验性质的功能以及错误提醒:

	glewExperimental = true;
	if (glewInit() != GLEW_OK) 
	{
		printf("Init GLEW failed.");
		glfwTerminate();
		return -1;
	}

在开始渲染之前,需要告诉OpenGL渲染窗口的尺寸大小,即视口(Viewport)。可以通过调用glViewport函数来设置窗口的维度(Dimension):

glViewport(0, 0, 800, 600);
  • 前两个参数X,Y————以像素为单位,指定了视口的左下角(在第一象限内,以(0,0)为原点的)位置。
  • 后两个参数width,height————表示这个视口矩形的宽度和高度,根据窗口的实时变化重绘窗口。在这里插入图片描述

在程序中添加一个while循环,渲染循环(Render Loop),它能在我们让GLFW退出前一直保持运行。下面实现了一个简单的渲染循环:

while (!glfwWindowShouldClose(window)) 
	{
		glfwSwapBuffers(window);
		glfwPollEvents();
	}
  • glfwWindowShouldClose函数在我们每次循环的开始前检查一次GLFW是否被要求退出,如果是的话该函数返回true然后渲染循环便结束了,之后为我们就可以关闭应用程序了。
  • glfwPollEvents函数检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态,并调用对应的回调函数(可以通过回调方法手动设置)。
  • glfwSwapBuffers函数会交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲),它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上。
  • 双缓冲(Double Buffer):
    应用程序使用单缓冲绘图时可能会存在图像闪烁的问题。
    这是因为生成的图像不是一下子被绘制出来的,而是按照从左到右,由上而下逐像素地绘制而成的。
    最终图像不是在瞬间显示给用户,而是通过一步一步生成的,这会导致渲染的结果很不真实。
    为了规避这些问题,应用双缓冲渲染窗口应用程序。
    前缓冲保存着最终输出的图像,它会在屏幕上显示;而所有的的渲染指令都会在后缓冲上绘制。
    当所有的渲染指令执行完毕后,我们交换(Swap)前缓冲和后缓冲,这样图像就立即呈显出来,之前提到的不真实感就消除了。

正确释放/删除之前的分配的所有资源

	glfwTerminate();
	return 0;

实现效果为一个黑窗口:在这里插入图片描述
以下是这一步后main.cpp的完整代码:

#include <iostream>

#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>

int main() {
	
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	
	//Open GLFW Window
	GLFWwindow* window = glfwCreateWindow(800,600,"My OpenGL Game",NULL,NULL);
	if(window == NULL)
	{
		printf("Open window failed.");
		glfwTerminate();
		return - 1;
	}
	glfwMakeContextCurrent(window);

	//Init GLEW
	glewExperimental = true;
	if (glewInit() != GLEW_OK) 
	{
		printf("Init GLEW failed.");
		glfwTerminate();
		return -1;
	}
	
	glViewport(0, 0, 800, 600);
	
	while (!glfwWindowShouldClose(window)) 
	{
		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	glfwTerminate();
	return 0;
	
}

目标②:输入检测与背景颜色

  • 输入检测
    在GLFW中实现一些输入控制,可以通过使用GLFW的几个输入函数来完成。
    比如GLFW的glfwGetKey函数,它需要一个窗口以及一个按键作为输入。这个函数将会返回这个按键是否正在被按下。
    我们将创建一个processInput函数来实现这个功能。
void processInput(GLFWwindow* window){
	if (glfwGetKey(window, GLFW_KEY_ESCAPE )== GLFW_PRESS)
	{
		glfwSetWindowShouldClose(window, true);
	}
}
  • 在渲染循环中调用输入检测
while (!glfwWindowShouldClose(window)) 
	{
		processInput(window);

		glfwSwapBuffers(window);
		glfwPollEvents();
	}
  • 渲染
    渲染指令的结构应该如下所示
// 渲染循环
while(!glfwWindowShouldClose(window))
{
    // 输入
    processInput(window);

    // 渲染指令
    ...

    // 检查并调用事件,交换缓冲
    glfwSwapBuffers(window);
    glfwPollEvents();
}
  • 背景颜色
    我们使用一个自定义的颜色清空屏幕。
    我们在每个新的渲染迭代开始的时候总是希望能清屏,否则上一次迭代的渲染结果仍会被看见。
    可以通过调用glClear函数来清空屏幕的颜色缓冲,它接受一个缓冲位(Buffer Bit)来指定要清空的缓冲,可能的缓冲位有GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT。
    由于现在我们只是设定背景颜色,所以我们只清空颜色缓冲。
	glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
	glClear(GL_COLOR_BUFFER_BIT);

实现的效果应该是一个有颜色的窗口,同时可以按esc退出

在这里插入图片描述以下是这一步后main.cpp的完整代码:

#include <iostream>

#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>

void processInput(GLFWwindow* window){
	if (glfwGetKey(window, GLFW_KEY_ESCAPE )== GLFW_PRESS)
	{
		glfwSetWindowShouldClose(window, true);
	}
}

int main() {
	
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
	
	//Open GLFW Window
	GLFWwindow* window = glfwCreateWindow(800,600,"My OpenGL Game",NULL,NULL);
	if(window == NULL)
	{
		printf("Open window failed.");
		glfwTerminate();
		return - 1;
	}
	glfwMakeContextCurrent(window);

	//Init GLEW
	glewExperimental = true;
	if (glewInit() != GLEW_OK) 
	{
		printf("Init GLEW failed.");
		glfwTerminate();
		return -1;
	}
	
	glViewport(0, 0, 800, 600);
	
	while (!glfwWindowShouldClose(window)) 
	{
		processInput(window);

		glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	glfwTerminate();
	return 0;
	
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值