Welcome to the Hall of Mirrors 3D manual! This app is a real-time, GPU-accelerated 3D raymarching environment built in Godot. It lets you construct and render complex geometric sculptures, infinite optical mirror chambers, and space group crystallographic lattices—all generated procedurally via Signed Distance Fields (SDFs).
Because the environment is drawn directly on the GPU using raymarching, you are flying inside a mathematical world rather than around standard 3D meshes.
Mouse Left-Click + Drag: Rotate view (Look around).
W / S: Move forward / backward.
A / D: Strafe left / right.
Q / E: Move down / up.
Move Speed Slider: Adjusts how quickly the camera travels through space.
Note: Camera control is disabled whenever a text input field, file dialog, or preset menu is active.
Use the Renderer dropdown at the top of the interface to switch between the two available raymarching pipelines:
Creates an optical chamber using real-time reflective geometric solids and bounding mirror surfaces. It simulates multiple light bounces inside an enclosed room.
Generates three-dimensional, perfectly repeating spatial structures based on formal Crystallographic Space Groups. Instead of simple primitive arrays, it uses symmetry transformations ($M \cdot p + t$) combined with procedural non-linear fold operators.
When in Mirrors mode, the sidebar exposes options for room geometry and reflective primitives:
Sides: Sets the polygon count for the surrounding vertical mirror tube (2 to 12 walls).
Radius / Height: Controls the scale and proportions of the mirror chamber.
Tilt / Spin: Rotates and skews the wall angles.
Floor / Ceiling Mirrors: Enables or disables reflective horizontal planes above and below.
Enable individual geometry objects inside the chamber:
Sphere (Witch Ball): Optional faceted "disco ball" mode via the Facets count slider. Can be set to render the camera inside or outside the sphere.
Cylinder, Torus, & Cone Mirrors: Toggleable central curved reflective primitives with adjustable major/minor radii and angles.
Bounces: Maximum ray reflection depth (1 to 48). Higher values yield deeper recursive optical reflections at the cost of GPU performance.
Reflectance & Fresnel: Adjusts light falloff, metal absorption, and edge reflection intensity.
Metal: Pick metallic color presets (Chrome, Gold, Copper, Silver, Rose).
When in Crystal mode, you design unit-cell geometries using crystallographic symmetry matrices and non-linear folds.
+-------------------------------------------------------+
| Space Group Lattice |
| (P1, P-1, P2/m, Pmmm, P4/mmm, Pm-3m, Im-3m, etc.) |
+-------------------------------------------------------+
|
v
+-------------------------------------------------------+
| Non-Linear Fold Stack (0 to 8) |
| (Polar Fold, Rosette, Mirror Plane, Polyhedral, etc.)|
+-------------------------------------------------------+
|
v
+-------------------------------------------------------+
| Base Motif Primitive |
| (Sphere, Box, Rod + Displacement) |
+-------------------------------------------------------+
Select from 18 fundamental space groups (ranging from simple triclinic P1 to complex cubic body-centered Im-3m).
Cell Size: Adjusts the unit-cell bounding box dimensions.
Motif Primitive: Choose the base repeating seed shape (Sphere, Box, or Rod).
Site X, Y, Z: Offsets the base motif's origin inside the unit cell before symmetry operations are evaluated.
You can layer up to 8 procedural domain folds in sequence. Order matters—shifting fold positions changes the resulting geometry. Available folds include:
Polar Fold Dn: Rotational repetition around the Z-axis with mirrored symmetry.
Rosette Cn: Pure rotational symmetry folds.
Mirror Plane: Clips and reflects space across cardinal axes.
Polyhedral: Folds space into octahedral or icosahedral fundamental domains.
Twist: Applies a continuous spatial twist along the vertical axis.
Kleinian 3D: Iterated sphere inversions in a ring, generating fractal limit sets with variable sphere count, scale, lift, and iteration depth.
Displacement: Range $-1.0$ to $1.0$. Uses the luminance of a loaded photo to push the motif surface inward or outward.
Positive ($0.0$ to $1.0$): Light areas extend outward (close); dark areas pull inward (far).
Negative ($-1.0$ to $0.0$): Dark areas extend outward (close); light areas pull inward (far).
Disp Blur: Sets the texture LOD level (blur) for height sampling. Blurring stabilizes normal calculations on high-contrast source photos.
The built-in keyframe system animates camera movements, structural parameters, and fold stack variables smoothly over time.
Control
Function
+ Key
Captures all current material parameters, camera coordinates, and fold settings at the active timeline position.
Play / Stop
Toggles real-time preview playback.
Close Loop
Copies the first keyframe to the exact end timestamp, ensuring a seamless animation loop.
Copy / Paste
Duplicate keyframe states across different timeline positions.
Render Sequence
Opens the folder picker to render frames.
Set Length (s), FPS (24, 30, 60), and enable Seamless Loop if desired.
Click Render Sequence... and select an output folder.
The engine renders off-screen PNG frames (HOM YYYY-MM-DD HH-MM-SS_#####.png).
If ffmpeg is available on your system path, the app automatically compiles the frame sequence into an H.264 MP4 video.
Click Load Image... to supply a custom texture. Supported formats: .png, .jpg, .webp, .bmp.
Applied to objects in Mirror mode via triplanar mapping, and drives height-field displacement and coloring in Crystal mode.
Export Sizes: 1080p, 1440p, 2160p (4K), or 4320p (8K).
Supersample 2x: Renders off-screen at double resolution before Lanczos downsampling to eliminate raymarching noise and aliasing.
Click Save PNG... to export the current view.
Presets record the full state of your scene—including group index, fold parameters, lighting, aspect ratios, and full keyframe animation tracks.
Save Preset: Saves scene configurations as .json files.
Include Animation: Toggleable checkbox to choose whether keyframe timelines are stored inside the preset file.
Note: Preset files store procedural parameters and references, not the image file itself. Re-load your source texture after opening a preset if needed.