Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

OpenGLContext 3.0.0a1

OpenGLContext renders 3D scenes with PyOpenGL, in a window belonging to whichever GUI toolkit your application already uses. It loads glTF 2.0 and VRML97 worlds, draws them through a core-profile pipeline with physically based materials, and lets you walk around inside them with game-style physics and positional audio.

The primary focus of the library has always been to provide a way to create simple demos and tests for the PyOpenGL library. With the 3.0 release OpenGLContext is closer to a game engine than a demonstration library. It is still the primary suite of test cases run to verify PyOpenGL behaviour, but it is also a relatively broad framework on which you can create your own demos or tools.

What it does

  • Renders into five GUI toolkits — GLFW (recommended for core-profile and PBR rendering), GLUT, Pygame, wxPython and Qt/PySide — owning the window or embedded as one canvas in a larger application. Backends are plug-ins, so an application can register its own.

  • Loads scenes — glTF 2.0 and GLB with animation, skinning and morph targets; VRML97; Wavefront OBJ; and streamed 3D Tiles datasets, from a file or over the network. PK3 files with a secondary package.

  • Draws them — physically based materials, image-based lighting, shadows, transmission and bloom, particle effects, fog, TrueType text, and instancing that collapses repeated shapes into a single draw.

  • Lets you interact — click to pick objects in the scene, move through it in examine, fly, walk or first-person mode, respond to mouse, keyboard and timer events, and put panels, widgets and a settings screen over the top.

  • Game-style physics — rigid bodies, collision, joints and gravity zones, and a character who walks on the terrain you can see.

  • Game-style positional audio — sounds placed in the scene and heard from where the listener stands.

  • Viewer Applicationoglc-view model.glb. With embedded links to sample content you can browse through the embedded UI.

Install

Needs Python 3.10+ and a platform with Desktop OpenGL 3.3+

pip install "OpenGLContext[glfw,draco,audio]"
oglc-view model.glb

or, with uv:

uv run --with "OpenGLContext[glfw,draco,audio]" oglc-view

Extras add optional pieces: audio for sound you can hear, draco for Draco-compressed glTF, pygame and wx for those backends, all for everything.

Documentation

docs/documentation.html is the index — installation, tutorials, and a page per feature. docs/structure.html describes how the pieces fit together.

Development

The 3.0.0 release of OpenGLContext makes use of Large Language models during the development process. A few of the stand-in models for weapons were also generated via LLMs.

Releasing

.github/workflows/release.yml runs on every push to main. It compares __version__ in OpenGLContext/__init__.py against PyPI: if that version is already published the run stops there, and if it is new the sdist and wheel are built, checked and uploaded. Bumping the version is what cuts a release; a push that leaves it alone does nothing.

Three checks stand between the build and the upload — twine check --strict on the metadata, scripts/check_release_artifact.py on both artifacts, and a comparison of the built filenames against the version that was looked up.

The test suite is not among them. It renders real frames and wants a live GL context, which a stock runner does not have, so run it locally and confirm it is green before bumping the version:

python -m pytest tests/
python scripts/check_release_artifact.py --source-root . dist/*.whl dist/*.tar.gz

Uploading uses PyPI trusted publishing, so no API token is stored anywhere. It needs a publisher registered on the PyPI project for this repository with workflow release.yml and the environment field left blank: the OIDC claim carries no environment, and a publisher that names one will not match.

Changelog

3.0.0a1

The major version marks the removals at the end of this entry: several sub-packages and the visitor-based renderer are gone, so code that imported them needs changing. Everything else here is additive.

  • glTF 2.0, as a loader package (loaders/gltf/) and the format the viewer leads with: .gltf/.glb, local or over http(s), with animation, skinning, morph targets, sparse accessors, computed tangents and the KHR_materials_*/KHR_texture_transform/unlit/specular-glossiness family. KHR_draco_mesh_compression decodes when the optional DracoPy is installed. See docs/gltf.html.

  • Physically-based rendering — a metallic/roughness uber-shader and PBR render pass, PBRMaterial, image-based lighting (analytic or a runtime probe, with Radiance .hdr panoramas), screen-space transmission and emissive bloom. docs/pbr.html, docs/ubershader.html.

  • Shadow maps, per-light, with cascades for directional lights and an fps-adaptive cascade count. Replaces the removed stencil-volume path. docs/shadows.html.

  • Instanced rendering, automatic: the pass batches shapes that share geometry and a compatible appearance into one glDrawElementsInstanced, for VRML USE/DEF, shared glTF meshes and EXT_mesh_gpu_instancing alike. docs/instancing.html.

  • One viewer, oglc-view, for glTF, VRML97, OBJ and 3D Tiles: format is chosen from the source by a registered SceneAdapter, so a third party adds a format without touching the viewer. It carries a launch menu, a model library, and settings and controls screens. oglc-vrml, oglc-gltf and oglc-tiles are deprecated aliases for it. docs/viewer.html.

  • An overlay UI (ui/) — panels, widgets, layout and a skin, drawn in one batched call, with a settings screen generated from a node's own fields, a console and a key-bindings editor. docs/overlayui.html.

  • Rigid-body physics and character movement — collision, gravity, joints and gravity zones through the omi_physics package, first-person and examine navigation, declared movement modes, and a terrain-walking mode. docs/physics.html, docs/navigation.html.

  • Terrain and 3D Tiles — an OGC 3D Tiles streaming runtime with screen-space-error LOD, async paging and eviction; splat-textured heightfield terrain; and instanced vegetation. docs/terrain.html.

  • Spatial audio — VRML97's Sound and AudioClip play, alongside glTF's KHR_audio_emitter, through the omi_audio package. docs/audio.html.

  • Particle systems, fog, and a HUD/debug overlay with frame timing and loop instrumentation. docs/particles.html, docs/hud.html.

  • Untrusted assets are contained. A document that names external resources — a glTF's buffers, images and audio, a 3D Tiles tileset's content and nested tilesets — may only reach what its own origin permits: same-origin http(s) for a document fetched over the network (re-checked on every redirect hop), and the document's own directory for one loaded from disk. Every fetched resource is size-capped, and the download cache is per-user rather than in shared system temp. The policy lives in one module, loaders/resolver.py.

  • Packaging modernisedpyproject.toml with PEP 639 licence metadata, and scripts/check_release_artifact.py, which refuses an artifact carrying files the source tree no longer has.

  • glTF audio codec extensions. A KHR_audio_emitter source may offer the same sound in Ogg Vorbis through OMI_audio_ogg_vorbis, keeping its own MP3 as the fallback; the Vorbis is decoded and preferred. Which OMI extensions are supported at all is tabulated in docs/gltf.html; the codec rules are in docs/audio.html.

  • Removed code that nothing reached any more. None of the five GUI backends is affected.

    • browser sub-package — the unfinished wxPython "browser" shell and the VPython-compatible visual API (never finished past prototype, see the 2.0.0c1 note below). The one piece anything outside it used, appdatadirectory(), is now OpenGLContext.userpaths. The oglc-visual script goes with it.

    • shadow sub-package — stencil shadow volumes, which required the fixed-function pipeline and an infinite-perspective projection. Dynamic shadows are shadow maps (see docs/shadows.html); the vrml_view_shadow script goes with it.

    • scenegraph.tree — the volumetric/space-colonization tree. Shipped vegetation is instanced glTF with impostors.

    • The visitor-based multi-pass renderer — RenderPass, VisitingRenderPass, Opaque/Transparent/SelectRenderPass, OverallPass, PassSet and RenderVisitor. Rendering has gone through the flat pass (passes/_flat.py) for some time; these were reachable only from the two sub-packages removed above. renderpass.py now just selects a flat pass, rendervisitor.py just binds the active Viewpoint, and visitor.py is the find() traversal. docs/renderprocess.html, which documented the removed system, is withdrawn.

    • DisplayListCompiler / DisplayListRenderer — unreachable: the compiler-selection weighting always preferred ArrayGeometryCompiler (1.0 over 0.9), so no IndexedFaceSet has compiled to a display list in a long time. Display lists themselves remain, for the bitmap font providers that use them.

    • scenegraph.nurbsshader (superseded by nurbstess, which is the one wired into nurbs.py), move.fps (superseded by move.modes.FPSMode), passes.flat, events.tkevents and events.fxevents (no Tk or FOX context exists to reach them).

  • DisplayList.__del__ no longer reports an error when its context has already gone away; there is nothing to release in that case.

