基于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)
基于GLUT的PyOpenGL的使用的更多相关文章
- VS2012下基于Glut 矩阵变换示例程序2:
在VS2012下基于Glut 矩阵变换示例程序:中我们在绘制甜圈或者圆柱时使用矩阵对相应的坐标进行变换后自己绘制甜圈或者圆柱.我们也可以使用glLoadMatrixf.glLoadMatrixd载入变 ...
- VS2012下基于Glut 矩阵变换示例程序:
也可以使用我们自己的矩阵运算来实现OpenGL下的glTranslatef相应的旋转变换.需要注意的是OpenGL下的矩阵是列优先存储的. 示例通过矩阵运算使得圆柱或者甜圈自动绕Y轴旋转,可以单击鼠标 ...
- VS2012下基于Glut OpenGL glEdgeFlag示例程序:
glEdgeFlag (GLboolean flag)表示一个顶点是否应该被认为是多边形的一条边界边的起点.flag为GL_TRUE后面的点都被认为是边界上的点,flag为GL_FALSE则之后的点不 ...
- VS2012下基于Glut OpenGL glDepthMask示例程序:
glDepthMask (GLboolean flag)函数可以决定将他之后的数据不写入深度缓冲区.当flag为GL_TRUE时之后的数据不写入深度缓冲区,即使启用了深度缓冲区测试功能. 使用上一个D ...
- VS2012下基于Glut OpenGL glScissor示例程序:
剪裁测试用于限制绘制区域.我们可以指定一个矩形的剪裁窗口,当启用剪裁测试后,只有在这个窗口之内的像素才能被绘制,其它像素则会被丢弃.换句话说,无论怎么绘制,剪裁窗口以外的像素将不会被修改.有的朋友可能 ...
- 跟我学Python图像处理丨带你入门OpenGL
摘要:介绍Python和OpenGL的入门知识,包括安装.语法.基本图形绘制等. 本文分享自华为云社区<[Python图像处理] 二十七.OpenGL入门及绘制基本图形(一)>,作者:ea ...
- H5游戏开发之多边形碰撞检测
2D多边形碰撞检测介绍这是一篇论证如何在2D动作游戏中执行碰撞检测的文章(Mario,宇宙入侵者等),为了保证它的高效性和精确性,碰撞检测是以多边形为基础的,而不是以sprite为基础.这是两种不同的 ...
- Mac使用Xcode配置openGL
Mac使用Xcode配置openGL 博主这学期有图形学课要用到OpenGL,于是首先就开始配置开发环境了.应该说网上Windows上配置OpenGL教程比较多,Mac版的比较少.博主特来分享配置过程 ...
- Start from here: <<OpenGL的基本程序解析>>
这是我的第一篇学习OpenGL的笔记,也是博主的第一篇博客,希望能够在这里和大家一起成长. 下面的代码是<OpenGL超级宝典(第五版)>中的示例代码,基本程序如下: #include & ...
- 二进制格式 PLY 模型文件的读取与渲染
PLY 文件头部信息: ply format binary_little_endian 1.0 comment VCGLIB generated element vertex 13469 proper ...
随机推荐
- MongoDB安全加固,防止数据库攻击删除勒索威胁
前言: 今天发现前段时间自己搭建的一个系统的MongoDB数据找不到了,觉得很奇妙,然后登上MongoDB数据库发现多了一个名为READ__ME_TO_RECOVER_YOUR_DATA的数据库,里面 ...
- 基于.NetCore开发博客项目 StarBlog - (23) 文章列表接口分页、过滤、搜索、排序
前言 上一篇留的坑,火速补上. 在之前的第6篇中,已经有初步介绍,本文做一些补充,已经搞定这部分的同学可以快速跳过,基于.NetCore开发博客项目 StarBlog - (6) 页面开发之博客文章列 ...
- MVP、原型、概念验证,傻傻分不清楚?
MVP.原型以及概念验证这三者的概念虽然没有密切的联系,但也有不少人会分不清这三者的区别,在这篇文章中,我们会帮大家区分一下这三个概念.首先是MVP,MVP是Minimum Viable Produc ...
- Vue中实现自定义excel下载
目录 第一种:后端生成excel 第二种:前端合成excel 总结 参考资料 最近在工作中遇到一个需求,就是需要在前端实现一个错误模板Excel的下载功能. 实现下载有两种方式,一种是后端生成一个ex ...
- 【rabbitmq】单独配置某一个消费者手动ack,其他消费者自动ack
前言:博主才疏学浅,此方案仅供参考,如有更优方案请大佬评论区告知,十分感谢✿✿ヽ(°▽°)ノ✿ 问题背景:同一个服务中存在多个不同业务的rabbitmq的消费者,其中一个推送业务的消费者需要加死信队列 ...
- linux系统一键开启root登陆
服务器只能key登陆,用这个后直接可以root方式登陆 sudo -i echo root:要设置的密码 |sudo chpasswd root sudo sed -i 's/^#\?PermitRo ...
- python之路43 JavaScript语法BOM与DOM jQuery对比 标签绑定事件
前戏 到目前为止,我们已经学过了JavaScript的一些简单的语法.但是这些简单的语法,并没有和浏览器有任何交互. 也就是我们还不能制作一些我们经常看到的网页的一些交互,我们需要继续学习BOM和DO ...
- 洛谷P8508 做不完的作业【题解】
事先声明 此题解为一篇洛谷题解的详细补充,这里(我才不告诉你我这道题想了好久) 题目大意 有 \(n\) 个任务,记作 \(t\) 数组,由于主人公很懒,所以他每天都要睡觉,每一天都有 \(x\) 小 ...
- 揭开华为云CodeArts TestPlan启发式测试设计神秘面纱!
摘要:质量是产品的生死线. 本文分享自华为云社区<揭开华为云CodeArts TestPlan启发式测试设计神秘面纱!>,作者:华为云PaaS服务小智 . 2019年12月20日,是美国波 ...
- DQL_排序查询-DQL_聚合函数
DQL_排序查询 排序查询 语法: order by 子句 order by 排序字段1 排序方式1 , 排序字段2 排序方式2 , 排序字段3 排序方式3 ..... 排序方式 : A ...