1.OpenGL 着色器详解
2.用Python和OpenGL探索数据可视化(实践篇)-使用几何着色器绘制实体线框(Solid Wireframe)模型
3.OpenGL学习之旅(6)---imgui库使用
4.用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞”
5.OpenGL自学笔记(四)(着色器)
6.OpenGL - 教程 -调试图形学
OpenGL 着色器详解
GLSL语言
GLSL(OpenGL Shading Language)专用于编写着色器,源码通过定义main函数的解析程序片段,指导渲染引擎渲染内容。源码
GLSL语法类似C语言,解析增加特定关键字修饰变量。源码基本结构如下:声明GLSL版本、解析全新众人帮推广页源码模式、源码变量,解析主函数main处理输入输出。源码
输入变量in
GLSL允许有限输入变量,解析硬件决定数量,源码可通过GL_MAX_VERTEX_ATTRIBS查询上限。解析
输出变量out
片段着色器直接输出色值,源码无需与后续阶段关联。解析可通过一致数据类型和名称建立顶点着色器到片段着色器间联系。源码
全局变量
全局变量作用于整个着色器程序,可在多个着色器间共享,通过GL编码获取。
示例:片段着色器中使用全局变量。
顶点着色器与片段着色器
顶点着色器声明位置与颜色变量,片段着色器声明一致输入变量接收颜色,实现数据传递。
数据类型
向量类型定义、重组用于复杂数据结构。
glVertexAttribPointer
设置顶点变量属性,定义步长、偏移与位置,用于配置顶点数据。
顶点数据、着色器配置
顶点着色器声明输入变量,片段着色器接收传递颜色,完成数据流。
着色器程序
着色器程序作为最小绘制单元,由两个着色器决定结果。面向对象封装着色器程序。
加载着色器代码梳理
流程包括:创建着色器对象、附加源码编译、创建程序、绑定与链接。
着色器程序类封装
用Python和OpenGL探索数据可视化(实践篇)-使用几何着色器绘制实体线框(Solid Wireframe)模型
在Python和OpenGL的框架下,通过几何着色器可以更高效地实现三维模型的实体线框(Solid Wireframe)绘制,避免了传统双绘制方法的繁琐。本文将指导你如何在VS Code环境中,通过一步步的软件收藏源码代码修改,来创建一个可以自由旋转、缩放和变换视图的实体线框模型示例。
下面是具体步骤的概述:
1. 确保你的电脑支持OpenGL 4.5,参考《准备工作(一)》和《准备工作(二)》设置开发环境。
2. 在上一节中,我们学习了计算着色器;现在,我们将转向几何着色器,它能一次性生成线框,提升效率。
3. 在`pygl`文件夹中,你需要添加ProgramVFG类,以及solid_wireframe.vs、geom和fs文件,编写几何着色器代码。
4. 在`solid_wireframe_app.py`中,编写主程序,通过鼠标交互控制模型显示和参数调整。
5. 运行代码,你可以直观地观察到实体线框模式下的模型,如克莱因曲面或Breather曲面,颜色和线框颜色都可以自由定制。
完整的教程源代码已上传至Gitee,系列文章的参考内容从基础篇到实践篇,涵盖了OpenGL的各个方面,如光照、纹理、事件处理和高级渲染技术。
通过本节的学习,你将更深入理解如何利用几何着色器提升数据可视化的性能,为你的三维建模和数据分析项目增添实用技巧。
OpenGL学习之旅(6)---imgui库使用
在OpenGL学习之旅的第六部分,我们将探索如何将imgui库集成到我们的项目中,为OpenGL程序增添交互性。首先,我们从GitHub上克隆imgui库的源码,并确保将其编译成动态库以便于链接至可执行程序。在CMakeLists.txt文件中,我们需添加编译imgui库中源文件的路径,同时确保链接到glfw库和opengl库。
在我们的main函数中,包含imgui头文件后,我们进行初始化。随后,JA A源码在渲染循环中创建imgui窗口帧,并显示默认窗口。在渲染部分,我们需要更新imgui窗口,以实现动态交互。最后,在程序结束时释放imgui资源。
通过imgui窗口,我们可以动态调试3D空间变换。首先定义用于动态调试的变量,如旋转轴和旋转角度,以及平移向量,用于调整透视投影变换中的视场角。在渲染循环中,将这些变量添加至imgui窗口中,以便用户能够实时观察3D变换效果。运行程序后,用户能够通过调节参数,如帧率,动态观察3D空间变换。
本文总结了使用imgui进行动态调试参数的流程,并提供了main.cpp与CMakeLists.txt的完整源码。
用Python和OpenGL探索数据可视化(三维篇)- 与照相机“共舞”
本文深入探索使用Python和OpenGL进行三维数据可视化。首先,确保您的设备支持OpenGL 4.5版本,推荐于年之后生产的电脑。其次,配置开发环境,包括VS Code、Python和OpenGL。利用Python和OpenGL,我们能将三维世界的图形映射至二维屏幕,理解空间变换的重要性。
通过绘制三维坐标轴和立方体,我们已经学习了OpenGL如何通过一系列数学变换将三维世界映射至屏幕。本节将重点介绍视图矩阵和投影矩阵,它们是开发人员进行空间变换的关键。您可以通过代码实践更好地理解这些概念。
为了实践,打开VS Code,选择“Open Folder”,在D:\pydev\pygl的basic文件夹下新建文件camera_app.py。输入代码,自由之刃源码运行VS Code,您将看到交互式界面,包含三个滑动条用于控制照相机的位置、目标及视野、近面和远面。通过调整滑动条,可以实时改变照相机的视角,观察三维模型。点击“使用顶点颜色”切换立方体的显示模式,或点击“重置”恢复初始设置。
本文系列提供丰富的资源和代码示例,帮助您深入学习使用Python和OpenGL进行数据可视化。从基础篇到三维篇,每篇文章都详细介绍了OpenGL的使用技巧,旨在让开发者掌握三维数据可视化的核心知识。
欲获取源代码及更多资源,请访问:gitee.com/eagletang/pyg...
OpenGL自学笔记(四)(着色器)
这一章节没有太多新内容,主要是对之前内容的复述。如果你熟悉shadertoy,那么这一部分可能不需要过多解释。更建议阅读资深人士的教程。
着色器(Shader)是一种运行在GPU上的小程序,为图形渲染管道的特定部分提供支持。从基本意义上讲,着色器是一种将输入转换为输出的程序。着色器非常独立,它们之间不能相互通信,唯一的沟通方式是通过输入和输出。
着色器使用GLSL(类似C语言)编写。除了GLSL,还有HLSL、CG等其他语言。GLSL是为图形计算专门设计的,包含针对向量和矩阵的有用特性。
以下是着色器的基础结构。
在顶点着色器中,每个输入变量被称为顶点属性。可声明的顶点属性数量有限,通常由硬件决定。一般至少有个(包含4个分量)的顶点属性可用。
GLSL包含C等其他语言的大部分默认基础类型:int、float、double、闪剪源码unit和bool。同时还有两种容器类型:向量(Vector)和矩阵(Matrix)。
GLSL中的向量是一个可以包含最高4个分量的容器,分量类型是基础类型之一。大多数情况下,使用vecn就足够了。一个拥有4个分量的向量可以通过点访问符号进行访问,分别使用.x、.y、.z和.w来获取第1~4个分量。对于颜色,则使用rgba进行访问,同理对纹理坐标则使用stpq访问相同的分量。
重组是向量分量的一种灵活用法,允许使用原来向量的分量任意组合形成一个新的向量。但是不允许从vec2中获取.z元素,即2维向量不能获取第四个分量。也可以把一个向量作为一个参数传给不同的向量构造函数。
着色器是独立的小程序,但也是整体的一部分。因此,每个着色器都有输入和输出,以便进行数据交流和传递。GLSL定义了in和out关键字专门来实现这个目的。每个着色器使用这两个关键字设定输入和输出,只要一个输出变量与下一个着色器阶段的输入匹配,它就会传递下去。但在顶点和片段着色器中会有所不同。
顶点着色器应该接收特殊形式的输入,否则会效率低下。顶点着色器的输入特殊在于它直接从顶点数据中接收输入。为了定义顶点数据该如何管理,使用location这一元数据指定输入变量,这样我们才可以在CPU上配置顶点属性。我们已经在前面的教程中看过这个了,layout (location = 0)。顶点着色器需要为它的输入提供一个额外的layout标识,以便将其链接到顶点数据。也可以通过在OpenGL代码中使用glGetAttribLocation查询属性位置值(Location)。
另一个例外是片段着色器,它需要一个vec4颜色输出变量,因为片段着色器需要生成一个最终输出的颜色。如果你在片段着色器中没有定义输出颜色,OpenGL会把你的物体渲染为黑色(或白色)。
因此,如果我们打算从一个着色器向另一个着色器发送数据,我们必须在发送方着色器中声明一个输出,在接收方着色器中声明一个类似的输入。当类型和名字都一样的时候,OpenGL就会把两个变量链接到一起,它们之间就能发送数据了(这是在链接程序对象时完成的)。
uniform是一种从CPU中的应用向GPU中的着色器发送数据的方式,但uniform和顶点属性有些不同。首先,uniform是全局的(Global)。全局意味着uniform变量必须在每个着色器程序对象中都是独一无二的,而且它可以被着色器程序的任意着色器在任意阶段访问。其次,无论你把uniform值设置成什么,uniform会一直保存它们的数据,直到它们被重置或更新。
我们可以在一个着色器中添加uniform关键字至类型和变量名前来声明一个GLSL的uniform。从此处开始我们就可以在着色器中使用新声明的uniform了。通过uniform设置三角形的颜色:
这里在片段着色器中声明了一个uniform的四维向量作为最终颜色输出。因为uniform是全局变量,可以在任何着色器中定义它们,而无需通过顶点着色器作为中介,所以不用在顶点着色器中定义这个uniform。
如果声明了一个uniform却在GLSL代码中没用过,编译器会静默移除这个变量,导致最后编译出的版本中并不会包含它,这可能导致几个非常麻烦的错误!
这个uniform现在还是空的;我们还没有给它添加任何数据,所以下面我们就做这件事。我们首先需要找到着色器中uniform属性的索引/位置值。当我们得到uniform的索引/位置值后,我们就可以更新它的值了。这次我们不去给像素传递单独一个颜色,而是让它随着时间改变颜色:
glfwGetTime()获取程序运行秒数,使用sin得到[-1,1]区间的值,最后做一个[0-1]区间的规范化,储存为一个变量。用glGetUniformLocation查询uniform变量的位置值。参数就是着色器程序对象和uniform变量名。如果返回-1,意味着没有找到。最后是通过glUniform4f函数设置uniform变量的值(根据位置值设置变量)第一个参数是位置值,后面就是设置的值了。
查询uniform地址不要求你之前使用过着色器程序,但是更新一个uniform之前你必须先激活程序,因为它是在当前激活的着色器程序中设置uniform的。
现在写一个着色器类用来读取硬盘中的着色器文件,编译并链接它们。
这里把所有的着色器类都放在头文件中。第一行的包含是用来防止链接冲突的,once意思是该头文件只被包含一次。着色器类储存了着色器程序的ID。它的构造函数需要顶点和片段着色器源代码的文件路径,这样可以把着色器源码的文本文件储存在硬盘上。use用来激活着色器程序。所有的set…函数能够查询一个uniform的位置值并设置它的值。
这里我创建了一个新的CPP文件用来定义着色器头文件中的声明内容。
构造函数中是处理着色器文件的读取并编译和链接着色器。而检查编译和链接的函数如下。除此之外还有激活程序,自己额外加了个删除的程序。
uniform的setter函数:
创建一个着色器对象,读取文件路径即可。
有可能这一步会出一点问题,不知道具体包含路径。我这里的../表示上级目录,这里是返回到解决方案文件夹了。
其实可以在构造函数中的catch中打印当前输入的路径,就可以知道路径与资源文件夹中路径是否一致。
最后在渲染循环中渲染:
OpenGL - 教程 -调试图形学
图形编程的确能带来乐趣,但错误的渲染或完全未渲染都会让人沮丧。在与像素打交道时,找到问题源头往往困难重重。与CPU调试不同,OpenGL调试没有控制台输出,不能在GLSL代码中设置断点,也无法检查GPU运行状态。下面介绍一些调试OpenGL程序的技巧,这些技巧将大大帮助你解决问题。
首先,了解OpenGL中的用户错误标记。当你使用OpenGL不当(例如在绑定之前配置缓冲)时,它会检测到错误,并在幕后生成用户错误标记。通过调用glGetError()函数,可以查询这些错误标记并返回错误值。例如,glBindTexture()函数的文档中列出了所有可能生成的用户错误代码。
值得注意的是,glGetError()在每次调用后会清除所有错误标记,因此在循环中调用该函数以检查每帧可能的错误更为合适。在分布式系统(如X)中,glGetError()只会清除一个错误代码标记,这意味着在多次调用之间可能有多个错误发生。
利用glGetError()定位错误来源非常有效,通过在代码中各处调用它,可以快速确定OpenGL错误的源头。此外,可以编写辅助函数将错误代码与错误发生的位置(使用预处理器指令__FILE__和__LINE__)结合打印出来,便于追踪错误。
对于OpenGL 4.3及以上版本,可以使用调试输出拓展,它直接将更详细的信息发送给用户,有助于使用调试器捕捉错误源头。在GLFW中请求调试输出非常简单,只需要在创建窗口之前设置提醒。调试输出上下文启用后,每次不正确的OpenGL指令都会提供大量有用的错误信息。
利用调试输出,可以很容易地找到错误发生的准确行号或调用。通过在特定错误类型或函数顶部设置断点,调试器在抛出错误时捕捉信息,帮助快速定位问题。此外,可以使用glDebugMessageInsert()函数自定义错误输出,方便与使用调试输出的程序或OpenGL代码协同开发。
对于GLSL着色器,虽然无法直接使用如glGetError()的函数,但可以利用输出变量到帧缓冲的颜色通道来快速检查着色器代码的正确性。通过观察视觉结果,可以快速识别变量是否显示了正确的值。这种方法适用于检查法向量、纹理等变量是否正确传递。
确保你的着色器代码符合GLSL规范,可以使用OpenGL GLSL参考编译器进行检查。下载可执行版本或完整源码,将着色器文件作为参数传递,编译器会报告任何规范不符合的情况。
显示帧缓冲的内容是调试的一个好方法,特别是当帧缓冲在幕后运行时。通过简单的着色器编写一个助手函数,可以在屏幕右上角快速显示任何纹理,以便检查帧缓冲输出。这种方法能让你对帧缓冲内容保持持续反馈。
在遇到上述方法无法解决问题时,可以使用第三方调试软件。这些工具通常可以注入OpenGL驱动,拦截各种OpenGL调用,提供大量有用的数据,如性能测试、缓冲内存检查、纹理和帧缓冲附件显示等。适合大规模产品代码开发。
推荐的调试工具包括gDebugger、RenderDoc、CodeXL、NVIDIA Nsight等,它们在不同方面提供强大支持。每款工具都有其优点和适用场景,选择最适合你需求的工具。
用Python和OpenGL探索数据可视化(三维篇)- 创建三维坐标轴类和立方体类
本系列文章讲解使用Python与OpenGL 4.5进行数据可视化开发,确保您的计算机支持OpenGL 4.5版本,建议阅读《准备工作(一)Windows下检测显卡和OpenGL信息》以确认兼容性。继续参阅《准备工作(二)配置Windows下VS Code + Python + OpenGL开发环境》以完成所需开发环境的设置。
上一节我们通过立方体学习了OpenGL的变换矩阵与模型矩阵。紧接着在《用Python和OpenGL探索数据可视化(三维篇)- 你好,坐标轴》一节中我们绘制了三维坐标轴。立方体与坐标轴是三维图形绘制中常见的元素,因此我们将在本节中通过代码重构将它们转化为专门类,以便后续的重复使用。
开始VS Code,使用File菜单下的“Open Folder”功能,打开D:\pydev\pygl并进入common文件夹,新建一个名为shaders的子文件夹。将basic文件夹下的shaders子文件夹中的axes.vs、axes.fs、cube.vs、cube.fs文件复制至common文件夹的shaders文件夹。
在common文件夹中新建axeshelper.py文件,并在其中输入相应代码。同样地,创建cube.py文件并输入对应代码。接着,在common文件夹中建立__init__.py文件,并在其中输入必要的代码。
在basic文件夹中新建一个名为cube_app_v1.py的文件,并在其中输入相应的代码。点击VS Code右上角的三角形图标以运行代码,此时会呈现预期的结果。
借助坐标轴的辅助,图形变换变得清晰且有趣。通过本系列文章中的源代码资源,您可以进一步探索和实践Python与OpenGL的数据可视化开发。
参考系列文章:1.《用Python和OpenGL探索数据可视化(基础篇)- 你好,窗口!》;2.《用Python和OpenGL探索数据可视化(基础篇)- 你好,OpenGL!》;3.《用Python和OpenGL探索数据可视化(基础篇)- 你好,ImGui!》;4.《用Python和OpenGL探索数据可视化(基础篇)- 你好,小不点!》;5.《用Python和OpenGL探索数据可视化(基础篇)- 重构代码“你好,小不点!”》;6.《用Python和OpenGL探索数据可视化(基础篇)- “你好,线段!”》;7.《用Python和OpenGL探索数据可视化(基础篇)- 重构代码组织OpenGL核心对象包pygl》;8.《用Python和OpenGL探索数据可视化(基础篇)- 你好,三角形!》;9.《用Python和OpenGL探索数据可视化(基础篇)- 改进OpenGL程序Program类》;.《用Python和OpenGL探索数据可视化(基础篇)- 你好,矩形!》;.《用Python和OpenGL探索数据可视化(基础篇)- 完善pygl增加索引缓存对象EBO》;.《用Python和OpenGL探索数据可视化(基础篇)- 你好,纹理!》;.《用Python和OpenGL探索数据可视化(基础篇)- 完善pygl增加OpenGL二维纹理对象》;.《用Python和OpenGL探索数据可视化(基础篇)- 细说纹理环绕》;.《用Python和OpenGL探索数据可视化(基础篇)- 细说纹理过滤》;.《用Python和OpenGL探索数据可视化(基础篇)- 处理键盘和鼠标事件》;.《用Python和OpenGL探索数据可视化(三维篇)- 你好,坐标轴》;.《用Python和OpenGL探索数据可视化(三维篇)- 用立方体体验模型矩阵》。
opengl-:源码编译
1 源码编译 + cmake + vscode
系统环境:ubuntu ..6
编译环境: g++9.4 cmake3..3
编译工具:vscode
1.1 glfw源码编译
Release 3.3. · glfw/glfw 下载 glfw-3.3..zip
安装依赖
解压源码文件
cmake配置
编译工程 edgelee / vscode-opengl-tutorial -1-glfw
1.2 glad源码编译
glad.dav1d.de/ 选择配置内容(如图)
生成源文件 glad.zip
解压zip
cmake配置
一级CmakeList
二级CmakeList
编译工程 edgelee / vscode-opengl-tutorial -2-glad
1.3 imgui源码编译(依赖系统OpenGL)
imgui源码下载
github.com/ocornut/imgu...
ubuntu安装opengl
解压zip
cmake配置
一级CmakeList
二级CmakeList
根据makefile内容配置CmakeList(imgui-1..4/examples/example_glfw_opengl3/Makefile)
编译输出 edgelee / vscode-opengl-tutorial -3-imgui-(system-gl)
1.4 imgui源码编译(不依赖系统OpenGL)
imgui源码下载:同1.3
ubuntu安装opengl:不需要(即使安装,不使用)
解压zip:同1.3
cmake配置
一级CmakeList:同1.3
二级CmakeList:去掉OpenGL依赖
编译错误
根据错误提示,修正
imgui-1..4/backends/imgui_impl_glfw.cpp文件的添加
编译结果 edgelee / vscode-opengl-tutorial -3-imgui-(no-system-gl)
2 实例2.1 旋转三角形 glfw +glad
源码文件:glfw-3.3./examples/simple.c(不采用glfw自带glad,修改到自编译glad)
一级CmakeList
二级CmakeList
生成效果 edgelee / vscode-opengl-tutorial -sample-glfw-glad
2.2 gui界面 glfw +imgui
源码文件:imgui-1..4/examples/example_glfw_opengl3/main.cpp
一级CmakeList
二级CmakeList
生成效果 edgelee / vscode-opengl-tutorial -sample-glfw-imgui
2.3 gui界面 glfw +glda +imgui(建议方式)
注:建议采用此方式,openGL api 统一使用 gdal api
源码文件:imgui-1..4/examples/example_glfw_opengl3/main.cpp(修改到 gdal api)
一级CmakeList
二级CmakeList
生成效果 edgelee / vscode-opengl-tutorial -sample-glfw-glad-imgui