• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ekarpp / lumo / 14235426927

03 Apr 2025 03:53AM UTC coverage: 72.653%. First build
14235426927

push

github

ekarpp
0.6.1

* Generalize thread pool
* Paralellize material parsing for scenes
* Implement variable wavelength index of refraction (and dispersion)
* Implement efficiency optimized russian roulette
* Add batching to samplers
* Restricts mediums to scene boundaries
* Fix cylinder bounding box
* Fix instance sample on normals
* Update github actions

290 of 821 new or added lines in 36 files covered. (35.32%)

6740 of 9277 relevant lines covered (72.65%)

39613243.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/renderer/task.rs
1
use super::*;
2

3
#[derive(Clone)]
4
pub struct RenderTaskExecutor {
5
    camera: Arc<Camera>,
6
    scene: Arc<Scene>,
7
    sampler: SamplerType,
8
    integrator: Integrator,
9
    tone_map: ToneMap,
10
}
11

12
impl RenderTaskExecutor {
NEW
13
    pub fn new(
×
NEW
14
        camera: Arc<Camera>,
×
NEW
15
        scene: Arc<Scene>,
×
NEW
16
        sampler: SamplerType,
×
NEW
17
        integrator: Integrator,
×
NEW
18
        tone_map: ToneMap,
×
NEW
19
    ) -> Self {
×
NEW
20
        Self { camera, scene, sampler, integrator, tone_map }
×
NEW
21
    }
×
22
}
23

24
impl Executor<RenderTask, RenderTaskResult> for RenderTaskExecutor {
NEW
25
    fn exec(&mut self, task: RenderTask) -> RenderTaskResult {
×
NEW
26
        let mut tile = task.tile;
×
NEW
27
        let mut rng = Xorshift::new(task.seed);
×
NEW
28
        let mut ns = [0; SAMPLES_INCREMENT as usize];
×
NEW
29
        let mut fs = [0.0; SAMPLES_INCREMENT as usize];
×
NEW
30
        let mut ptr = 0;
×
NEW
31
        let mut num_rays = 0;
×
NEW
32

×
NEW
33
        let (mi_y, mx_y) = (tile.px_min.y, tile.px_max.y);
×
NEW
34
        let (mi_x, mx_x) = (tile.px_min.x, tile.px_max.x);
×
NEW
35

×
NEW
36
        (mi_y..mx_y).cartesian_product(mi_x..mx_x)
×
NEW
37
            .for_each(|(y, x): (u64, u64)| {
×
NEW
38
                let xy = Vec2::new(x as Float, y as Float);
×
NEW
39
                self.sampler.new(task.batch, task.total_samples, rng.gen_u64())
×
NEW
40
                    .flat_map(|rand_sq: Vec2| {
×
NEW
41
                        let raster_xy = xy + rand_sq;
×
NEW
42
                        let f = (0..task.samples)
×
NEW
43
                            .fold(0.0, |acc, i| acc + fs[i as usize]);
×
NEW
44
                        let f2 = (0..task.samples)
×
NEW
45
                            .fold(0.0, |acc, i| acc + fs[i as usize] * fs[i as usize]);
×
NEW
46
                        let var = f2 - f * f / task.samples as Float;
×
NEW
47
                        let delta = if var <= 0.0 {
×
NEW
48
                            1e-5
×
49
                        } else {
NEW
50
                            let cost = (0..task.samples)
×
NEW
51
                                .fold(0, |acc, i| acc + ns[i as usize]);
×
NEW
52
                            (var / cost as Float).sqrt()
×
53
                        };
54

NEW
55
                        let samples = self.integrator.integrate(
×
NEW
56
                            &self.scene,
×
NEW
57
                            &self.camera,
×
NEW
58
                            &mut rng,
×
NEW
59
                            delta,
×
NEW
60
                            raster_xy
×
NEW
61
                        );
×
NEW
62

×
NEW
63
                        // main sample stored in last position, BDPT splats for RR?
×
NEW
64
                        let sample = &samples[samples.len() - 1];
×
NEW
65
                        num_rays += sample.cost;
×
NEW
66
                        ns[ptr] = sample.cost;
×
NEW
67
                        fs[ptr] = sample.color.luminance(&sample.lambda);
×
NEW
68
                        ptr += 1;
×
NEW
69
                        ptr %= task.samples as usize;
×
NEW
70

×
NEW
71
                        samples
×
NEW
72
                    })
×
NEW
73
                    .for_each(|mut sample: FilmSample| {
×
NEW
74
                        sample.color = self.tone_map.map(&sample);
×
NEW
75
                        tile.add_sample(&sample)
×
NEW
76
                    })
×
NEW
77
            });
×
NEW
78

×
NEW
79
        let num_camera_rays = (mx_x - mi_x) * (mx_y - mi_y) * task.samples;
×
NEW
80
        RenderTaskResult::new(tile, num_camera_rays, num_rays as u64)
×
NEW
81
    }
×
82
}
83

84
pub struct RenderTask {
85
    pub tile: FilmTile,
86
    pub batch: u64,
87
    pub samples: u64,
88
    pub total_samples: u64,
89
    pub seed: u64,
90
}
91

92
impl RenderTask {
NEW
93
    pub fn new(
×
NEW
94
        tile: FilmTile,
×
NEW
95
        batch: u64,
×
NEW
96
        samples: u64,
×
NEW
97
        total_samples: u64,
×
NEW
98
        seed: u64
×
NEW
99
    ) -> Self {
×
NEW
100
        Self { tile, batch, samples, total_samples, seed }
×
101
    }
×
102
}
103

104
pub struct RenderTaskResult {
105
    pub tile: FilmTile,
106
    pub num_camera_rays: u64,
107
    pub num_rays: u64,
108
}
109

110
impl RenderTaskResult {
NEW
111
    pub fn new(tile: FilmTile, num_camera_rays: u64, num_rays: u64) -> Self {
×
NEW
112
        Self { tile: tile, num_rays, num_camera_rays }
×
113
    }
×
114
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc