Skip to content

Repository files navigation

neural-implicit-fields

A compact, self-contained PyTorch demonstrator for coordinate-based neural fields as continuous representations of 3D geometry. A multilayer perceptron $f_\theta:(x,y,z)\mapsto\text{value}$ is fit to a target shape and rendered with a differentiable renderer, so an image / depth / silhouette loss back-propagates all the way into the network weights.

It is the bridge from discrete geometry-processing meshes to the continuous, learned representations of modern 3D computer vision (neural SDFs, DeepSDF, NeRF). The same coordinate-network core drives two families:

  • a neural signed distance field ($f_\theta:\mathbb{R}^3\to\mathbb{R}$), rendered by sphere tracing, and
  • a NeRF-style radiance field ($x\mapsto(\sigma,\mathbf{c})$), rendered by emission–absorption volume integration.

The defining choices:

  • A shape is a function, not a mesh. Geometry lives in the weights $\theta$ of a small MLP. It has no resolution: it is queried at any real coordinate, and meshed by marching cubes only when an explicit surface is wanted.
  • Normals are autodiff, not stencils. The surface normal is $\nabla_x f_\theta$ via torch.autograd with create_graph=True, so a renderer that shades with normals stays differentiable end-to-end.
  • Fitting is gradient descent through the renderer. Because the sphere march is an unrolled differentiable computation, the field can be learned from images alone (inverse rendering), not just from ground-truth distances.

Mathematical background, including the mesh ↔ SDF ↔ neural-field duality and the IGR / Eikonal recipe, is written up in docs/theory.md.


The pipeline, mapped to the code

Stage Module What it does
Input encoding encoding.py NeRF positional (Fourier-feature) encoding $\gamma(x)$
The neural field field.py Coordinate MLP: neural SDF or density/colour field; autodiff normals
Target geometry geometry.py Analytic SDFs + CSG, samplers, marching-cubes mesh extraction
Differentiable rendering render.py Sphere tracing + NeRF volume rendering; cameras and rays
Objectives losses.py SDF, Eikonal, normal (geometric); depth, silhouette (rendered)
Optimisation training.py fit_geometric (3D supervision) and fit_rendered (inverse render)

Mathematical background

The field

A neural field is a small MLP on raw coordinates. With a single output it is a signed distance function whose zero level set is the surface,

$$ \mathcal{S} = {, x \in \mathbb{R}^3 : f_\theta(x) = 0 ,}, \qquad f_\theta < 0 \ \text{inside},\quad f_\theta > 0 \ \text{outside}. $$

The (normalised) gradient is the surface normal, obtained by autodiff: $n(x) = \nabla_x f_\theta(x) / \lVert \nabla_x f_\theta(x)\rVert$.

Geometric objective (IGR)

To make the learned field an honest distance field, it is regularised towards the Eikonal equation $\lVert\nabla_x f\rVert = 1$:

$$ \mathcal{L} = \lambda_\text{sdf}, \mathbb{E}\big[|f_\theta(x) - d(x)|\big]

  • \lambda_\text{eik}, \mathbb{E}\big[(\lVert\nabla_x f_\theta\rVert - 1)^2\big]
  • \lambda_\text{nrm}, \mathbb{E}{x\in\mathcal{S}}\big[1 - n\theta!\cdot n\big]. $$

A geometric initialisation starts $f_\theta(x)\approx\lVert x\rVert - r$ (a sphere), and softplus activations keep the normals smooth. Every $\lambda$ is a config field — a new regulariser is a new weight, never a loop edit.

Differentiable rendering

Sphere tracing advances each camera ray by the field's own value, which is a safe step length because it is the distance to the surface:

$$ t \leftarrow t + f_\theta\big(o + t,d\big). $$

Unrolling the march makes the hit point, depth, normals, and silhouette differentiable in $\theta$, so a render loss trains the field from images. The NeRF volume integral $C=\sum_i T_i,(1-e^{-\sigma_i\delta_i}),\mathbf{c}_i$ (with transmittance $T_i$) is the density-field counterpart.


Results

All figures are produced on CPU by the scripts in examples/. A fitted field, meshed at three resolutions, can be inspected interactively in the live demo (GitHub Pages, plain Three.js).

