使用 PyOpenGL 进行 2D 图形渲染总结

2024-03-24 06:44

本文主要是介绍使用 PyOpenGL 进行 2D 图形渲染总结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、说明

OpenGL是一个广泛使用的开放式跨平台实时 3D 图形库,开发于二十多年前。它提供了一个低级API,允许开发人员以统一的方式访问图形硬件。在开发需要硬件加速且需要在不同平台上运行的复杂 2D 或 3D 应用程序时,它是首选平台。它可以在多种语言中使用,包括 C/C++、C#、Java、Objective-C(用于 iPhone 和 iPad 游戏)、Python 等。在本文中,我将展示如何将 OpenGL 与 Python 一起使用(感谢PyOpenGL 库)来高效渲染 2D 图形。

二、安装简介

需要带有 Numpy、 PyOpenGL和 PyQt4库的 Python。在 Windows 上,可以在此网页上找到二进制安装程序 。

此外,还需要系统显卡的最新驱动程序,以便可以使用最新的OpenGL实现。特别是,我们将利用 顶点缓冲对象 (VBO),从 OpenGL 版本 1.5(2003 年出现)开始,这些对象在核心实现中可用。在此日期之后发货的显卡应具有支持 VBO 的驱动程序。但是,系统上安装的驱动程序可能不支持最新版本的 OpenGL。

例如,在 Windows 上,我对 2009 年显卡的默认驱动程序存在一些问题:OpenGL 1.1 是唯一受支持的版本。 原因是当构造函数驱动程序未找到或不可用时,Windows(从 Vista 开始)可以使用一种基于 Windows 显示驱动程序模型 (WDDM)的通用驱动程序。现在,WDDM 驱动程序倾向于使用 DirectX(微软自己的图形库,与 OpenGL 并行)而不是 OpenGL,因此这些驱动程序仅支持非常旧的 OpenGL 版本。为了使事情正常进行,需要找到构造函数驱动程序并强制安装它们。可能会有点痛。

简而言之,如果在运行下面的脚本时出现提及 OpenGL 和缓冲区对象的错误消息,请确保显卡驱动程序正确。OpenGL Extensions Viewer是检查显卡 OpenGL 功能的一个非常有用的工具 。它适用于 Windows、Linux 和 iOS。

三、QGL控件

我们将定义一个 Qt 小部件,在窗口中的随机位置显示点。该小部件将派生自 QGLWidgetQt 小部件,它提供对 OpenGL API 进行渲染的访问。派生类中至少需要重写三个方法:initializeGL()、updateGL()和resizeGL(w, h)。

initializeGL():在这里调用 OpenGL 初始化命令。它也是创建顶点缓冲区对象并用一些数据填充它们的地方。

paintGL():在此处调用 OpenGL 渲染命令。每当需要重绘窗口时就会调用它。

resizeGL(w, h):在这里进行与相机和视口相关的调用。每当小部件的大小发生更改时都会调用它(新的小部件大小作为参数传递给此方法)。

顶点缓冲区对象
渲染数据最有效的方法是尽量减少从系统内存到 GPU 内存的数据传输,并尽量减少对 OpenGL 渲染命令的调用次数。执行此操作的一种便捷方法是使用 顶点缓冲区对象。它们允许在 GPU 上分配内存,在 GPU 上加载一次数据(如果数据发生变化则加载多次),并高效地渲染它,因为数据在连续调用之间保留在 GPU 上 paintGL()。PyOpenGL 集成了一个模块来轻松创建和使用 VBO:

import OpenGL.arrays.vbo as glvbo
# in initializeGL:
# create a VBO, data is a Nx2 Numpy array
self.vbo = glvbo.VBO(self.data)# in paintGL:
# bind a VBO, i.e. tell OpenGL we're going to use it for subsequent
# rendering commands
self.vbo.bind()

四、使用 VBO 绘画

OpenGL 可以渲染点、线和凸多边形等图元。 glEnableClientState 和 glVertexPointer 函数配置 VBO 进行渲染,glDrawArrays 函数从存储在 GPU 内存中的缓冲区中绘制图元。可以与 VBO 一起使用的其他绘图命令包括 glMultiDrawArrays,用于从单个 VBO 绘制多个独立图元(与使用多个 VBO 相比,效率更高,但灵活性较差)。索引绘图也是可能的,并允许以任意顺序使用顶点,并在渲染期间多次重用顶点。相关函数是glDrawElements和glMultiDrawElements。

