OpenGL学习笔记【4】——创建窗口,给窗口添加渲染颜色

 一、前三章节的前情回顾

章节一:上下文(Context)

   OpenGL学习笔记【1】——简介-CSDN博客

      章节一讲述了OpenGL在渲染的时候需要一个Context来记录了OpenGL渲染需要的所有信息和状态,可以把上下文理解成一个大的结构体,它里面记录了当前绘制使用的颜色、是否有光照计算以及开启的光源等。不同的操作系统,都有各自的上下文创建方法,最简单的上下文可以通过GLFW创建。

章节二:GLFW库

OpenGL学习笔记【2】——开发环境配置(GLFW,VS,Cmake),创建第一个项目-CSDN博客

       章节二讲述了一个专门的窗口库:GLFW库,一个轻量级的图形界面框架,GLFW 的主要功能创建并管理窗口和 OpenGL 上下文,同时还提供了处理手柄、键盘、鼠标输入的功能。

      章节二还创建了一个空项目MyFirstOpenGL。

章节三: GLAD库

  OpenGL学习笔记【3】—— GLAD配置-CSDN博客

     章节三讲述了GLAD库是用来管理OpenGL的函数指针的,所以在调用任何OpenGL的函数之前我们需要初始化GLAD,从而让我们能够使用所有OpenGL函数。

    章节三还创建了一个main.cpp文件,代码中引入了GLAD和GLFW的两个库文件。

前三章节准备工作已经完成,接下来可以开始创建窗口了

二、创建窗口步骤

  2.1、初始化GLFW库

   glfwInit()函数:  一般我们使用Glfw库,首先初始化GLFW库,即需要调用glfwInit()得到OpenGL随显卡驱动一起发布的新特性的函数入口地址。

  2.2、 glfwWindowHint配置GLFW

     glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE)

       使用核心模式(Core-profile),在调用一个OpenGL的废弃函数时会产生invalid operation 错误,当意外的使用了不该使用的旧函数时是一个很好的提醒。

    注意:请确认您的系统支持OpenGL3.3或更高版本,否则此应用有可能会崩溃或者出现不可预知的错误,如果你的OpenGL版本低于3.3,检查一下显卡是否支持OpenGL 3.3+(不支持的话你的显卡真的太老了),并更新你的驱动程序,有必要的话请更新显卡。

  2.3、创建一个窗口对象

(1) glfwCreateWindow()函数:创建窗口对象 返回值类型GLFWwindow*

参数1,2为窗口的宽度和高度,参数3是窗口的名字,最后两个参数可以忽略。

glfwCreateWindow 创建了一个宽度为800像素、高度为600像素的窗口。

  注意: 其实处理过的的窗口值是从-1到1的显示,而(0,0)点就是窗口的中心。

(2) glfwMakeContextCurrent(window)函数:

将窗口window设置为当前线程的主上下文,即捕获当前窗口,准备对当前窗口进行画图.

 (3) glfwTerminate(); 终止GLFW,释放资源。

2.4、渲染循环

      为了在主动关闭GLFW之前可以不断绘制,在OpenGL中需要添加一个while循环,我们可以把它称之为渲染循环(Render Loop)。如果没有渲染循环,程序运行的话渲染效果只会出现一次就会快速消失。

 glfwWindowShouldClose(window)函数:检查GLFW是否被要求退出。

2.5、点击本地Windows调试器运行测试

运行结果如下就表示窗口创建成功了

2.6、窗口创建成功,接下来给窗口添加渲染颜色

      上面创建的窗口是白色的,我们给这个窗口上个颜色,但是给窗口上颜色之前,需要先初始化GLAD。

      (1)初始化GLAD

        因为用来给窗口上色的相关函数是openGL的函数由第三章节对于GLAD的介绍我们已经知道在调用任何OpenGL的函数之前需要先初始化GLAD,初始化后我们才能够使用所有的OpenGL函数。

