OpenGL学习笔记【1】——简介
一、OpenGL概念
OpenGL (Open Graphics Library,译名:开放式图形库开放式图形库) 是一种用于渲染 2D 和 3D 图形的跨语言、跨平台的编程接口(API)。
二、OpenGL跨语言
OpenGL 是一个 C 语言库,因此理解 C 语言(或 C++)的基本知识是非常有用的。然而,许多其他语言也有 OpenGL 的绑定,值得一提的包括:
(1)JavaScript绑定的WebGL(基于OpenGL ES 2.0在Web浏览器中的进行3D渲染的API);
(2)C绑定的WGL、GLX和CGL;
(3)iOS提供的C绑定;
(4)Android提供的Java和C绑定;
所以你可以选择你最熟悉的语言来学习。
三、OpenGL跨平台
OpenGL 提供了一组底层的图形渲染函数,严格规定了每个函数该如何执行,以及它们的输出值,这些函数可以直接与图形硬件交互,实现高效的图形渲染。至于内部具体每个函数是如何实现(Implement)的,将由OpenGL库的开发者(通常是显卡的生产商)自行决定。
OpenGL被设计为只有输出的,只提供渲染功能,核心API没有窗口系统、音频、打印、键盘/鼠标或其他输入设备的概念,也正是这种限制使得OpenGL允许进行渲染的代码完全独立于它运行的操作系统,允许跨平台开发。
OpenGL没有提供着色器编译器,而是由显卡驱动来完成着色器的编译工作,也就是说,只要显卡驱动支持对GLSL的编译它就能运行,所以能够跨平台。具有强大的通用性和可移植性,可以将其轻松的移植在多个不同的平台上进行二次开发。因为OpenGL本身是一个与硬件无关的软件接口,所以,通用于市面上较为流行的平台:比如,Windows、Unix、Linux、MacOS等。
四、OpenGL扩展特性
OpenGL的一大特性就是对扩展(Extension)的支持,当一个显卡公司提出一个新特性或者渲染上的大优化,通常会以扩展的方式在驱动中实现。扩展可能会引入新功能和新常量,并且可能放松或取消现有的OpenGL函数的限制。然后一个扩展就分成两部分发布:包含扩展函数原型
的头文件和作为厂商的设备驱动。供应商使用扩展公开自定义的API而无需获得其他供应商或Khronos Group的支持,这大大增加了OpenGL的灵活性。
每个扩展都与一个简短的标识符
关系,该标识符基于开发公司的名称。例如,英伟达(nVidia)的标识符是NV。如果多个供应商同意使用相同的API来实现相同的功能,那么就用EXT标志符。这种情况更进一步,Khronos Group的架构评审委员(Architecture Review Board,ARB)正式批准该扩展,那么这就被称为一个“标准扩展”,标识符使用ARB。
OpenGL是一个不断进化的API,新版OpenGL规范会定期由Khronos Group发布,新版本通过扩展API来支持各种新功能。OpenGL 更像是一种显卡驱动标准,由各个硬件厂家适配,各个硬件厂商根据 OpenGL 接口规范编撰对应的驱动,换句话说,对于各个硬件厂商 OpenGL 确实是一个基于 GPU 的软件实现,但是对于普通的应用层开发者 OpenGL 就是一个由硬件厂商提供的驱动程序罢了。
在OpenGL的发展历程中,总是兼顾向下兼容的特性,但是到了一定的程度之后,这些旧有的OpenGL API不再适应时代的需要,还有一些扩展并不是驱动一定要实现的扩展,这些被统一划入可选的Compatibility Profile;而由OpenGL规范规定必须支持的扩展,则是Core Profile,想要支持先进的OpenGL,相应的Core Profile扩展必须被实现。
五、OpenGL 上下文
5.1、Context上下文的理解
OpenGL Context,中文解释就是OpenGL的上下文。OpenGL只是图形API,它只负责渲染,渲染指令执行所需要的那些东西就是Context。
OpenGL在渲染的时候需要一个Context来记录了OpenGL渲染需要的所有信息和状态,可以把它理解成一个大的结构体,它里面记录了当前绘制使用的颜色、是否有光照计算以及开启的光源等。
对于OpenGL的上下文的理解看到一个比较形象的比喻:好比一个画家在画图,OpenGL就是这个画家(可以发出各种指令),而画家作画需要用到的画笔、画布等东西就是Context,Context的切换就像画家同时作多幅画,当要画另外一幅画的时候,画家需要放下原来的画笔,拿起了另外一幅画所需要的画笔。
5.2、Context上下文的历史版本
(1)在OpenGL 3.0版本之前,OpenGL创建Context都是一致的;
(2)但是从OpenGL 3.0开始,为了摆脱历史的“包袱”,OpenGL想要彻底的废弃掉之前的许多特性,但是无奈市面上已经有大量依赖OpenGL之前版本的代码,导致OpenGL维护小组的这一想法难以付诸实施, OpenGL 3.0 引入了废弃机制,标记了许多OpenGL的函数是废弃的(但是3.0并没有真正移除它们,也就是说3.0版本仍然是一个可以向后兼容的Context);
(3)在OpenGL 3.1的发布删除了之前3.0标记的过时函数(固定管线相关的函数),但是为了之前的OpenGL代码可用, 引入了一个扩展ARB_compatibility,这个扩展可以让OpenGL 3.1支持之前的OpenGL固定管线的内容,
(4)OpenGL 3.2中开始引入了OpenGL Context的一些分类,正式引入了模式的概念(Profile),之后随着版本发展到OpenGL 3.3,一切算是确定下来。
(5)到了OpenGL3.3之后,OpenGL的context profile分为了两个版本,core pfofile和compatibility profile,前者表示删除任何标记为deprecated(弃用)的功能,后者则表示不删除任何功能。
5.3、创建上下文context使用的图形界面框架
不同的操作系统,都有各自的上下文创建方法和设置当前上下文的API,最简单的上下文可以通过Glut或是Glfw创建,相比较而言glfw是一个轻量级的图形界面框架,托管在 www.glfw.org,现在非常的活跃,如果新入门可以优先考虑glfw,相关的教程网上也比较多。
使用glfw创建一个窗口,并使该窗口的上下文成为当前上下文:
// 设置窗口提示glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // OpenGL主版本号glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // OpenGL次版本号glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 使用核心模式// 创建窗口GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);if (window == NULL) {glfwTerminate();return -1;}// 使窗口上下文当前上下文glfwMakeContextCurrent(window);
创建了绘制上下文,并设置为当前上下文以后,还不能使用OpenGL最新的特性,
一般我们使用Glfw库,首先初始化GLFW库,即需要调用glfwInit(),:得到OpenGL随显卡驱动一起发布的新特性的函数入口地址。
//初始化GLFW,得到OpenGL随显卡驱动一起发布的新特性的函数入口地址glfwInit();//下面glfwWindowHint函数配置GLFW====================glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//设置主板本号为3glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//设置副版本号为3glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//核心模式(Core-profile)//参数1:选项的名称。可以从很多以GLFW_开头的枚举值中选择//参数2:接受一个整型,用来设置这个选项的值//设置版本号为3.3版本,需要告诉GLFW我们要使用的OpenGL版本是3.3//GLFW会在创建OpenGL上下文时做出适当的调整。//这也可以确保用户在没有适当的OpenGL版本支持的情况下无法运行//如果你使用的是Mac OS X系统,你还需要解除下面这行代码的注释//glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);// 创建窗口对象GLFWwindow* window = glfwCreateWindow(800, 600, "LearnOpenGL", NULL, NULL);if (window == NULL) {//创建窗口对象失败,打印错误信息std::cout << "Failed to create GLFW window" << std::endl;//需要引用iostream头文件//终止GLFWglfwTerminate();return -1;}//参数1:窗口宽//参数2:窗口高//参数3:窗口标题(名字)//参数4,参数5暂时忽略//返回值类型:GLFWwindow*:我们会在其它的GLFW操作中使用到// 使窗口上下文当前上下文glfwMakeContextCurrent(window);
5.4、线程私有
OpenGL的绘制命令都是作用在当前的Context上,这个Current Context是一个线程私有(thread-local)的变量,也就是说如果我们在线程中绘制,那么需要为该线程制定一个Current Context的,当多个线程参与绘制任务时,需要原线程解绑再重新绑定新的线程。多个线程不能同时指定同一个Context为Current Context,否则会导致崩溃。
六、OpenGL的开发模式
6.1、立即渲染模式 (Compatibility Profile)
Compatibility Profile兼容之前的OpenGL固定管线的内容,也可以使用Core Profile中的内容。
早期的OpenGL使用立即渲染模式(Immediate mode,也就是固定渲染管线),OpenGL 3.2版本以前都是该模式,该模式固定以glBegin开始绘制,以glEnd结束绘制,明确规定了先做什么后做什么,有一套固定的函数和执行流程,开发者可以“傻瓜式”的使用这些函数来实现渲染效果,它面向过程,比较简单、易于理解,但是灵活性(固定的执行流程)和性能都较差(CPU与GPU通信频繁)。
6.2、 核心模式(Core Profile)
核心模式即着色器渲染模式,从3.2版本开始废弃了立即渲染模式,开发者通过编写shader来完成图形的渲染,常见的shader有vertex shader和fragment shader,这种模式较为灵活和高效,但是比较复杂。
从OpenGL3.2开始,规范文档开始废弃立即渲染模式,并鼓励开发者在OpenGL的核心模式(Core-profile)下进行开发,这个分支的规范完全移除了旧的特性。当使用OpenGL的核心模式时,OpenGL迫使我们使用现代的函数。当我们试图使用一个已废弃的函数时,OpenGL会抛出一个错误并终止绘图。
现今,更高版本的OpenGL已经发布(写作时最新版本为4.6),你可能会问:既然OpenGL 4.6 都出来了,为什么我们还要学习OpenGL 3.3?答案很简单,所有OpenGL的更高的版本都是在3.3的基础上,引入了额外的功能,并没有改动核心架构。新版本只是引入了一些更有效率或更有用的方式去完成同样的功能。因此,所有的概念和技术在现代OpenGL版本里都保持一致。当你的经验足够,你可以轻松使用来自更高版本OpenGL的新特性。
除了core profile(核心渲染模式)和compatibility profile(立即渲染模式)外,还有一种模式:foward compatibility,这个表示所有标记为deprecated的函数都禁用,这个模式只对opengl3.0及以上的版本有效。但这个选项对OpenGL 3.2+ compatibility Profile Context没有任何作用。
七、OpenGL需要了解的技术和知识
1、计算机图形学基础:理解基本的计算机图形学概念,如向量、矩阵、变换、光照、纹理等,可以帮助你更好地理解和使用 OpenGL。这些主题通常在计算机图形学的入门课程中介绍。
2、线性代数:在计算机图形学中,我们经常需要处理 2D 或 3D 空间中的点和向量,这需要一些线性代数的知识。至少要熟悉向量的加法、减法和点积,以及如何使用矩阵进行变换。
3、计算机硬件:理解计算机硬件,特别是图形处理器 (GPU) 的基本工作原理,可以帮助你理解 OpenGL 的许多设计决策,以及为什么某些操作比其他操作更快。
4、IDE 和调试工具:熟悉一个集成开发环境(如 Visual Studio、Eclipse 或者 PyCharm)将会对你编写和调试代码非常有帮助。此外,学习使用像 gDEBugger 或者 RenderDoc 这样的 OpenGL 调试工具也是很有用的。
5、API 文档和教程:熟悉 OpenGL 的官方文档(或你正在使用的语言绑定的文档)。这将是你在学习和使用 OpenGL 时的重要资源。同时,还有许多优秀的在线教程,如https://learnopengl.com/Getting-started/OpenGL;https://learnopengl-cn.github.io/.
相关文章:
OpenGL学习笔记【1】——简介
一、OpenGL概念 OpenGL (Open Graphics Library,译名:开放式图形库开放式图形库) 是一种用于渲染 2D 和 3D 图形的跨语言、跨平台的编程接口(API)。 二、OpenGL跨语言 OpenGL 是一个 C 语言库,因此理解 C 语言(或 C)的…...
C语言课后作业 20 题+考研上机应用题
题目 1: 计算圆的面积 描述: 输入圆的半径,计算并输出圆的面积。 题目 2: 判断一个年份是否为闰年 描述: 输入一个年份,判断并输出该年份是否为闰年。 题目 3: 计算并输出斐波那契数列的前10个数 描述: 输出斐波那…...
macOS上基于httpd-dav搭建WebDav服务
文章目录 配置 Apache httpd修改 ServerName启动验证 httpd 服务启用 Dav 扩展服务配置 配置 httpd 扩展 Dav 服务设置共享目录文件夹配置 DavLockDB 目录创建 WebDAV 访客用户 httpd-dav.conf 主要改动部分BasicDigest共享多个目录 授予 httpd 完全磁盘访问权限验证更新配置重…...
Java-设计模式-单例模式
单例模式 从单例加载的时机区分,有懒汉模式/饥饿模式。 从实现方式区分有双重检查模式,内部类模式/Enum模式/Map模式等。在《Effective Java》中,作者提出利用Enum时实现单例模式的最佳实践。 内容概要 实现单例模式的几个关键点 利用Enu…...
图片html5提供的懒加载与vue-lazyload的区别
原生HTML lazy loading特性 <img src"/images/ocean.jpeg" alt"Ocean" loading"lazy"> loading"lazy" 是HTML5的一个原生特性,它允许浏览器延迟加载图片直至图片距离视口很近或者即将进入视口时。这是一种由浏览器…...
golang 根据某个特定字段对结构体的顺序进行排序
文章目录 方法一方法二方法三 在Go语言中,我们可以使用 sort.Slice() 函数对结构体进行排序。假设你有一个结构体,并且希望根据其中的某个字段进行排序,你可以使用自定义的排序函数。 方法一 下面是一个示例代码,假设有一个包含…...
React Router 参数使用详解
React Router 参数使用详解 React Router 是 React 中用于处理路由的常用库,它提供了丰富的功能来管理应用程序的导航和路由状态。在 React Router 中,我们经常需要使用不同类型的参数来处理路由信息,包括 params 参数、search 参数和 state…...
Vue中$set用法解析
当一个 Vue 实例被创建时,它向 Vue 的响应式系统中加入了其 data 对象中能找到的所有的属性。当这些属性的值发生改变时,视图将会产生“响应”,即匹配更新为新的值,但是遇到以下情况不会进行数据的双向绑定。 当你利用索引直接改…...

进制,码制及其表示范围
一 进制 1 常见的进制及其简写 十进制(Dec)二进制(Binary)十六进制(Hex)八进制(Octal) 2 进制之间的相互转换 二 码制 1 常用的码制 三 各码制在定点整数时表示的范围 个人推导…...

钡铼技术R40工业4G路由器加速推进农田水利设施智能化
钡铼技术R40工业4G路由器作为一种先进的通信设备,正在被广泛应用于各行各业,其中包括农田水利设施的智能化改造。通过结合钡铼技术R40工业4G路由器,农田水利设施可以实现更高效的管理和运营,提升农田灌溉、排水等工作效率…...

基于龙芯2k1000 mips架构ddr调试心得(一)
1、基础知识 DDR2的I/O频率是DDR的2倍,也就是266、333、400MHz。 DDR3传输速率介于 800~1600 MT/s之间 DDR4的传输速率目前可达2133~3200 MT/s 2k1000内存:板载2GB DDR3 ,可选4GB 使用龙芯芯片最好用他们自己的Bo…...

智能合约语言(eDSL)—— 使用rust实现eDSL的原理
为理解rust变成eDSL的实现原理,我们需要简单了解元编程与宏的概念,元编程被描述成一种计算机程序可以将代码看待成数据的能力,使用元编程技术编写的程序能够像普通程序在运行时更新、替换变量那样操作更新、替换代码。宏在 Rust 语言中是一种功能&#x…...