颜色可以在调用渲染命令之前使用函数 glColor 指定,也可以通过为颜色创建一个特殊的 VBO(包含每个点的颜色)来指定。相关函数是glColorPointer和glEnableClientState(GL_COLOR_ARRAY)。一种变体是将颜色与顶点打包在一起,即在单个 VBO 中每个点有 5 个数字(x、y 坐标和 R、V、B 颜色分量)。请参阅此处的一些详细信息。

注意:显然,在OpenGL中,使用单精度浮点数比使用双精度浮点数更好。显卡可能确实不支持后一种格式。我在这篇文章的早期版本中使用了双精度,在特定情况下我遇到了一些令人讨厌的内存访问冲突崩溃。当我换成花车时它们就消失了。如果这对任何人有帮助…、

# in paintGL:
# set the color yellow
gl.glColor(1,1,0)
# enable the VBO
gl.glEnableClientState(gl.GL_VERTEX_ARRAY)
# tell OpenGL that each vertex is made of 2 single precision floating
# numbers (x and y coordinates).
gl.glVertexPointer(2, gl.GL_FLOAT, 0, self.vbo)
# draw all points from the VBO
gl.glDrawArrays(gl.GL_POINTS, 0, len(self.data))

五、设置 2D 渲染的正交投影

该resizeGL方法设置用于 光栅化的几何投影。由于我们在本文中只对 2D 渲染感兴趣,因此我们 在该 函数中使用正交投影glOrtho。该 glViewport 函数允许指定用于后续渲染命令的屏幕部分。这里我们只是告诉 OpenGL 在整个窗口内进行绘制。

# paint within the whole window
gl.glViewport(0, 0, self.width, self.height)
# set orthographic projection (2D only)
gl.glMatrixMode(gl.GL_PROJECTION)
gl.glLoadIdentity()
# the window corner OpenGL coordinates are (-+1, -+1)
gl.glOrtho(-1, 1, 1, -1, -1, 1)

六、设置 PyQt 小部件

这里我们使用 PyQt 作为 GUI 窗口系统。为了在屏幕上显示一个窗口并使用我们的 OpenGL 小部件,我们首先需要定义一个 Qt 主窗口,将 OpenGL 小部件放入其中,最后创建一个 Qt 应用程序来托管主窗口。

# paint within the whole window
gl.glViewport(0, 0, self.width, self.height)
# set orthographic projection (2D only)
gl.glMatrixMode(gl.GL_PROJECTION)
gl.glLoadIdentity()
# the window corner OpenGL coordinates are (-+1, -+1)
gl.glOrtho(-1, 1, 1, -1, -1, 1)

定义一个 Qt 窗口,其中包含 OpenGL 小部件

# define a Qt window with an OpenGL widget inside it
class TestWindow(QtGui.QMainWindow):def __init__(self):super(TestWindow, self).__init__()# initialize the GL widgetself.widget = GLPlotWidget()# [...] (set data for the OpenGL widget)# put the window at the screen position (100, 100)self.setGeometry(100, 100, self.widget.width, self.widget.height)self.setCentralWidget(self.widget)self.show()# create the Qt App and window
app = QtGui.QApplication(sys.argv)
window = TestWindow()
window.show()
app.exec_()

七、完整剧本

这是完整的脚本。

# PyQt4 imports
from PyQt4 import QtGui, QtCore, QtOpenGL
from PyQt4.QtOpenGL import QGLWidget
# PyOpenGL imports
import OpenGL.GL as gl
import OpenGL.arrays.vbo as glvboclass GLPlotWidget(QGLWidget):# default window sizewidth, height = 600, 600def set_data(self, data):"""Load 2D data as a Nx2 Numpy array."""self.data = dataself.count = data.shape[0]def initializeGL(self):"""Initialize OpenGL, VBOs, upload data on the GPU, etc."""# background colorgl.glClearColor(0,0,0,0)# create a Vertex Buffer Object with the specified dataself.vbo = glvbo.VBO(self.data)def paintGL(self):"""Paint the scene."""# clear the buffergl.glClear(gl.GL_COLOR_BUFFER_BIT)# set yellow color for subsequent drawing rendering callsgl.glColor(1,1,0)# bind the VBOself.vbo.bind()# tell OpenGL that the VBO contains an array of verticesgl.glEnableClientState(gl.GL_VERTEX_ARRAY)# these vertices contain 2 single precision coordinatesgl.glVertexPointer(2, gl.GL_FLOAT, 0, self.vbo)# draw "count" points from the VBOgl.glDrawArrays(gl.GL_POINTS, 0, self.count)def resizeGL(self, width, height):"""Called upon window resizing: reinitialize the viewport."""# update the window sizeself.width, self.height = width, height# paint within the whole windowgl.glViewport(0, 0, width, height)# set orthographic projection (2D only)gl.glMatrixMode(gl.GL_PROJECTION)gl.glLoadIdentity()# the window corner OpenGL coordinates are (-+1, -+1)gl.glOrtho(-1, 1, 1, -1, -1, 1)if __name__ == '__main__':# import numpy for generating random data pointsimport sysimport numpy as npimport numpy.random as rdn# define a Qt window with an OpenGL widget inside itclass TestWindow(QtGui.QMainWindow):def __init__(self):super(TestWindow, self).__init__()# generate random data pointsself.data = np.array(.2*rdn.randn(100000,2),dtype=np.float32)# initialize the GL widgetself.widget = GLPlotWidget()self.widget.set_data(self.data)# put the window at the screen position (100, 100)self.setGeometry(100, 100, self.widget.width, self.widget.height)self.setCentralWidget(self.widget)self.show()# create the Qt App and windowapp = QtGui.QApplication(sys.argv)window = TestWindow()window.show()app.exec_()

在这里插入图片描述

这篇关于使用 PyOpenGL 进行 2D 图形渲染总结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/840753

相关文章

Spring IoC 容器的使用详解(最新整理)

《SpringIoC容器的使用详解(最新整理)》文章介绍了Spring框架中的应用分层思想与IoC容器原理,通过分层解耦业务逻辑、数据访问等模块,IoC容器利用@Component注解管理Bean... 目录1. 应用分层2. IoC 的介绍3. IoC 容器的使用3.1. bean 的存储3.2. 方法注

Python内置函数之classmethod函数使用详解

《Python内置函数之classmethod函数使用详解》:本文主要介绍Python内置函数之classmethod函数使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录1. 类方法定义与基本语法2. 类方法 vs 实例方法 vs 静态方法3. 核心特性与用法(1编程客

Linux中压缩、网络传输与系统监控工具的使用完整指南

《Linux中压缩、网络传输与系统监控工具的使用完整指南》在Linux系统管理中,压缩与传输工具是数据备份和远程协作的桥梁,而系统监控工具则是保障服务器稳定运行的眼睛,下面小编就来和大家详细介绍一下它... 目录引言一、压缩与解压:数据存储与传输的优化核心1. zip/unzip:通用压缩格式的便捷操作2.

使用Python实现可恢复式多线程下载器

《使用Python实现可恢复式多线程下载器》在数字时代,大文件下载已成为日常操作,本文将手把手教你用Python打造专业级下载器,实现断点续传,多线程加速,速度限制等功能,感兴趣的小伙伴可以了解下... 目录一、智能续传:从崩溃边缘抢救进度二、多线程加速:榨干网络带宽三、速度控制:做网络的好邻居四、终端交互

Python中注释使用方法举例详解

《Python中注释使用方法举例详解》在Python编程语言中注释是必不可少的一部分,它有助于提高代码的可读性和维护性,:本文主要介绍Python中注释使用方法的相关资料,需要的朋友可以参考下... 目录一、前言二、什么是注释?示例:三、单行注释语法:以 China编程# 开头,后面的内容为注释内容示例:示例:四

JavaSE正则表达式用法总结大全

《JavaSE正则表达式用法总结大全》正则表达式就是由一些特定的字符组成,代表的是一个规则,:本文主要介绍JavaSE正则表达式用法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录常用的正则表达式匹配符正则表China编程达式常用的类Pattern类Matcher类PatternSynta

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

ModelMapper基本使用和常见场景示例详解

《ModelMapper基本使用和常见场景示例详解》ModelMapper是Java对象映射库,支持自动映射、自定义规则、集合转换及高级配置(如匹配策略、转换器),可集成SpringBoot,减少样板... 目录1. 添加依赖2. 基本用法示例:简单对象映射3. 自定义映射规则4. 集合映射5. 高级配置匹

Spring 框架之Springfox使用详解

《Spring框架之Springfox使用详解》Springfox是Spring框架的API文档工具,集成Swagger规范,自动生成文档并支持多语言/版本,模块化设计便于扩展,但存在版本兼容性、性... 目录核心功能工作原理模块化设计使用示例注意事项优缺点优点缺点总结适用场景建议总结Springfox 是

嵌入式数据库SQLite 3配置使用讲解

《嵌入式数据库SQLite3配置使用讲解》本文强调嵌入式项目中SQLite3数据库的重要性,因其零配置、轻量级、跨平台及事务处理特性,可保障数据溯源与责任明确,详细讲解安装配置、基础语法及SQLit... 目录0、惨痛教训1、SQLite3环境配置(1)、下载安装SQLite库(2)、解压下载的文件(3)、