A Python library for SDF modeling with real-time GLSL rendering and mesh export.
Project description
About
SDF Forge 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 sdforge import sphere, box
# A sphere intersected with a box
shape = sphere(1) & box(1.5)
# Render a preview in a native window.
# An interactive orbit camera is used by default.
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 sdforge 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.5
sphere_radius = 1.2
scene = box(box_size, radius=0.1) | sphere(sphere_radius)
return scene
if __name__ == "__main__":
# The render() function automatically enables hot-reloading by default
# and looks for a `main` function in this file to call upon reload.
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 sdforge import sphere, box
# A box with a sphere carved out of it
shape = box(1.5) - sphere(1.2)
# Save the model. Higher samples = more detail.
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 sdforge import sphere, box
# A box with a sphere carved out of it.
b = box(size=1.5)
s = sphere(r=1.0)
scene = b - s
scene.render()
Transformations & Shaping
Chain methods to transform, shape, and repeat objects.
import numpy as np
from sdforge import box, Y
# A tall box
b = box(size=(0.5, 2.5, 0.5))
# Twist it around the Y-axis
# The 'k' parameter controls the amount of twist.
scene = b.twist(k=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 sdforge import sphere, box
# A blue sphere is subtracted from a red box.
red_box = box(1.5, radius=0.1).color(1.0, 0.2, 0.2)
blue_sphere = sphere(1.2).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 sdforge import box, sphere, Camera, Light
def main():
scene = box(1.5, radius=0.1) | sphere(1.2)
# A camera positioned at (4, 3, 4), looking at the origin.
cam = Camera(position=(4, 3, 4), target=(0, 0, 0), zoom=1.5)
# A light source with soft shadows
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 sdforge import box, Param
# Create Param objects to control different aspects of the scene.
# Param(name, default_value, min_value, max_value)
p_size = Param("Box Size", 0.8, 0.2, 2.0)
p_radius = Param("Corner Radius", 0.1, 0.0, 0.5)
# Use the Param objects just like regular numbers.
scene = box(size=p_size, radius=p_radius)
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 sdforge import sphere, Forge
# A standard library primitive
s = sphere(1.2)
# A custom shape defined with GLSL
# 'p' is the vec3 point in space
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);
""")
# The Forge object can be combined like any other shape
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 sdforge import box, sphere
scene = box(1.5, radius=0.1) - sphere(1.2)
# This single call generates the entire shader file.
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 sdforge
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 "sdforge[export]"
-
Interactive UI: To enable UI widgets like sliders for
Paramobjects.pip install "sdforge[ui]"
-
Full Installation: To install all optional features at once.
pip install "sdforge[full]"
Acknowledgements
This project is inspired by the simplicity and elegant API of Michael Fogleman's fogleman/sdf library. SDF Forge aims to build on that foundation by adding a real-time, interactive GLSL-powered renderer.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sdforge-0.2.1.tar.gz.
File metadata
- Download URL: sdforge-0.2.1.tar.gz
- Upload date:
- Size: 89.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f25bb042330c5ac9198c5f4ec5c2530bb26841e4f66b5f6c5ff3eeba01dae230
|
|
| MD5 |
761425e7a225cfd9d8d3cfbd63e8e65a
|
|
| BLAKE2b-256 |
bb28c5733f77e177157c30b7d4a99688775dcd196df1b77b97fe2bf41c9a6dff
|
File details
Details for the file sdforge-0.2.1-py3-none-any.whl.
File metadata
- Download URL: sdforge-0.2.1-py3-none-any.whl
- Upload date:
- Size: 112.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d4c2dbfca1900603c86b38b240624bf2bb5e060c1bcc5127bb327b636df93cab
|
|
| MD5 |
983219b30ac93c06cb68d4dd559a9eb2
|
|
| BLAKE2b-256 |
22f6b9b1f0229a3fa06cacd3d66cec97c80fb4467bddbd9cf99b42e1e7df883d
|