//初始化GLAD
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{
    //初始化失败,即加载函数地址失败,打印错误信息
    std::cout << "Failed to initialize GLAD" << std::endl;
    return -1;
}

    gladLoadGLLoader(GLADloadproc)函数:根据我们编译的系统,GLAD库中用于加载系统相关的OpenGL函数指针地址。参数1为GLADloadproc类型的函数指针地址。这里我们通过GLFW中的glfwGetProcAddress属性获取了函数指针的的地址。

    初始化GLAD后,接下来就能够使用所有OpenGL函数 了,即可以给窗口上色了。

 (2) 给窗口添加渲染颜色(给窗口上色)

        我们要把所有的渲染(Rendering)操作放到渲染循环中,因为我们想让这些渲染指令在每次渲染循环迭代的时候都能被执行。

   既然渲染指令放在渲染循环里,渲染指令又是OpenGL函数,所以说初始化GLAD函数要放在渲染循环代码的前面。

   while (!glfwWindowShouldClose(window))
    {    
        //设置窗口颜色为黑色(参数1,2,3,4对应:R,G,B,A)
         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
         glClear(GL_COLOR_BUFFER_BIT); //清空颜色缓冲
          glfwSwapBuffers(window);
    } 

   glClearColor()函数:清空当前窗口的所有颜色,并且给窗口设置成指定参数的背景色;

   glClear(GL_COLOR_BUFFER_BIT)函数:将缓存清除为预先的设置值(设置窗口为黑色);

   glClear传入的参数是:缓冲位(Buffer Bit),这里我们只关心颜色值,所以只清空颜色缓冲即可。

   颜色缓冲(GL_COLOR_BUFFER_BIT)这个缓冲区更新存储颜色数据;

   深度缓冲(GL_DEPTH_BUFFER_BIT):这个缓冲区存储顶点深度值;

  模板缓冲(GL_STENCIL_BUFFER_BIT):用来做模板测试。模板缓冲类似于深度缓冲。模板测试的结果决定了像素的颜色值是否要被写入到渲染目标,像素的深度值是否要被写入深度缓冲。

     glClearColor函数是一个设置函数,而glClear函数是一个使用的函数,glClear使用了当前设置的颜色给窗口上色
 

glfwSwapBuffers(window)函数交换(Swap)前缓冲和后缓冲.

    为什么要交换缓冲?

       因为电脑绘图是一个个像素逐一画的,需要时间,如果单一缓冲,我们可能会看到具体绘画过程,会造成屏幕闪烁等问题,所以为了解决这个问题,这里用了双缓冲技术,用两个内存区域来保存数据,分为前缓冲区和后缓冲区,前缓冲区用于展示屏幕上的内容,而后缓冲区就用来绘制,然后每一帧开始的时候,将两个缓冲区交换,这样后缓冲区又可以画新的内容。

单缓冲和双缓冲的区别?
       单缓冲:是将所有的绘图指令在窗口上执行,就是直接在窗口上绘图,这样的绘图效率是比较慢的,如果使用单缓冲,而电脑比较慢,你回看到屏幕的闪烁。
     双缓冲:实际上的绘图指令是在一个缓冲区完成,这里的绘图非常的快,在绘图指令完成之后,再通过交换指令(glfwSwapBuffers(window))把完成的图形立即显示在屏幕上,这就避免了出现绘图的不完整,同时效率很高。 一般用OpenGL绘图都是用双缓冲,单缓冲一般只用于显示单独的一副非动态的图像。
   点击运行,查看给窗口上色的效果:

  

三、按下ESC键可以关闭GLFW窗口

        通过章节二我们知道GLFW库提供了处理手柄、键盘、鼠标输入的功能,接下来我们就实现按下Esc键关闭我们创建的窗口。

(1)编写processInput函数

  注意:processInput函数一定要放在main函数前面

//监听键盘输入函数
void processInput(GLFWwindow* window) {
    //按下ESC键,关闭指定窗口
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
    {       
        glfwSetWindowShouldClose(window, true);
    }
}

    glfwGetKey(参数1,参数2):

   参数1:响应窗口对象;参数2:按下的键;返回值:int。
 

    glfwSetWindowShouldClose(参数1,参数2):

   参数1:响应窗口对象,参数2:用来设置是否关闭窗口。

(2)调用processInput函数
     

 glfwPollEvents()函数的作用是处理并接收窗口事件,例如鼠标移动、键盘输入等。通常,该函数需要在每一帧渲染循环中被调用,以便及时地接收并处理用户的输入。

