OpenGL ES
Pyglet has experimental support for OpenGL ES 3.2, with some limitations. Devices like Raspberry Pi 4 and 5 supports OpenGL ES 3.1 with extensions covering most of the missing 3.2 features (with the exception of tessellation shaders). There are likely other devices with ES support that can run Pyglet.
Creating a window / context
In order to successfully create a context and window with OpenGL ES we first need to:
Likely disable the shadow window because very few environments supports this
Pass in a custom config at window creation specifying OpenGL ES and version
Example:
import pyglet
# Disable shadow window
pyglet.options.shadow_window = False
# Query the best config for the screen
display = pyglet.display.get_display()
screen = display.get_default_screen()
config = screen.get_best_config()
# Specify that we want to use OpenGL ES 3.1
# This is very specific to the Raspberry Pi 4 and 5. Use 3.2 if you can.
config.opengl_api = "gles"
config.major_version = 3
config.minor_version = 1
# Create the window
window = pyglet.window.Window(config=config)
Limitations
Multisampling
Be careful with enabling multisampling on the window. Likely
get_best_config()
will not have multisampling enabled.
Textures
Pixel format for textures and images are limited to RGBA
. If you try to
load any other pixel format through pyglet’s image loading functions you
will get an error when they are turned into OpenGL textures later.
The reason for this limitation is that OpenGL ES does not support pixel
format conversion during pixel transfer, meaning when calling glTexImage
to upload pixel data to the GPU, the pixel format must match the internalformat.
In desktop OpenGL an RGB image will be automatically converted to RGBA during
this transfer. This is not supported in OpenGL ES.
You are, however, free to create your own textures with any pixel format using the gl bindings directly.
Compute Shader
If you are planning to bind textures to image units with the intention of
using them in a compute shader, you need to create these textures yourself
using the gl bindings and allocate space using glTexStorage
. Pyglet is
using glTexImage
to allocate space and upload the pixel data for textures.
The difference here is that glTexStorage
creates immutable storage. You can
only call it once and then fill the allocated space with pixel data using
glTexSubImage
. glTexImage
on the other hand can be called multiple times
reallocating the texture storage each time. Likely OpenGL ES doesn’t want to
deal with the extra complexity of validating the texture storage of images
every time a compute shader is dispatched.
In short: Create your own textures with immutable storage if you are planning to use them in a compute shader.
Shaders
Pyglet’s shader system supports basic conversion between GLSL 1.5/3.3 shaders to GLES 3.2 shaders when running in OpenGL ES mode. This is to ensure that pyglet’s built-in shaders also works with GL ES. This system is not perfect and are likely to have some flaws.
Currently the shaders are converted to ES 3.1 shaders as a careful approach
manually enabling extensions needed for ES 3.2. Precisions qualifiers are
injected using mediump
by default.