敏捷开发——elementUI/Vue使用/服务器部署
1. 创建vue项目 2. 安装element-ui组件库 npm i -S element-ui或 npm install element-ui3. 在main.js中导入element-ui组件 import ElementUI from element-ui import element-ui/lib/theme-chalk/index.css Vue.use(ElementUI)element-ui 组件库地址:Element …...
uniapp 使用sqlite时无法读取到db文件中的数据
问题 {“code”:-1404,“message”:“android.database.sqlite.SQLiteException: no such table: user (Sqlite code 1): , while compiling: select * from user, (OS error - 2:No such file or directory),http://ask.dcloud.net.cn/article/282”} at pages/index/index.vu…...

Linux 网络接口管理
为了更深入的了解linux系统,为此做出网络接口管理的知识总结。看起来麻烦,其实一点都不难,相信多看多了解总会是没错的!❤️❤️ 一起加油吧!✨✨🎉🎉 文章目录 前言一、网络配置的文件介绍二、…...
【设计模式】Java 设计模式之模板策略模式(Strategy)
策略模式详解:模式结构、实现与应用场景 一、策略模式概述 策略模式是一种行为设计模式,它使得算法可以独立于使用它的客户端变化。策略模式使得算法可以在运行时切换,从而增强了系统的灵活性和可维护性。在策略模式中,我们定义…...

SpringBoot项目前端Vue访问后端(图片静态资源) 配置
静态资源配置 Configuration public class WebMvcConfig extends WebMvcConfigurationSupport {Value("${file.save-path}")private String fileSavePath;Overrideprotected void addResourceHandlers(ResourceHandlerRegistry registry) {//映射本地文件夹registry…...
colab中数据集保存到drive与取出的方法
from google.colab import drive drive.mount(/content/drive) 一、下载数据集 from datasets import load_dataset max_length 32 # Maximum length of the captions in tokens coco_dataset_ratio 50 # 50% of the COCO2014 dataset# Load the COCO2014 dataset for tr…...
React 应该如何学习?
学习 React 是现代 Web 前端开发中的重要一步,因为它是一个流行且强大的 JavaScript 库,用于构建用户界面。React 的学习过程需要掌握一系列的概念、技术和最佳实践。 1. 基础知识 1.1 HTML、CSS 和 JavaScript React 本质上是一个 JavaScript 库&…...

跨平台无缝操作:ShareMouse让多电脑协同更高效
ShareMouse是一款功能强大的鼠标和键盘共享软件,它支持多台计算机之间的无缝连接,让用户能够通过一套键鼠设备轻松控制多台电脑,提高工作效率。此外,ShareMouse还具备剪贴板共享、文件拖放等功能,实现不同计算机间的便…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
TCP/IP 网络编程 | 服务端 客户端的封装
设计模式 文章目录 设计模式一、socket.h 接口(interface)二、socket.cpp 实现(implementation)三、server.cpp 使用封装(main 函数)四、client.cpp 使用封装(main 函数)五、退出方法…...
【大厂机试题解法笔记】矩阵匹配
题目 从一个 N * M(N ≤ M)的矩阵中选出 N 个数,任意两个数字不能在同一行或同一列,求选出来的 N 个数中第 K 大的数字的最小值是多少。 输入描述 输入矩阵要求:1 ≤ K ≤ N ≤ M ≤ 150 输入格式 N M K N*M矩阵 输…...
宠物车载安全座椅市场报告:解读行业趋势与投资前景
一、什么是宠物车载安全座椅? 宠物车载安全座椅是一种专为宠物设计的车内固定装置,旨在保障宠物在乘车过程中的安全性与舒适性。它通常由高强度材料制成,具备良好的缓冲性能,并可通过安全带或ISOFIX接口固定于车内。 近年来&…...