四、释放/删除之前分配的所有资源

  //终止GLFW,释放所有资源====================
    glfwTerminate();

   此章节的代码如下所示:

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>// C++的标准输入输出头文件
//监听键盘输入函数
void processInput(GLFWwindow* window) {
    //按下ESC键,关闭指定窗口
    if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS)
    {       
        glfwSetWindowShouldClose(window, true);
    }
}
int main() 
{
	glfwInit();
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//设置主板本号为3
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//设置副版本号为3
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    //创建窗口对象 返回值类型:GLFWwindow*
    GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);
    if (window == NULL)//创建窗口对象失败,打印错误信息
    {    
        std::cout << "Failed to create GLFW window" << std::endl;//需要引用iostream头文件      
        glfwTerminate(); //终止GLFW
        return -1;
    }  
    glfwMakeContextCurrent(window); //将窗口的上下文设置为当前线程的主上下文

    //初始化GLAD
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        //初始化失败,即加载函数地址失败,打印错误信息
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }
    //渲染循环
    while (!glfwWindowShouldClose(window))
    {    
        //设置窗口颜色为黑色(参数1,2,3,4对应:R,G,B,A)
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT); //清空颜色缓冲
        glfwSwapBuffers(window);
        //检查有没有触发什么事件(比如键盘输入、鼠标移动等)、更新窗口状态
        glfwPollEvents();
        //调用按下Esc键,关闭窗口
        processInput(window);      
    }

   //终止GLFW,释放所有资源====================
    glfwTerminate();
 
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/490129.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaSE系统性总结全集(精华版)

目录 1. 面向对象&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;详解 1.1 面向过程和面向对象的区别 1.2面向对象的三大特性 1.2.1 封装 1.2.2 继承 1.2.3 多态 1.2.4 方法重写和方法重载的区别&#xff08;面试题&#xff09; 1.2.5 访问权限修饰符分…

动听的洗牌游戏(Java篇ArrayList实操)

本篇会加入个人的所谓‘鱼式疯言’ ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

【数仓】DataX软件安装及配置,从mysql同步到hdfs

相关文章 【数仓】基本概念、知识普及、核心技术【数仓】数据分层概念以及相关逻辑【数仓】Hadoop软件安装及使用&#xff08;集群配置&#xff09;【数仓】Hadoop集群配置常用参数说明【数仓】zookeeper软件安装及集群配置【数仓】kafka软件安装及集群配置【数仓】flume软件安…

PyTorch----torch.nn.Linear()函数

torch.nn.Linear是PyTorch中的一个模块&#xff0c;用于在神经网络中实现完全连接层。它表示输入张量的一个线性变换通过将它与一个权矩阵相乘并加上一个偏置项。 下面是torch.nn.Linear的语法: torch.nn.Linear(in_features, out_features, biasTrue)参数&#xff1a; in_f…

干货分享之反射笔记

入门级笔记-反射 一、利用反射破泛型集合二、Student类三、获取构造器的演示和使用1.getConstructors只能获取当前运行时类的被public修饰的构造器2.getDeclaredConstructors:获取运行时类的全部修饰符的构造器3.获取指定的构造器3.1得到空构造器3.2得到两个参数的有参构造器&a…

【项目技术介绍篇】如何从码云gitee下载项目代码

作者介绍&#xff1a;本人笔名姑苏老陈&#xff0c;从事JAVA开发工作十多年了&#xff0c;带过大学刚毕业的实习生&#xff0c;也带过技术团队。最近有个朋友的表弟&#xff0c;马上要大学毕业了&#xff0c;想从事JAVA开发工作&#xff0c;但不知道从何处入手。于是&#xff0…

用 C++ 编码架构图的最佳用例

统一建模语言&#xff08;UML&#xff09;&#xff0c;作为一种实际应用的语言标准&#xff0c;借助一系列架构图呈现建模软件系统。UML 的出现鼓励了自动化软件工具的开发&#xff0c;有助于自动代码生成。UML 图面向对象系统和软件工具&#xff0c;将静态结构和动态行为以可视…

python---协程与任务详解

文章目录 前言一. 基本概念了解与学习1.1 阻塞1.2 非阻塞1.3 同步1.4 异步1.5 多进程1.6 协程 二. 示例操作对比2.1 同步调用2.2 多进程2.3 异步IO 三. 异步协程3.1 定义协程3.2 多任务协程3.3 协程实现3.4 使用 aiohttp3.5 与多进程结合 总结 前言 之前爬虫使用的是requests多…

Docker 【安装MongoDB】

文章目录 前言一、安装二、使用1. 通过权限认证的方式登入2. 基础操作 前言 MongoDB是一个非关系型数据库&#xff0c;它主要的应用场景有这些 相比mysql&#xff0c;MongoDB没有事务&#xff0c;索引之类的东西。最小单位是文档。 可能有人说&#xff0c;为什么这个场景我要…

latex在写算法`\For` 和 `\EndFor` 以及 `FOR` 和 `\ENDFOR` ,报错Undefined control sequence.