Geometric fit — a neural SDF fit to a target by distance regression + Eikonal, then sphere-traced (examples/fit_geometric.py):

geometric fit

Continuous representation — the same learned field as a dense SDF slice (with its zero level set) and meshed by marching cubes at three resolutions; the triangle count is chosen at extraction time, not baked into the model (examples/manifold_continuity.py):

manifold continuity

Inverse rendering — a field learned from depth + silhouette images alone, with gradients flowing back through the sphere march (examples/inverse_rendering.py):

inverse rendering


Quick start

uv sync --extra dev          # environment (PyTorch, etc.)

# Fit a neural SDF to a shape by direct geometric supervision:
uv run python examples/fit_geometric.py --target blob --iters 2000

# Learn the same kind of field from images only (inverse rendering):
uv run python examples/inverse_rendering.py --target torus --iters 1200

# The "continuous manifold" figure (SDF slice + multi-resolution meshing):
uv run python examples/manifold_continuity.py --target blob

# Mesh a fitted field to OBJ (needs the 'mesh' extra):
uv run python scripts/export_mesh.py --target blob --resolution 192 --out blob.obj

In code:

import torch
from neural_fields import CoordinateMLP, FieldConfig, TrainConfig
from neural_fields import fit_geometric, make_target, render_image, Camera, RenderConfig

field = CoordinateMLP(FieldConfig())                 # (x,y,z) -> signed distance
history = fit_geometric(field, make_target("torus"), TrainConfig(n_iters=2000))

img = render_image(field, Camera.look_at((1.6, 1.1, 1.8)), RenderConfig())  # (H, W, 3)
sdf = field.sdf(torch.zeros(1, 3))                   # query the continuous field anywhere

Available targets: sphere, box, torus, blob, csg.


Project layout

neural-implicit-fields/
├── src/neural_fields/
│   ├── encoding.py       NeRF positional / Fourier-feature encoding
│   ├── field.py          CoordinateMLP (neural SDF) + RadianceField; autodiff normals
│   ├── geometry.py       analytic SDFs, CSG, samplers, marching-cubes extraction
│   ├── render.py         differentiable sphere tracing + NeRF volume rendering
│   ├── losses.py         SDF, Eikonal, normal, depth, silhouette
│   ├── training.py       fit_geometric (3D) and fit_rendered (inverse rendering)
│   ├── config.py         FieldConfig / RenderConfig / TrainConfig dataclasses
│   └── utils.py          seeding, device, checkpoints
├── tests/
│   ├── test_encoding.py  encoding shapes/values
│   ├── test_field.py     forward shapes, init, gradients, radiance head
│   ├── test_geometry.py  analytic SDF values, CSG, sampling, marching cubes
│   ├── test_render.py    rays, sphere-trace depth, soft mask, differentiability
│   ├── test_losses.py    each loss term
│   ├── test_grad.py      torch.autograd.gradcheck (first/second order)
│   └── test_training.py  both fit pipelines reduce their loss
├── examples/             runnable figures (geometric, inverse, manifold)
├── scripts/              fit.py CLI + export_mesh.py
├── web/                  static Pages demo (Three.js viewer of the fitted field)
├── assets/               committed result figures (referenced above)
├── docs/theory.md        coordinate networks as continuous manifold representations
├── CITATION.cff
├── CHANGELOG.md
└── .github/workflows/    ci.yml (ruff + mypy + pytest, 3.10–3.12) + pages.yml (deploy)

Development

uv run ruff check .          # lint (E, F, W, I, UP, B, SIM)
uv run ruff format .         # format (line length 100)
uv run mypy                  # type-check src/
uv run pytest                # 42 tests, incl. gradient checks + convergence

Gradient correctness is a first-class invariant: any new differentiable operation comes with a torch.autograd.gradcheck test, since a silently broken gradient (an in-place op, or a non-differentiable step slipping into the ray march) is the most common and costly bug in differentiable-geometry code.


Citation

See CITATION.cff. This work builds on Implicit Geometric Regularization (Gropp et al., 2020), DeepSDF (Park et al., 2019), NeRF (Mildenhall et al., 2020), and sphere tracing (Hart, 1996).

License

MIT — see LICENSE.

About

Coordinate-based neural fields (neural SDFs / radiance fields) fit to 3D geometry by differentiable sphere tracing in PyTorch

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages