scirs2_vision/nerf/types.rs
1//! Core types for Neural Radiance Fields (NeRF) and Instant-NGP.
2//!
3//! Defines configuration structs, ray/sample types, and rendering result types
4//! used across the NeRF implementation.
5
6/// Configuration for a standard NeRF MLP model (Mildenhall et al. 2020).
7#[derive(Debug, Clone)]
8#[non_exhaustive]
9pub struct NerfConfig {
10 /// Number of hidden layers in the geometry network.
11 pub n_layers: usize,
12 /// Width (number of units) of each hidden layer.
13 pub hidden_dim: usize,
14 /// Number of frequency bands for positional encoding of 3-D location.
15 pub n_freq_pos: usize,
16 /// Number of frequency bands for positional encoding of view direction.
17 pub n_freq_dir: usize,
18 /// Near clipping distance along the ray.
19 pub near: f64,
20 /// Far clipping distance along the ray.
21 pub far: f64,
22 /// Number of coarse stratified samples per ray.
23 pub n_samples: usize,
24 /// Number of additional importance samples per ray (hierarchical sampling).
25 pub n_importance: usize,
26}
27
28impl Default for NerfConfig {
29 fn default() -> Self {
30 Self {
31 n_layers: 8,
32 hidden_dim: 256,
33 n_freq_pos: 10,
34 n_freq_dir: 4,
35 near: 2.0,
36 far: 6.0,
37 n_samples: 64,
38 n_importance: 128,
39 }
40 }
41}
42
43/// Configuration for Instant-NGP multi-resolution hash encoding (Müller et al. 2022).
44#[derive(Debug, Clone)]
45#[non_exhaustive]
46pub struct NgpConfig {
47 /// Number of resolution levels in the hash grid hierarchy.
48 pub n_levels: usize,
49 /// Number of feature dimensions stored per hash entry per level.
50 pub n_features_per_level: usize,
51 /// log₂ of the hash table capacity at each level.
52 pub log2_hashmap_size: usize,
53 /// Grid resolution at the coarsest level.
54 pub base_resolution: usize,
55 /// Grid resolution at the finest level.
56 pub finest_resolution: usize,
57}
58
59impl Default for NgpConfig {
60 fn default() -> Self {
61 Self {
62 n_levels: 16,
63 n_features_per_level: 2,
64 log2_hashmap_size: 19,
65 base_resolution: 16,
66 finest_resolution: 512,
67 }
68 }
69}
70
71/// A camera ray defined by an origin point and a unit-length direction vector.
72#[derive(Debug, Clone, Copy)]
73pub struct Ray {
74 /// World-space origin of the ray (camera position).
75 pub origin: [f64; 3],
76 /// Unit-length direction vector of the ray in world space.
77 pub direction: [f64; 3],
78}
79
80impl Ray {
81 /// Construct a new [`Ray`], normalising `direction` to unit length.
82 ///
83 /// Returns `None` when `direction` has zero (or near-zero) magnitude.
84 pub fn new(origin: [f64; 3], direction: [f64; 3]) -> Option<Self> {
85 let mag = (direction[0] * direction[0]
86 + direction[1] * direction[1]
87 + direction[2] * direction[2])
88 .sqrt();
89 if mag < 1e-12 {
90 return None;
91 }
92 Some(Self {
93 origin,
94 direction: [direction[0] / mag, direction[1] / mag, direction[2] / mag],
95 })
96 }
97
98 /// Evaluate the ray at parameter `t`: `origin + t * direction`.
99 #[inline]
100 pub fn at(&self, t: f64) -> [f64; 3] {
101 [
102 self.origin[0] + t * self.direction[0],
103 self.origin[1] + t * self.direction[1],
104 self.origin[2] + t * self.direction[2],
105 ]
106 }
107}
108
109/// A single volumetric sample along a ray.
110#[derive(Debug, Clone)]
111pub struct SamplePoint {
112 /// World-space 3-D position of the sample.
113 pub position: [f64; 3],
114 /// Distance along the ray at which this sample was taken.
115 pub t: f64,
116 /// Volume density σ predicted by the MLP (non-negative).
117 pub density: f64,
118 /// RGB radiance (each channel in [0, 1]) predicted by the MLP.
119 pub color: [f64; 3],
120}
121
122impl SamplePoint {
123 /// Create a new sample, clamping `density` to ≥ 0.
124 pub fn new(position: [f64; 3], t: f64, density: f64, color: [f64; 3]) -> Self {
125 Self {
126 position,
127 t,
128 density: density.max(0.0),
129 color: [
130 color[0].clamp(0.0, 1.0),
131 color[1].clamp(0.0, 1.0),
132 color[2].clamp(0.0, 1.0),
133 ],
134 }
135 }
136}
137
138/// Output of the discrete volume-rendering integral.
139#[derive(Debug, Clone)]
140pub struct VolumeRenderResult {
141 /// Rendered RGB color for the ray (each channel in [0, 1]).
142 pub color: [f64; 3],
143 /// Expected depth — weighted sum of sample distances.
144 pub depth: f64,
145 /// Accumulated transmittance remaining after all samples.
146 pub transmittance: f64,
147 /// Per-sample alpha-compositing weights (Tᵢ · αᵢ).
148 pub weights: Vec<f64>,
149}