OpenGL接口

Piglet提供了到OpenGL的直接接口。该接口被所有的pyglet高级API使用,因此所有的渲染都是由显卡而不是CPU高效地完成的。您可以直接访问此界面;使用它与在C中使用OpenGL非常相似。

界面是一个“薄包装器” libGL.so 在Linux上, opengl32.dll 在Windows和 OpenGL.framework 在OS X上,pyglet维护人员根据最新规范重新生成界面,因此它始终是最新版本和几乎所有扩展的最新版本。

该接口由 pyglet.gl 包裹。要使用它,你需要对OpenGL、C和ctype有很好的了解。您可能更喜欢使用OpenGL而不使用ctype,在这种情况下,您应该调查 PyOpenGLPyOpenGL 提供类似的功能,具有更具“Pythonic”风格的界面,并且无需任何修改即可与Piglet一起使用。

使用OpenGL

上提供了OpenGL的文档 OpenGL website 以及(更全面地)在 OpenGL Programming SDK

导入程序包可以访问OpenGL和所有已注册的OpenGL扩展。这对于除最高级的OpenGL用法之外的所有用法都足够了:

from pyglet.gl import *

所有函数名和常量都与C语言中的对应函数相同。例如,下面的代码设置GL Clear颜色并启用深度测试和面剔除:

from pyglet.gl import *

# Direct OpenGL commands to this window.
window = pyglet.window.Window()

glClearColor(1, 1, 1, 1)
glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)

某些OpenGL函数需要数据数组。这些数组必须构造为 ctypes 正确类型的数组。下面的示例说明如何使用OpenGL类型构造数组:

from pyglet.gl import *

# Create a new array type of length 32:
array32f = GLfloat * 32

# Create an instance of this array with initial data:
array_instance = array32f(*data)

# More commonly, combine these steps:
array_instance = (GLfloat * 32)(*data)

类似的数组结构可用于为其他OpenGL对象创建数据。

调整窗口大小

pyglet会在每个窗口上自动设置视区和平行投影。它在默认情况下执行此操作 on_resize() 处理程序定义于 Window 。pyglet窗口有一个 projection 可以使用4x4投影矩阵设置的属性。看见 矩阵与向量数学 有关创建矩阵的详细信息,请参阅。默认设置 on_resize 处理程序定义为::

@window.event
def on_resize(width, height):
    glViewport(0, 0, *window.get_framebuffer_size())
    window.projection = Mat4.orthogonal_projection(0, width, 0, height, -255, 255)

如果需要定义您自己的投影(例如,要使用三维透视投影),则应使用您自己的事件覆盖此事件;例如:

@window.event
def on_resize(width, height):
    glViewport(0, 0, *window.get_framebuffer_size())
    window.projection = Mat4.perspective_projection(window.aspect_ratio, z_near=0.1, z_far=255)
    return pyglet.event.EVENT_HANDLED

请注意, on_resize() 无论是第一次显示窗口,还是以后调整窗口大小,都会为窗口调用处理程序。

错误检查

默认情况下,pyglet调用 glGetError 在每次GL函数调用之后(除非这样的检查无效)。如果报告了错误,则会引发 GLException 其结果是 gluErrorString 作为这条信息。

这在开发过程中非常方便,因为它可以在早期捕获常见的编码错误。但是,它对性能有很大影响,当使用 -O 选择。

您也可以通过设置以下选项来禁用此错误检查 before 正在导入 pyglet.glpyglet.window **

# Disable error checking for increased performance
pyglet.options['debug_gl'] = False

from pyglet.gl import *

在导入后设置选项 pyglet.gl 都不会有任何效果。一旦禁用,在每次GL调用中都不会有错误检查开销。

使用扩展函数

在使用扩展函数之前,您应该检查该扩展是否由当前驱动程序实现。通常,这是通过使用 glGetString(GL_EXTENSIONS) ,但pyglet有一个方便的模块, pyglet.gl.gl_info 这将为您实现以下目标:

if pyglet.gl.gl_info.have_extension('GL_ARB_shadow'):
    # ... do shadow-related code.
else:
    # ... raise an exception, or use a fallback method

您还可以轻松查看OpenGL::的版本

if pyglet.gl.gl_info.have_version(4, 6):
    # We can assume all OpenGL 4.6 functions are implemented.

请记住,只调用 gl_info 在创建窗口后运行。

使用多个窗口

Piglet允许您同时创建和显示任意数量的窗口。每个上下文都将使用其自己的OpenGL上下文创建,但默认情况下,所有上下文将共享相同的纹理对象、显示列表、着色器程序等 [1]. 每个上下文都有自己的状态和帧缓冲区。

始终存在活动的上下文(除非没有窗口)。使用时 pyglet.app.run() 对于应用程序事件循环,pyglet在调度 on_draw()on_resize() 事件。

在其他情况下,您可以使用显式设置活动上下文 pyglet.window.Window.switch_to

AGL、GLX和WGL

OpenGL上下文本身由特定于操作系统的库管理:OS X上的AGL、X11下的GLX和Windows上的WGL。在创建窗口时,pyglet会处理这些细节,但您可能需要直接使用这些函数(例如,使用pBuffers)或扩展函数。

这些模块被命名为 pyglet.gl.aglpyglet.gl.glxpyglet.gl.wgl 。您只需为正在运行的操作系统导入正确的模块:

if sys.platform.startswith('linux'):
    from pyglet.gl.glx import *
    glxCreatePbuffer(...)
elif sys.platform == 'darwin':
    from pyglet.gl.agl import *
    aglCreatePbuffer(...)

或者,您也可以使用 pyglet.compat_platform 以支持与Piglet未正式支持的平台兼容的平台。例如,FreeBSD系统将显示为 linux-compat 在……里面 pyglet.compat_platform

有方便的模块用于查询WGL和GLX的版本和扩展名 pyglet.gl.wgl_infopyglet.gl.glx_info ,分别为。AGL没有这样的模块,只需查询OS X的版本即可。

如果使用GLX扩展模块,则可以导入 pyglet.gl.glxext_arb 对于已注册的分机或 pyglet.gl.glxext_nv 获取最新的NVIDIA扩展。

同样,如果使用WGL扩展模块,请导入 pyglet.gl.wglext_arbpyglet.gl.wglext_nv