RayCastMapper for SDF

Jens Munk Hansen
Tue, 05 May 2026 17:27:40 +0000
Development

Hi Developers

We’ve prototyped a single-surface sphere-tracing mapper by forking
vtkOpenGLGPUVolumeRayCastMapper. The fork keeps all of the parent’s
pipeline plumbing — NDC→texture ray setup, depth-buffer composition,
clipping, picking, OpenGL state — and only diverges in the per-step
behaviour and the iso-hit write. The input is a vtkImageData whose
active point scalar is a signed distance field.

Three display modes are exposed on the mapper:

- Normals: the eye-space outward normal at the iso hit, encoded as
  RGB. Useful as a quick correctness check.
- Color: per-voxel albedo from a sidecar 3-D texture, sampled
  trilinearly at the hit. Multi-light Phong intentionally matches
  vtkPolyDataMapper's output for the same scene lights, so the
  volume render is interchangeable with a polydata reference.
- Flat: a constant colour read once per render from the volume
  property's RGB transfer function.

The sphere trace handles truncated SDFs cleanly: voxels holding a
“no info” sentinel are skipped instead of being bracketed, so the
trace doesn’t fire on the spurious zero crossing at the truncation
boundary. The hit position is bisected to sub-voxel precision before
the gradient sample. Step fraction, bisection iterations, sentinel
threshold and eps tolerance are exposed as Set/Get knobs on the mapper.

We’ve validated visually side-by-side against vtkPolyDataMapper of the
same surface under both parallel and perspective projection, including
camera positions inside the model where the trace must hit a back-face
of the surface.

I made this for understanding the plumbing. Hopefully, I will soon move into the area of TSDF with fast updates. It is still in early development, currently adding C++ tests for validation agains rendering using vtkPolyDataMapper.

Would something along these lines be of interest as an option / display
mode on vtkOpenGLGPUVolumeRayCastMapper itself, or do you see iso
ray casting (sphere-traced, single-surface, opaque) as better kept in
a separate class? If a separate class, it could share the utilities using by the existing vtkOpenGLGPUVolumeRayCastMapper

Just a small example. Difficult to maintain sharp edges without increasing the resolution of the SDF, therefore the attempt for implementing a fast sparse TSDF.

1 post - 1 participant

Read full topic