Camera transform & projection
Yaw, pitch, translation into view space, then a perspective divide. The result is a flat 2D coordinate per vertex.
Python · pygame-ce · MIT
VEXPOLY is a first-person arena shooter written in a single Python file.
The camera, the clipper, the lighting, the fog — all written by hand,
then handed to pygame.draw.polygon.
$ git clone https://github.com/dranimalis/vexpoly.git
$ cd vexpoly
$ python3 -m venv .venv && source .venv/bin/activate
$ pip install -r requirements.txt
$ python vexpoly.py
Python 3.9+ · pygame-ce 2.5 recommended · everything else ships in the repo
Renderer
Camera transform. Near-plane clipping. Perspective projection. Backface culling. Directional lighting. Distance fog. Depth sorting. A per-frame polygon budget. All of it runs in Python, per frame.
Pipeline
Every frame runs through the same eight stages. No shortcuts, no corners cut, no graphics API.
Yaw, pitch, translation into view space, then a perspective divide. The result is a flat 2D coordinate per vertex.
Polygons that cross the camera plane get cut before they can flip inside out.
Anything pointing away from the camera, or outside the view, is dropped before lighting runs.
One fixed light vector, one dot product per face. Cheap, consistent, readable.
Camera-space depth drives a fade toward the sky colour, so far geometry melts into the horizon.
Faces are sorted back-to-front by average camera-space depth, then handed to pygame.draw.polygon one by one.
Themes
Each theme swaps the sky gradient, fog colour, light direction, colour grade, and the entire texture set. Not just a tint. Tap one — it repaints this page and the live demo above.
Controls
Updates
Support
VEXPOLY talks to nothing. If you want to chip in, there's a page for that. A star or a bug report helps just as much.