2.0.0c1 -> 2.1.0a1

  • PyOpenGL 3.x compatibility

  • Support for Numpy

  • PyVRML97 project split back out into separate project

  • A few more tests/demos

  • Register and look up node-types explicitly using plug-in framework.

  • Register and look up context-types explicitly using plug-in framework.

  • Expose scripts for vrml_view and choosecontext.

2.0.0b1 -> 2.0.0c1

Refactoring and code cleanup:

  • Major scripts moved to the bin subdirectory.

  • Contexts now have classmethods for their "main" functions.

  • Scripts to choose the default context class and font.

  • Application data directory now hidden on non-Win32 platforms (.OpenGLContext instead of OpenGLContext).

  • Mechanism for specifying context attributes (size, depth, buffer type, etceteras). See the contextdefinition.ContextDefinition Node-class for details.

  • Default getScenegraph implementation of getattr(self,'sg',None).

  • Force flush before swap buffers (attempt to compensate for rendering artefacts on Linux).

Non-standard MouseOver node for constructing buttons.

  • PyGame interactivity fixes

    • Work on making the PyGame interactions, particularly keyboard repeats, act in the same way as the keyboard interactions under wxPython and GLUT
  • wxTestingContext icons

    • wxPython testing context now has icons set for the frame so that it isn't showing the (ugly) default windows icons.
  • A few more tests/demos

    • wx_with_controls.py — demo of wxPython context + interacting control outside the context

    • arbwindowpos.py — ARB extension for pixel-level positioning of bitmap position within the rendering window

  • Resources directory w/ OpenGLContext icons for easy import

  • Dispatcher module completely factored out into the SourceForge pydispatcher project.

  • Switched registerCallback to using class-methods, switched demo to using those methods to allow non-context-dependent registration of mouse events.

  • Refactoring of mouse-based events, addition of code to allow "captured" and "bubbling" events (parent recieves events before/after children and can cancel further propagation).

  • Bug Fixes:

    • Try ImageTexture stub when PIL not available

    • Workaround for strange bug with wxPython where the main thread appears as two different objects, depending on whether it's in a callback or not.

    • Test for bugs in PyOpenGL's feedback mode operation

  • Additionally, some work has been done on the browser sub-package, but it is still not finished to even prototype stages yet. It may, however, be useful as a source of sample code to some people.

2.0.0a4 -> 2.0.0b1

  • Optimization and accelerator modules:

    • The entire rendering pipeline has been noticeably sped up, with a number of key performance bottlenecks rewritten using C modules (which should compile on any Python+Numeric setup).
  • Frustum Culling:

    • Bounding box calculation for common geometry types, including caching and automatic updating of bounding boxes.

    • Frustum extraction from model view matrix.

  • Polygonal and Bitmap Text (TTF):

    • Use of (new) ttfquery package based on the fonttools package allows scanning for system fonts (or fonts in a given directory) and doing primitive face-name matching for those fonts. Uses direct extraction of font outlines for polygonal text.

    • Context customization point for setup

    • Eliminated BitmapText node, use FontStyle.format ='bitmap' instead.

  • All rendering methods and functions are now given a "mode" argument, and generally pass that argument to the functions they call to provide access to the current renderpass, context, etc.

  • GLE-based extrusion geometry types added

  • Added object for managing initialized extensions for a given context

  • Added some utility mechanisms for dealing with parametric equations of planes expressed as 4-item arrays.

  • Switch to using Mip-mapped textures by default

  • Polygon tessellation code reworked and generalized (used by the polygonal text engine, for instance).

  • Added (disabled) code to use display lists instead of array geometry for rendering indexed face sets.

  • Broke out vertex and polygon classes from IFS module

  • wxPython context:

    • Added wants-chars style to work properly in panels

    • wxPython context should also be somewhat more stable, particularly when used with Python 2.2.3. Workarounds for Python 2.2.2 bugs are still in place, but they do not guarantee that no errors will occur, merely reduce the likelihood when using Python 2.2.2.

    • Added ability to provide an OpenGL attribList for wxContext.

  • Bug Fixes (too many to list everything):

    • Textures and display-lists in particular have significant bug fixes checked in. Many of these were simply making the objects context-specific. Also caught strange bug where display list creation is returning 0 rather than raising exceptions.

    • Textured transparent geometry (i.e. geometry whose textures have Alpha channels) are now rendered during the transparent rendering pass, rather than the opaque rendering pass.

    • Fix for unlit textured geometry not showing white as base colour.

    • TextureTransform logic bug eliminated (was occasionally leaving the texture transform active).

    • The cache API is now easier to use, and hopefully will not be triggering Python 2.2.2 errors anymore.

    • Python 2.3 compatibility revisions

    • Removed premature optimisation which was eliminating USE'd transparent shapes even though the matrices were different.

    • Fix for build_normalPerVertex to properly build the normals (produces true smoothing, rather than the rather strange looking results of the previous version).

2.0.0a3 -> 2.0.0a4

  • PROTOs:

    • Initial support for prototyped nodes added, which allows for loading a wider swath of VRML content. No support for EXTERNPROTO as-of-yet.

    • Refactored vrml.vrml97.prototypes into vrml.route and vrml.vrml97.script modules

  • Events:

    • Partial rework of the mouse-events API to allow the events to be handled during the event-cascade, addition of support for event-cascade deferal of event processing to eventhandler mix-in and Context classes.

    • Addition of support in the event base class for tracking visited node/field combinations, calling of base-class initializer from the sub-class initializer's.

    • ROUTEs are now active for fields

    • IS mappings now work for PROTO fields (sub-class of ROUTE)

    • Introduction of Event class in the vrml package, should become the base-class for OpenGLContext.events.event

  • Cleanup of bugs in Shape, Switch and WGLFont where corner-cases were not properly caught (e.g. no geometry, whichChoice out-of-bounds, no text on a line)

  • IndexedFaceSet:

    • Reworked generation code extensively, now supports colour-per-face and normal-per-face modes of VRML97

    • Added a few sanity checks as well.

  • PixelTexture node added.

  • Preliminary Cylinder and Cone implementations.

  • Stub implementations of LOD, Inline and Billboard nodes.

  • Fix for transparent-geometry rendering (depth-buffer-testing enabled).

  • Consolidated vrml.node and vrml.vrml97.node into vrml.node. Moved fieldtypes to vrml package instead of VRML97 package

  • Made default testing-context preference-sequence wx, Pygame, then GLUT

  • Made all Bindable types also act as Children, since they are present in the scenegraph hierarchy.

  • Fix for parsing hexidecimal-encoded SFImage fields (as seen in PixelTextures).

  • Work-around for Python 2.2.2 calling of receiver methods in dispatcher.

  • Considerably more robust getField implementation in protofunctions

2.0.0a2 -> 2.0.0a3

  • Major Documentation updates (almost all doc-strings are updated in all modules).

  • Loaders:

    • Fixed bug with local-file loading where a local-file combined with the url ../ would give a result of: z:../ , we now create a file-path url in cases where a local-file is loaded.

    • Moved vrml2pklgz script to loaders module.

    • Re-added "dump" method to VRML97 loader.

  • ViewPlatform:

    • Fix for the straighten method

    • Elimination of distance attribute

    • Switch to new-style classes

    • Loosening of the API for setPosition and setOrientation

    • Fix for bug in the "forward" method

    • Mix-in:

      • Eliminated trackball attribute and unProject method, commented out the unused slider interface
  • Minor tweaks/optimisations to vectorutilities.

  • Nodes:

    • Changed Node.externalURL back to a simple attribute value of the class (bug-fix)

    • Made SFNode and MFNode donate rootSceneGraph to children without them when values are set.

    • Eliminated unused WeakMFNode field-type

    • Fixed bug in WeakField implementation (returned a weak reference)

    • Added a bound field to CubeBackground.

    • Fixed inheritence for WeakSFNode, eliminated cube-background work-around for rootSceneGraph tracking.

    • Texture/ImageTexture:

      • Refactored PIL texture conversions

      • Fixed typo/copying bug in Texture.__del__

      • Fix for image loading (default baseURI re-instated), reduced levels on a number of log messages

    • Fix for cube-background render when last glColor set the color to black.

    • Added fields Background to shadow those in CubeBackground which prevent ImageTexture objects being linearised to VRML97 where they shouldn't be.

  • Complete rework of the field.Field implementation to eliminate the seperate "fieldtype" objects in favour of making fieldtypes the actual type (class) of the field. [ MAJOR CHANGE ]

  • Unused methods deleted from OverallPass

  • Fixed bug in the builtin( ) function, it would only properly report for Nodes before, instead of working for both Nodes or prototypes/classes.

  • Events:

    • Eliminated use of Start and Stop Timer Events as parents for Pause and Resume events

    • InternalTime's now generate FractionalEvents in a few more places.

    • Moved the examine manager to the events package

    • EventManger.registerCallback raises NotImplementedError instead of SystemError if a sub-class doesn't implement the method.

    • Minor cleanup in Event and EventHandler classes

  • Switch a few classes to being new-style classes.

  • Testing Code:

    • ambient_only made a sub-class of the vrml_view test

    • Removed obsolete glut stencil buffer test script

