DistForge
About
DistForge is a Python library for creating 3D models using Signed Distance Functions (SDFs). It provides a real-time, interactive rendering experience in a native desktop window, powered by GLSL raymarching.
Features
- Simple, Pythonic API: Define complex shapes by combining primitives using standard operators (
|,-,&) and chaining transformations. - Real-time Rendering with Hot-Reloading: Get instant visual feedback in a lightweight native window powered by
modernglandglfw. Changes to your script are reloaded automatically. - Mesh Exporting: Save your creations as
.stl,.obj, or.glbfiles for 3D printing or use in other software. - Interactive Parameters: Define parameters that can be controlled by UI sliders in real-time (with a compatible UI renderer).
- Standalone GLSL Export: Export your entire scene to a single, self-contained GLSL fragment shader for use in game engines or graphics applications.
- Custom GLSL Primitives: Write custom SDF logic directly in GLSL using the
Forgeobject for maximum flexibility and performance.
Getting Started
Hello Forge
Define a simple shape and open a real-time preview window with just a few lines of code.
from distforge import sphere, box
shape = sphere(1) & box(1.5)
shape.render()
Live Preview & Hot-Reloading
For an interactive workflow, wrap your scene definition in a main() function. When you save any changes to the file, the preview window will automatically update.
from distforge import box, sphere
def main():
"""
While this script is running, try changing the values below and
saving the file. The render window will update automatically.
"""
box_size = 1.6
sphere_radius = 1.2
scene = box(box_size) | sphere(sphere_radius)
return scene
if __name__ == "__main__":
scene = main()
scene.render()
Saving to a Mesh File
You can save any static model to an .stl, .obj, or .glb file. The .save() method uses the Marching Cubes algorithm to generate a mesh from the SDF.
from distforge import sphere, box
shape = box(1.5) - sphere(1.2)
shape.save('model.obj', samples=2**22)
Core Concepts
Primitives & Operations
Create complex objects by starting with primitives and combining them with Python's bitwise operators: | for union, & for intersection, and - for difference.
from distforge import sphere, box
b = box(1.5)
s = sphere(1.0)
scene = b - s
scene.render()
Transformations & Shaping
Chain methods to transform, shape, and repeat objects.
import numpy as np
from distforge import box, Y
b = box(size=(0.5, 2.5, 0.5))
scene = b.twist(3.0).rotate(Y, np.pi / 4)
scene.render()
Materials
You can assign a unique color to any object or group of objects using the .color() method.
from distforge import sphere, box
red_box = box(1.5).color(1.0, 0.2, 0.2)
blue_sphere = sphere(1.0).color(0.3, 0.5, 1.0)
scene = red_box - blue_sphere
scene.render()
Camera & Lighting
You can override the default interactive camera and lighting to set a static viewpoint or create specific lighting conditions by passing Camera and Light objects to the renderer.
from distforge import box, sphere, Camera, Light
def main():
scene = box(1.5) | sphere(1.2)
cam = Camera(position=(4, 3, 4), target=(0, 0, 0), zoom=1.5)
light = Light(position=(4, 5, 3), shadow_softness=16.0)
return scene, cam, light
if __name__ == '__main__':
scene, cam, light = main()
scene.render(camera=cam, light=light)
Advanced Usage
Interactive Parameters
Use Param objects to define interactive, real-time parameters for your model. A compatible UI-enabled renderer would show these as sliders. The default renderer will use their default values.
from distforge import box, Param
p_size = Param("Box Size", 0.8, 0.2, 2.0)
scene = box(size=p_size)
scene.render()
Custom GLSL with Forge
For complex or highly-performant shapes, you can write GLSL code directly. This object integrates perfectly with the rest of the API.
from distforge import sphere, Forge
s = sphere(1.2)
custom_box = Forge("""
vec3 q = abs(p) - vec3(0.8);
return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0);
""")
scene = s - custom_box
scene.render()
Standalone GLSL Export
Generate a complete, self-contained GLSL fragment shader for your scene. This file can be used directly in applications like Godot, TouchDesigner, or Three.js.
from distforge import box, sphere
scene = box(1.5) - sphere(1.2)
scene.export_shader("exported_shader.glsl")
Installation
1. System Dependencies
The live viewer relies on glfw, which may require you to install its system-level libraries first. This is a common first step before installing the Python package.
On Debian/Ubuntu:
sudo apt-get install libglfw3-dev
On macOS (with Homebrew):
brew install glfw
On Windows:
glfw is generally bundled with the Python wheels, so no separate installation is typically needed.
2. Python Package
The library and its core dependencies can be installed using pip.
Standard Installation:
This will install the core library, including numpy, moderngl, and glfw, enabling all fundamental features like modeling, live preview with hot-reloading, and exporting to .stl and .obj formats.
pip install distforge
Optional Features: For additional functionality, you can install "extras":
-
.glbExport: To enable saving models to the GLB format, a modern and efficient format for web and game engines.pip install "distforge[export]"
-
Interactive UI: To enable UI widgets like sliders for
Paramobjects.pip install "distforge[ui]"
-
Full Installation: To install all optional features at once.
pip install "distforge[full]"
Acknowledgements
This project is inspired by the simplicity and elegant API of Michael Fogleman's fogleman/sdf library. DistForge aims to build on that foundation by adding a real-time, interactive GLSL-powered renderer.
Metadata
Release files for distforge 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| distforge-1.0.0.tar.gz | 89.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| distforge-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 199.8 kB
Release files / distforge-1.0.0.tar.gz
| Download URL | distforge-1.0.0.tar.gz |
|---|---|
| Size | 89.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0f39fdf5882bd52e903ee45a907ae261cca3be277293391a3eb6832452718f96
|
|
BLAKE2b-256 checksum How to use checksums |
5646fface7ba1be92b35d6bd8ff556a0dcd117eae2f9691f0c7f8ba041779b49
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / distforge-1.0.0-py3-none-any.whl
| Download URL | distforge-1.0.0-py3-none-any.whl |
|---|---|
| Size | 110.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2661a36230db15b3a26b4d34f9995a645d4103177d19b8487064af5821e85356
|
|
BLAKE2b-256 checksum How to use checksums |
26994eb01dfdac83750b99f25a0008309906410d204d2e7ca0e4e9dbda777a09
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|