使用 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

相关文章

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma