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);//设置主板本号为3glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//设置副版本号为3glfwWindowHint(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(); //终止GLFWreturn -1;}  glfwMakeContextCurrent(window); //将窗口的上下文设置为当前线程的主上下文//初始化GLADif (!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;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#.NET 与 Python 交互

若你要用.NET和Python交互&#xff0c;那么你可以使用两种技术&#xff1a;IronPython 和 Python.NET 。 但两者的基础实现和目标场景都不同&#xff0c;因此如何使用它们也有所不同。 IrconPython简称 IPy , Python.NET 也叫 pythonnet 或 Python for .NET &#xff0c;下面分…

基于Java校园跑腿管理系统设计与实现(源码+部署文档)

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…

《SQL必知必会第五版》第十五章(插入数据)挑战题

1. 使用 INSERT 和指定的列&#xff0c;将你自己添加到 Customers 表中。明确列出要添加哪几列&#xff0c;且仅需列出你需要的列。 INSERT INTO Customers(cust_id,cust_name,cust_address,cust_city,cust_state,cust_zip,cust_country,cust_contact,cust_email) VALUES(…

简单函数_加减乘除

任务描述 对输入的算式进行简单的运算&#xff0c;输出算式结果。运算符只会是加、减-、乘*、除/、求余%、阶乘&#xff01;之一。 输出运算的结果&#xff0c;如果出现除数为零&#xff0c;则输出“error”,如果求余运算的第二个运算数为0&#xff0c;也输出“error”。 输入…

自定义collate_fn函数:应对报错RuntimeError: stack expects each tensor to be equal size

使用BERT或ResNet分别生成文本和图像特征时,由于文本自身长度和图像大小的限制,导致最后形成的特征数据在送入DataLoader时会因为维度不同而报错: RuntimeError: stack expects each tensor to be equal size此时就需要自定义collate_fn函数实现数据的自定义加载功能,下面…

UR5 机器人 URDF 代码阅读

系列文章目录 文章目录 系列文章目录前言一、UR5 URDF 代码二、base_link三、shoulder_pan_joint四、shoulder_pan_trans五、ROS base_link 坐标系到 UR 机器人 Base 坐标系的转换六、与全零TCP&#xff08;工具坐标系&#xff09;重合的工具链接 前言 一、UR5 URDF 代码 <…

算法人生(8):从“注意力算法”看“战胜拖延”(被分心太多版)

现代人拖延产生的原因有很多&#xff0c;比如因为害怕失败而拖延&#xff0c;因为完美主义倾向而拖延&#xff0c;不想走出“舒适区”而拖延等等&#xff0c; 今天我们要针对一个常见的原因“被分心的事情太多”而产生的拖延来看&#xff0c;如何从“注意力算法”的思路中找到些…

类型双关联合体(C++基础)

类型双关 类型双关就是在同样的一个内存中&#xff0c;存储的数据可以用做不同类型的表述。用在底层性能优化的时候&#xff0c;一般使用的时候要非常小心&#xff0c;因为不当的使用可能导致程序的不稳定和不可预测的行为。 int a 5;//double value (double)a;double value…

软考信息系统项目管理师2024上半年报名流程及注意事项

2024年5月软考信息系统项目管理师报名入口&#xff1a; 中国计算机技术职业资格网&#xff08;http://www.ruankao.org.cn/&#xff09; 2024年软考报名时间暂未公布&#xff0c;考试时间上半年为5月25日到28日&#xff0c;下半年考试时间为11月9日到12日。不想错过考试最新消…

Qt Design Studio 软件怎么用(详细+通俗+有趣)

建议&#xff1a;本文长期更新&#xff0c;建议点赞/收藏&#xff01; 1. 啥是Qt Design Studio&#xff1f; Qt Design Studio 是一个用于设计和开发用户界面的工具&#xff0c;特别适合开发跨平台应用程序。它结合了UI设计和开发的工作流程&#xff0c;使得设计师和开发者可…

桌面显示器PD芯片:引领桌面显示技术的新篇章

随着科技的飞速发展&#xff0c;桌面显示器作为人们日常工作与生活中不可或缺的重要设备&#xff0c;其性能与品质也在不断提升。其中&#xff0c;PD芯片作为桌面显示器中的核心组件&#xff0c;发挥着至关重要的作用。本文将对桌面显示器PD芯片进行详细介绍&#xff0c;探讨其…

如何确定ISO体系认证的范围?越大越好是否合理?

什么叫认证范围 ISO认证范围是指企业在申请ISO体系认证时&#xff0c;确定管理体系所涉及的业务范围。这个范围通常包括产品、服务、活动等方面&#xff0c;是企业为了提升管理水平、增强竞争力而选择实施ISO体系认证时需要考虑的重要因素之一。 ISO体系认证的范围主要包括两…

【Leetcode】top 100 二叉树

基础知识补充 完全二叉树&#xff1a;顺序存储&#xff08;数组&#xff09; 非根节点的父节点序号floor((i-1)/2) 序号i的左孩子节点序号2*i1 右孩子节点序号2*i2 一般二叉树&#xff1a;链式存储 结构&#xff1a;left指针指向左子节点&#xff0c;right指针指向右子节点&am…

JAVA 100道题(17)

17.创建一个方法&#xff0c;接受一个整数作为参数&#xff0c;并检查它是否为正数。如果不是&#xff0c;则抛出自定义异常。 首先&#xff0c;你需要定义一个自定义的异常类。在Java中&#xff0c;你可以通过继承 Exception 类来创建自定义异常。然后&#xff0c;你可以创建一…

区区文件操作

一、概念 数据存到内存中&#xff0c;程序退出、掉电数据就丢失了 数据存到硬盘中&#xff0c;就是存储在文件中&#xff0c;数据就不会因为掉电、程序退出就丢失。想要数据持久化&#xff0c;就要使用文件。 二、分类 什么是文件&#xff1f; 硬盘&#xff08;磁盘&#…

springcloud 复习day2~[条件装配]

条件装配: 注解:Condition 定义一个注解 import org.springframework.context.annotation.Conditional;import java.lang.annotation.*;/*** author Gavin*/ Retention(RetentionPolicy.RUNTIME) Target({ElementType.TYPE, ElementType.METHOD}) Documented Conditional(Lo…

ffmpeg拉流并解码

流程 注意事项 版本不同导致的api差异资源安全释放

激光焊接机在不锈钢三角阀制造中的应用与发展

不锈钢三角阀激光焊接机是一种专门用于焊接不锈钢三角阀的高效、精准设备。这种设备在不锈钢三角阀的制造过程中起到了至关重要的作用&#xff0c;其应用主要体现在以下几个方面&#xff1a; ​ 一、激光焊接机在不锈钢三角阀制造中的应用 激光焊接机以其独特的优势&#xff…

力扣450 删除二叉搜索树中的节点 Java版本

文章目录 题目描述思路代码 题目描述 给定一个二叉搜索树的根节点 root 和一个值 key&#xff0c;删除二叉搜索树中的 key 对应的节点&#xff0c;并保证二叉搜索树的性质不变。返回二叉搜索树&#xff08;有可能被更新&#xff09;的根节点的引用。 一般来说&#xff0c;删除…