Use the live view to compose, then open Take a shot. A capture keeps the scene time and physics fixed, renders a finite sample budget, exports the result, and restores the preview settings. Camera motion can be integrated into one exposure or exported as a time-lapse image sequence.
Controls
- Choose a camera in Camera → Model: Pinhole, Thin Lens, or Tilt / shift. The selection changes the CPU camera object as well as the GPU camera model.
- Set focal length, focus distance, f-stop, and pupil shape. For a tilted lens, start with small angles: at long focus distances a fraction of a degree of sensor tilt can move the focus plane substantially.
- In Take a shot, set output size and the sample/pass budget. Keep the current framing / aspect preserves the current image proportions. Increasing pixel count and sample count are separate costs.
- Select Current renderer, higher quality, or CPU VCM comparison. The latter changes the estimator. It does not promise that CPU VCM supports every GPU material, projector, volume, or display feature.
- Press Take a shot. Progress includes camera samples and sequence images. Cancel keeps already exported sequence frames and restores the preview. A long CPU render pass must return before cancellation can be handled.
Files are placed in shots/<timestamp>/. Each image has JSON metadata recording sample budget, selected renderer, camera, frozen scene time, and export conventions.
What is saved
| File | Content |
|---|---|
Still .png |
Finished viewport display before selection outlines, retaining supported display effects. |
Motion .png |
Mean scene-linear radiance over camera samples, followed by exposure, Reinhard mapping, and gamma 2.2 once. It does not average already tone-mapped images. |
.hdr and .pfm |
Scene-linear accumulated film when that renderer exposes one. These omit postprocessing and retain values above 1. PFM is 32-bit floating point per RGB channel. |
.json |
Reproduction and scope information. |
GPU tracing, CPU VCM, UPBP, path guiding, and photon primitives expose a linear film for this workflow. Other renderer paths currently support still PNG capture rather than an assumed linear export. Raster capture increases resolution; repeated identical raster passes do not improve sampling quality. Existing estimators retain their own limitations, including any reconstruction kernels or clamps.
Camera motion
Pan rotates the view direction around camera up. Orbit rotates the position around the current look-at point. Dolly moves toward or away from that point and adjusts focus distance by the travel. Dolly zoom also adjusts focal length to approximately retain subject size. Forward travel stops before passing through the target.
A photograph samples the movement at shutter-interval midpoints and gives each camera position the full requested pass budget. For example, 16 camera samples at 128 passes means 2,048 render passes, not 128 total. Increasing camera samples removes stepping in motion blur; increasing passes reduces each image's sampling noise. Both can matter independently.
A sequence subdivides the same path into output frames. Shutter / frame interval controls how much of each interval is integrated. The scene itself remains frozen: this is camera-motion photography, not a simulation-time recorder or a general rolling-shutter path tracer. Camera shutterOpen/shutterClose remain separate ray-time fields; the capture scheduler does not pretend that every estimator interprets them.
Tilt and shift: implemented geometry
The physical mode uses an ideal paraxial thin lens. The sensor, lens, and focused object plane satisfy the thin-lens conjugacy relationship; for planar geometry their extensions intersect along the Scheimpflug line. A real tilt lens can have different principal planes and pupil magnification, so this is a useful optical model rather than a complete lens prescription. See Steger, A Comprehensive and Versatile Camera Model for Cameras with Tilt Lenses and the rendering-oriented chapter 31 in Ray Tracing Gems II.
Controls are independent:
- Lens tilt X/Y rotates the lens plane about its center.
- Lens shift X/Y translates the lens relative to the camera/sensor.
- Sensor tilt X/Y rotates the sensor about its center.
- Sensor shift X/Y moves the sensor laterally. Lens shift and sensor shift have different signs and different aperture origins; they are not interchangeable camera rotations.
- Focus distance sets the untilted sensor distance through the thin-lens equation; tilting then changes the plane of focus.
- Pupil rotation rotates bokeh; anamorphic ratio stretches the pupil. This does not model a complete cylindrical/anamorphic lens with its own direction-dependent focal powers.
With lens center L, sensor point S, a sampled pupil point A, backward lens normal n, and focal length f, define v = dot(S − L, n). The conjugate point is
X = L + (L − S) f / (v − f).
All pupil samples for the same sensor pixel point toward X. The outgoing ray is evaluated homogeneously:
direction ∝ (L − S) f + (L − A) (v − f).
This avoids dividing by zero as the focus moves to infinity. Beyond that boundary the lens can have a virtual rather than a real forward conjugate; extreme tilt should not be interpreted as an arbitrary sharp plane everywhere in the image. CPU and GPU use the same equations, sensor inversion, pupil distribution, and coordinate conventions.
The untilted Thin Lens and Pinhole models keep their established framing. The new physical tilted model uses a fixed sensor, so it has the small focus-breathing change associated with adjusting the lens conjugate distance. The existing nominal sensor-height convention (filmSize × 0.6) is retained to avoid changing all old compositions.
Apertures and comparison modes
Shared camera-ray aperture options are circle, hexagon, square, star, and an arbitrary regular polygon. Polygon and star samples use equal-area triangle fans; each sample represents equal pupil area. Rotation and horizontal stretch apply after sampling.
The legacy CPU VCM, UPBP, path-guiding, MLT and manifold implementations construct their own pinhole eye rays. Their linear films do not imply support for a finite or tilted pupil. The photon-primitive implementation has a separate fixed-pupil path. Capture must therefore require a pinhole for these CPU comparisons rather than silently replacing a composed depth-of-field image with a sharp one. This is independent of whether the estimator has otherwise sophisticated light transport.
The original GPU cross/star/ellipse controls remain available as Legacy GPU Aperture Shape. Light-tracing/BDPT camera connections continue using that original pupil/projection/PDF path. Shared shapes are used by CPU camera rays and GPU naive/NEE/MIS eye rays. For physical tilt/shift, use those eye-ray strategies: the old LT/BDPT connection does not yet have a tilted-lens camera PDF. Capture rejects unsupported GPU combinations rather than saving a falsely matched result.
Turning off Physical thin-lens conjugate model restores the original artistic CPU-only tilt model for comparison. GPU then uses an untilted thin-lens approximation, not a matched legacy tilt implementation. This distinction is shown in the Camera panel.
Artistic focus / curved sensor exposes the older world-plane override and sensor curvature. A chosen world focus plane converges rays there, but does not solve a realizable lens/sensor configuration. Curved sensors have no single planar inverse projection and are excluded from Camera::project. The GPU focus indicator follows the per-pixel physical conjugate distance, although it remains a relative-distance visualization rather than a measured blur-circle diameter.
Not modeled: multi-element internal surfaces, entrance/exit pupil separation, mechanical housing and shift limits, vignetting, optical aberration correction, diffraction, or a spectral lens prescription. Raster projection and screen-space postprocessing still assume a pinhole camera; they cannot replace a traced tilted lens. Aperture size currently changes depth of field, not calibrated sensor exposure throughput.
Presets
Camera → Camera preset saves/loads a JSON file; the default path is camera-presets/latest.json. The editable path permits named presets. It includes camera pose, lens and sensor geometry, aperture, world focus plane, and physical/legacy flags. Loading validates finite values and a usable orientation before replacing anything. These files are independent of prism.json and do not overwrite a scene.
Verification
PrismPhotoCameraTest checks the three-plane Scheimpflug intersection, convergence from independent pupil samples, inverse pixel projection, finite rays at extreme tilts, pupil centroids and area moments, linear HDR integration, camera sequencing, cancellation, and rejection of non-finite films. The current suite passes 203,189 checks.
PrismCameraGPUTest creates a hidden OpenGL 4.6 context, compiles the actual pt_camera.glsl, dispatches rays, reads them back, and compares with TiltShiftCamera::generateRay. Across 2,560 rays, five aperture families, and sensor-curvature/world-plane cases, maximum origin difference was 4.8 × 10⁻⁷ m and maximum direction-vector difference was 1.91 × 10⁻⁷ on the tested machine. These are model/parity tests, not a calibration of a real manufactured lens.