2.0.0a1 -> 2.0.0a2

  • Made scenegraph.regDefName de-register references to the object by it's previous defName if possible.

  • Added PROTO name declaration to BitmapText

  • Changed NurbsTrimmedSurface name to TrimmedSurface to follow the nurbs-extension naming scheme

  • Added standardPrototype function to loaders.vrml97 to allow for programmatic registry of standardPrototypes for the loader

  • Documentation updates.

  • A few setup and manifest changes.

  • Added a texture-specific log to the debug/logs module.

  • Addition of "root" protofunction for getting the root scenegraph for a node (doesn't currently support automatically setting the root field for children, however)

  • Elimination of weakref dicts for implementating scenegraph, uses protofunctions instead

  • Elimination of "DEF" and "PROTO" references in favour of protofunctions.defName and protofunctions.protoName

  • Image and Texture Loading:

    • Initial support for loading textures across the network, basically it's the original VRML97 loader with a bit of refactoring to support both images and scenes.

    • Caching textures (only creating a single OpenGL texture if there are multiple ImageTextures which use the same PIL image)

    • PIL paletted texture -> RGB

    • PIL resize of non-power-of-two textures

  • IFS Tesellation — commented out debugging code when IFS runs out of vertex indices before it runs out of other indices, just considers itself done now (lets some malformed content load)

  • .cvsignore files added throughout

  • Added missing attribution for glprint test

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openglcontext-3.0.0a2.tar.gz (3.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openglcontext-3.0.0a2-py3-none-any.whl (1.3 MB view details)

Uploaded Python 3

File details

Details for the file openglcontext-3.0.0a2.tar.gz.

File metadata

  • Download URL: openglcontext-3.0.0a2.tar.gz
  • Upload date:
  • Size: 3.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for openglcontext-3.0.0a2.tar.gz
Algorithm Hash digest
SHA256 05356a325bdc7565840e3a7cc29964fcc09027f8e29bf73e62f29e0939957509
MD5 d70dfd8584efcef9eaf02b9855f17365
BLAKE2b-256 5f01dfc83fe7be9684683d7eef03d9d8b80437e5cae3b6b54325eaa38cd6d2ab

See more details on using hashes here.

Provenance

The following attestation bundles were made for openglcontext-3.0.0a2.tar.gz:

Publisher: release.yml on mcfletch/openglcontext

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file openglcontext-3.0.0a2-py3-none-any.whl.

File metadata

File hashes

Hashes for openglcontext-3.0.0a2-py3-none-any.whl
Algorithm Hash digest
SHA256 579e5ed9d0cc1423b11c96cf678e536b7fc1e334d53e0f5bf9016b87664a8d7a
MD5 5d92982717c37f752c6aa3cdadbdf90c
BLAKE2b-256 86a0cdbf7571b5349e71beed46c7fd0ec5a6a6cd9334d9deebac743e0823b397

See more details on using hashes here.

Provenance

The following attestation bundles were made for openglcontext-3.0.0a2-py3-none-any.whl:

Publisher: release.yml on mcfletch/openglcontext

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page