这里写目录标题 1. 错误原因2. 进行改正3. 爱思唯尔期刊与施普林格期刊对于算法的格式不太一样&#xff0c;不能直接套用总结 1. 错误原因 我在算法中使用\For&#xff0c;\EndFor 2. 进行改正 换成FOR&#xff0c;\ENDFOR 3. 爱思唯尔期刊与施普林格期刊对于算法的格式不太…

CopyOnWriteArrayList原理

CopyOnWriteArrayList原理 1. 简介 在 ArrayList 的类注释上&#xff0c;JDK 就提醒了我们&#xff0c;如果要把 ArrayList 作为共享变量的话&#xff0c;是线程不安全的&#xff0c;推荐我们自己加锁或者使用 Collections.synchronizedList 方法&#xff0c;其实 JDK 还提供…

【解决】E: 无法获取 dpkg 前端锁 (/var/lib/dpkg/lock-frontend)

常用两个方法 1 杀死之前的相关进程 在提示信息里面有进程号 $ sudo kill 2158 2 强制解锁 sudo rm /var/cache/apt/archives/lock sudo rm /var/lib/dpkg/lock 以上不行时候&#xff0c;更新软件库 sudo apt-get update

锁车锁电曝视频+画像车主:车企的「科技与狠活」

作者 | 辰纹 来源 | 洞见新研社 近日&#xff0c;不少车企远程锁车锁电再度引热议。但车企的“科技狠活”没有最狠只有更狠&#xff0c;仅去年就发生数宗车企泄露车主视频等隐私数据的案例&#xff0c;不仅令当事车主“社死”&#xff0c;甚至成千上万网友发问“自己的车&…

2024中国闪存市场观察:AI助推闪存全面起势?

过去两年&#xff0c;闪存市场一直处于低迷状态&#xff0c;但去年第四季度闪存颗粒资源的上涨&#xff0c;导致闪存产品价格一路上扬&#xff0c;市场遂发生反转。 2024年&#xff0c;中国闪存市场会彻底走向复苏&#xff0c;还是急转直下&#xff1f;中国AI热潮&#xff0c;…

如何撰写高质量渗透测试报告

渗透测试作为信息安全领域的重要环节&#xff0c;其成果的体现形式往往凝聚在最终的渗透测试报告之中。一份优秀的渗透测试报告不仅记录了测试过程的每一个细节&#xff0c;更是指导客户改进安全状况、防范潜在风险的重要依据。下面&#xff0c;我们将深入探讨如何撰写一份详尽…

【最新!红外小目标检测算法HCFNet】

文章目录 摘要1 引言2 相关工作2.1 传统方法2.2 深度学习方法 3 方法3.1 PPA3.2 维度感知选择性整合模块3.3 多稀释通道细化器模块3.4 损失函数设计 4 实验4.1 数据集与评估指标4.2 实现细节4.3 消融和对比 5 结论 论文&#xff1a;HCF-Net: Hierarchical Context Fusion Netwo…

Python篇之网络编程,实现简单的服务端和客户端的内容传输

本小节内容&#xff1a;实现简单的信息交流 文章目录 一、 Socket介绍二、客户端与服务端三、在python中实现网络通信1. 服务端2. 客户端3. 连接测试 一、 Socket介绍 socket (简称 套接字) 模块是其内置的标准库之一&#xff0c;它实现了BSD sockets API&#xff0c;允许开发…

FreeRTOS使用记录

FreeRTOS使用记录 移植STM32F104ZGT6main.c 增加us延时 移植 STM32F104ZGT6 FreeRTOSConfig.h #ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H/*-----------------------------------------------------------* Application specific definitions.** These definition…

ES 进阶知识

索引Index 一个索引就是一个拥有几分相似特征的文档的集合。比如说&#xff0c;你可以有一个客户数据的索引&#xff0c;另一个产品目录的索引&#xff0c;还有一个订单数据的索引。一个索引由一个名字来标识&#xff08;必须全部是小写字母&#xff09;&#xff0c;并且当我们…

C++ STL - 优先级队列及其模拟实现

目录 0. 引言 1. priority_queue 介绍 1.1 构造函数 1.2 priority_queue 接口函数使用 1.3 仿函数 1.4 题目练习 2. priority_queue 模拟实现 2.1基本框架&#xff1a; 2.2 默认构造函数 2.3 基本函数 2.4 堆的向上以及向下调整 0. 引言 优先队列 (priority_queu…