基于GLUT的PyOpenGL的使用
1. GLUT概述
OpenGL只是一种规范,不仅语言无关,而且平台无关。规范只字未提获得和管理OpenGL上下文相关的内容,而是将这些作为细节交给底层的窗口系统。出于同样的原因,OpenGL纯粹专注于渲染,而不提供输入、音频以及窗口相关的API
OpenGL Utility Toolkit (GLUT) 是一个具有 ANSI C 和 FORTRAN 绑定的编程接口,用于编写独立于窗口系统的 OpenGL 程序。该工具包支持以下功能:
多个用于OpenGL渲染的窗口
回调驱动的事件处理
复杂的输入设备
简单的级联弹出菜单
......
参考:1 Introduction (opengl.org)
GLUT简化了使用OpenGL渲染的程序实现。GLUT 应用程序编程接口 (API) 只需要很少的例程来显示使用 OpenGL 渲染的图形场景。GLUT 根据其功能在逻辑上组织成多个子 API。子 API 包括:
初始化
命令行处理、窗口系统初始化和初始窗口创建状态由这些例程控制
开始事件处理
此例程进入 GLUT 的事件处理循环。此例程永远不会返回,并且它会根据需要不断调用 GLUT 回调
窗口管理
这些例程创建和控制窗口
叠加管理
这些例程建立和管理窗口的叠加
菜单管理
这些例程创建和控制弹出菜单
回调注册
这些例程注册要由 GLUT 事件处理循环调用的回调
颜色索引色彩映射表管
这些例程允许操作窗口的颜色索引色彩映射表
状态检索
这些例程允许程序从 GLUT 中检索状态
字体呈现
这些例程允许呈现笔画和位图字体
几何形状渲染
这些例程允许渲染 3D 几何对象,包括球体、圆锥体、二十面体和茶壶
2. GLUT的使用
笔者这里使用的是PyOpenGL包及其包含的GLUT绑定
PyOpenGL的安装参考:PyOpenGL的安装与错误解决 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com)
本文的逻辑流程参考GLUT的API文档:Contents (opengl.org)
2.1 初始化
以 glutInit
- 前缀开头的例程用于初始化 GLUT 状态。主要的初始化例程是 glutInit()
,在 GLUT 程序中只应调用一次。在 glutInit()
之前,不应调用任何非 glutInit 前缀的 GLUT
或 OpenGL 例程
其他 glutInit
- 例程可以在 glutInit()
之前调用。原因是这些例程可用于设置默认窗口初始化状态,这些状态可能由在 glutInit()
中完成的命令处理修改。例如, 可以在 glutInitInit 之前调用 glutInitWindowSize(400, 400),
以指示 400 x 400 是程序的默认窗口大小。
在 glutInit()
之前设置初始窗口大小或位置允许 GLUT 程序用户使用命令行参数指定初始大小或位置
glutInit()
将初始化 GLUT 库,并与窗口系统建立会话
glutInit()
还处理命令行选项,但特定选项解析取决于窗口系统
初始化的相关API有:
glutInitWindowPosition
初始窗口位置,初始值为 -1 和 -1。如果初始窗口位置的 X 或 Y 分量为负数,则实际窗口位置由窗口系统确定
glutInitWindowSize
初始窗口大小,初始值为 300 x 300。 初始窗口大小组件必须大于零。这些初始信息可以使用回调函数修改
glutInitDisplayMode
设置初始显示模式,假定想要一个有单缓冲区,深度缓冲区的RGB窗口,用“或“(|)操作符来建立你想要的显示模式
glutInitDisplayMode(GLUT_RGB|GLUT_SINGLE|GLUT|DEPTH)
,更多可用参数见官方文档2.3 glutInitDisplayMode (opengl.org)
Python代码:
# 引入GLUT库
from OpenGL.GLUT import *
glutInit()
'''
进行各种初始化
'''
2.2 窗口管理
GLUT初始化以后,需要创建窗口,才能进行渲染
GLUT 支持两种类型的窗口:顶级窗口和子窗口。这两种类型都支持 OpenGL 渲染和 GLUT 回调
相关的API有:
- 4.1 glutCreateWindow
- 4.2 glutCreateSubWindow
- 4.3 glutSetWindow, glutGetWindow
- 4.4 glutDestroyWindow
- ......
对于初学者来说,glutCreateWindow
应该是使用最多的函数
int glutCreateWindow(char *name)
创建一个顶级窗口,需要注意的是,参数是用作窗口名称的 ASCII 字符串,不是string
Python代码:
#通过b前缀将字符串转换成 bytes
glutCreateWindow(b"First")
2.3 注册回调
GLUT 支持许多回调来响应事件。有三种类型的回调:窗口、菜单和全局。窗口回调指示何时重新显示或改变窗口的形状、窗口的可见性何时更改以及输入何时可用于窗口
支持回调函数的API有:
- 7.1 glutDisplayFunc
- 7.2 glutOverlayDisplayFunc
- 7.3 glutReshapeFunc
- 7.4 glutKeyboardFunc
- 7.5 glutMouseFunc
- ......
glutDisplayFunc
算得上是使用最多的注册回调函数,图形的绘制离不开这个API
glutDisplayFunc(void (*func)(void))
设置当前窗口的显示回调
当 GLUT 确定需要重新显示窗口的正常平面时,将调用窗口的显示回调
Python代码:
def drawFunc():
'''
绘制函数
'''
#注册绘制函数为显示的回调函数,将会不停调用来绘制
glutDisplayFunc(drawFunc)
2.4 开始事件处理
在 GLUT 程序完成初始设置(如创建窗口和菜单)后,GLUT 程序通过调用 glutMainLoop()
进入 GLUT 事件处理循环
此例程在 GLUT 程序中最多应调用一次。一旦调用,此例程将永远不会返回。它将根据需要调用已注册的任何回调
Python代码:
glutMainLoop()
2.5 小结
虽然笔者只讲述了上述几个API,但是绘制图形已经足够,代码小结如下:
# 引入GLUT库
from OpenGL.GLUT import *
glutInit()
'''
进行各种初始化
'''
#通过b前缀将字符串转换成 bytes
glutCreateWindow(b"First")
def drawFunc():
'''
绘制函数
'''
#注册绘制函数为显示的回调函数,将会不停调用来绘制
glutDisplayFunc(drawFunc)
glutMainLoop()
3. 渲染
渲染是OpenGL的任务,而GLUT是提供渲染的环境(包括窗体等)
上述步骤已经建立了渲染的环境,在这里,将完善渲染函数,渲染出图形
3.1 清除绘制
在每个新的渲染迭代开始的时候我们总是希望清屏,否则我们仍能看见上一次迭代的渲染结果(这可能是你想要的效果,但通常这不是)
我们可以通过调用glClear函数来清空屏幕的颜色缓冲,它接受一个缓冲位(Buffer Bit)来指定要清空的缓冲,可能的缓冲位有GL_COLOR_BUFFER_BIT,GL_DEPTH_BUFFER_BIT和GL_STENCIL_BUFFER_BIT。由于现在我们只关心颜色值,所以我们只清空颜色缓冲
除了glClear之外,我们还调用了glClearColor来设置清空屏幕所用的颜色。当调用glClear函数,清除颜色缓冲之后,整个颜色缓冲都会被填充为glClearColor里所设置的颜色
Python代码:
glClearColor(0.2, 0.3, 0.3, 1)
glClear(GL_COLOR_BUFFER_BIT)
3.2 绘制图像
绘制流程终究不是几句话可以说完的,这里笔者使用GLUT自带的茶壶进行绘制
glutSolidTeapot(GLdouble size)
和glutWireTeapot(GLdouble size)
分别渲染固体或线框茶壶。生成茶壶的表面法线和纹理坐标。茶壶是使用 OpenGL 评估器生成的
参数size
为茶壶的相对大小
Python代码:
glutSolidTeapot(0.5)
3.3 刷新缓冲
OpenGL是使用一条渲染管线线性处理命令的,一般情况下,我们提交给OpenGL的指令并不是马上送到驱动程序里执行的,而是放到一个缓冲区里面,等这个缓冲区满了再一次过发到驱动程序里执行;很多时候只有几条指令是填充不满那个缓冲区的,就是说这些指令根本没有被发送到驱动里
glFlush()是OpenGL中的函数,用于强制刷新缓冲,保证绘图命令将被执行,而不是存储在缓冲区中等待其他的OpenGL命令
Python代码:
glFlush()
# glFinish()也可
3.4 小结
利用上述所有步骤的代码,我们已经可以绘制一个图形
全部的Python代码:
# 引入GLUT、OpenGL库
from OpenGL.GLUT import *
from OpenGL.GL import *
glutInit()
'''
进行各种初始化
'''
#通过b前缀将字符串转换成 bytes
glutCreateWindow(b"First")
def drawFunc():
'''
绘制函数
'''
glClearColor(0.2, 0.3, 0.3, 1)
glClear(GL_COLOR_BUFFER_BIT)
glutSolidTeapot(0.5)
glFlush()
#注册绘制函数为显示的回调函数,将会不停调用来绘制
glutDisplayFunc(drawFunc)
glutMainLoop()
绘制的结果:
4. 参考文档
[2]PyOpenGL的安装与错误解决 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com)
[3]OpenGL---GLUT教程(二) GLUT初始化 - 杨溪 - 博客园 (cnblogs.com)
[5]【OpenGL】glFinish()和glFlush()函数详解-转 - vranger - 博客园 (cnblogs.com)
最新文章
- 让 http 2来得更猛烈些吧
- 杭电ACM1003
- 实现了IEnumerable接口的GetEnumerator 即可使用 Foreach遍历,返回一个IEnumerator对象
- css 字体不撑开默认块级元素问题
- Android问题-打开DelphiXE8与DelphiXE10新建一个空工程提示";out of memory";
- Nginx Rewrite 实现匹配泛域名规则
- 3 Financial Services Social Media Success Storie
- 关于数组和List之间相互转换的方法
- jQuery 编辑div内容
- Spring AOP基于xml配置实例
- 【学习opencv第六篇】图像的反转操作
- Python调用(运行)外部程序
- Weave Scope 容器地图 - 每天5分钟玩转 Docker 容器技术(80)
- 定时任务 Cron表达式
- mysql的group_concat列转行函数
- Mybatis--课程中循序渐进的体会 《黑马程序员_Springmvc+Mybatis由浅入深全套视频教程video》
- mysql exists 如何使用
- 用开源项目CropImage实现图片的裁剪(不推荐)
- @TargetAPI + 版本判断实现高低API版本兼容
- 用pyenv 和 virtualenv 搭建单机多版本python 虚拟开发环境
热门文章
- TypeScript 之 控制流分析(Control Flow Analysis)
- 【机器学习】李宏毅——Transformer
- JavaScript:操作符:算术运算符(加减乘除模幂)及其隐式转换数据类型
- 新款 c++ web framework 支持orm http/2
- 跟光磊学Java-Windows版Java8开发环境搭建
- DSS+Linkis Ansible 单机一键安装脚本
- [常用工具] OpenCV_contrib库在windows下编译使用指南
- npm ERR! An unknown git error occurred
- JavaBean为何物?
- FLASH-CH32F203替换CH32F103 FLASH快速编程移植说明