Skip to main content

A Python library for SDF modeling with real-time GLSL rendering and mesh export.

Project description

SDForge Logo

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 (|, -, &).
  • Real-time Rendering with Hot-Reloading: Get instant visual feedback in a lightweight native window powered by moderngl and glfw.
  • Mesh Exporting: Save your creations as .stl files for 3D printing or use in other software.
  • Flexible Scene Construction: Write custom SDF logic directly in GLSL, easily assign different materials to individual objects, etc.

Hello Forge

Define a simple shape and open a real-time preview window with a couple lines:

from sdforge import *

# A sphere intersected with a box
shape = sphere(1) & box(1.5)

# Render a preview in a native window.
shape.render()

Basics

Defining & Combining Shapes

You can 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 *

# A sphere intersected with a box
f = sphere(1) & box(1.5)

# Subtract three cylinders along each axis
c = cylinder(0.5)
f -= c.orient(X) | c.orient(Y) | c.orient(Z)

f.render()

Live Preview & Hot-Reloading

For an interactive workflow, wrap your scene definition in a function and use the watch flag. When you save any changes to the file, the preview window will automatically update.

from sdforge import *

def main():
    f = sphere(1) & box(1.5)
    return f

if __name__ == '__main__':
    f = main()

    # The view will update every time you save the source file.
    f.render(watch=True)

Saving to a Mesh File

You can save any static (non-animated) model to an .stl file for 3D printing or for use in other software. The .save() method uses the Marching Cubes algorithm to generate a mesh from the SDF.

# Save the model to an .stl file.
f.save('model.stl', samples=2**24) # Higher samples = more detail

Advanced

GLSL Injection`

Many functions and object properties can accept GLSL expressions as strings. For e.g you can use the u_time uniform, which contains the elapsed time in seconds, to create animations.

from sdforge import *

# Animate a box's size using the u_time uniform
f = box(size="0.5 + 0.3 * sin(u_time)")

f.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 *

# A standard library primitive
s = sphere(1.2)

# A custom shape defined with GLSL
# 'p' is the vec3 point in space
custom_twist = Forge("""
    float k = 10.0;
    float c = cos(k*p.y);
    float s = sin(k*p.y);
    mat2  m = mat2(c,-s,s,c);
    vec3  q = vec3(m*p.xz,p.y);
    return length(q) - 0.5;
""")

f = s - custom_twist

f.render()

Custom Camera Controls

You can override the default mouse-orbit camera to create cinematic animations or set a static viewpoint. The Camera object accepts GLSL expressions for its position and target, which will be updated every frame.

from sdforge import *

def main():
    shape = sphere(1) & box(1.5)

    # An animated camera that orbits around the origin
    cam = Camera(
        position=(
            "5.0 * sin(u_time * 0.5)",
            "3.0",
            "5.0 * cos(u_time * 0.5)"
        ),
        target=(0, 0, 0)
    )
    return shape, cam

if __name__ == '__main__':
    sdf_object, camera_object = main()
    sdf_object.render(camera=camera_object, watch=True)

Custom Light Controls

You can customize the scene's light, including light position, ambient light, and shadow softness. The Light object also accepts GLSL expressions for its properties.

from sdforge import *

def main():
    shape = sphere(1) - cylinder(0.5)
    camera = Camera(
        position=(
            "5.0 * sin(u_time * 0.5)", 
            "3.0", 
            "5.0 * cos(u_time * 0.5)"
        )
    )

    # An animated light source with soft shadows
    light = Light(
        position=(
            "8.0 * sin(u_time * 0.3)",
            "5.0",
            "8.0 * cos(u_time * 0.3)"
        ),
        ambient_strength=0.05,
        shadow_softness="8.0 + 7.0 * sin(u_time * 0.7)"
    )

    return shape, camera, light

if __name__ == '__main__':
    sdf_obj, cam_obj, light_obj = main()
    sdf_obj.render(camera=cam_obj, light=light_obj, watch=True)

Assigning Materials

You can assign a unique color to any object or group of objects using the .color() method. The renderer will automatically handle combining the shapes and their materials correctly.

from sdforge import *

red_sphere = sphere(0.8).color(1, 0, 0)
blue_box = box(1.2).color(0, 0, 1)

# The union operation will correctly preserve the material of the closest surface
model = red_sphere | blue_box.translate(X * 0.5)

# You can also set a custom background color
model.render(bg_color=(0.1, 0.2, 0.3))

Recording to Video

You can record an interactive session to an MP4 video file by passing the record argument to the .render() method. This requires the optional [record] dependencies.

from sdforge import *

# Animate a box size using the u_time uniform
f = box(size="0.5 + 0.3 * sin(u_time)")

# Render and record the output to a video file.
# Close the window to stop the recording.
f.render(record="animated_box.mp4")

Installation

The library and its core dependencies can be installed using pip:

pip install sdforge

To enable optional video recording features, install with the [record] extra:

pip install sdforge[record]

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

sdforge-0.1.2.tar.gz (25.9 kB view details)

Uploaded Source

Built Distribution

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

sdforge-0.1.2-py3-none-any.whl (24.9 kB view details)

Uploaded Python 3

File details

Details for the file sdforge-0.1.2.tar.gz.

File metadata

  • Download URL: sdforge-0.1.2.tar.gz
  • Upload date:
  • Size: 25.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for sdforge-0.1.2.tar.gz
Algorithm Hash digest
SHA256 3656caa1722e8a26898cbba9662fe67de8e5383f64c8da73c71a02f518919a89
MD5 9ca77e0d29504c4b03fe6cc13ea3086e
BLAKE2b-256 47438192dbba770416652c5f34648b9c3506c3366a7096cd93c58819f64c810c

See more details on using hashes here.

File details

Details for the file sdforge-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: sdforge-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 24.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for sdforge-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 2ff7804860b023f7283823647f08b4226af92ba7ada8cfd808239795ff30fcc2
MD5 b0dac34305b779d5af1fe11ae20f9ea8
BLAKE2b-256 2dc49908ec86d14fd22019374d45fd7056384df89f9423bf1f774c483478c58a

See more details on using hashes here.

Supported by

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