(
scene: &Scene,
bvh: &Bvh,
environment: &Environment,
sun: Option<SunLight>,
camera: &Camera,
opts: &RenderOptions,
)
| 1928 | } |
| 1929 | |
| 1930 | fn render( |
| 1931 | scene: &Scene, |
| 1932 | bvh: &Bvh, |
| 1933 | environment: &Environment, |
| 1934 | sun: Option<SunLight>, |
| 1935 | camera: &Camera, |
| 1936 | opts: &RenderOptions, |
| 1937 | ) -> Vec<u8> { |
| 1938 | let w = opts.width as usize; |
| 1939 | let h = opts.height as usize; |
| 1940 | let mut pixels = vec![0u8; w * h * 3]; |
| 1941 | let image_size = UVec2::new(opts.width, opts.height); |
| 1942 | |
| 1943 | let scenario = Scenario { |
| 1944 | scene, |
| 1945 | bvh, |
| 1946 | environment, |
| 1947 | sun, |
| 1948 | }; |
| 1949 | |
| 1950 | pixels |
| 1951 | .par_chunks_mut(w * 3) |
| 1952 | .enumerate() |
| 1953 | .for_each(|(y, row)| { |
| 1954 | for x in 0..w { |
| 1955 | let pixel = UVec2::new(x as u32, y as u32); |
| 1956 | let mut accum = Vec3::ZERO; |
| 1957 | for s in 0..opts.spp { |
| 1958 | let mut rng = Rng::new(seed_for(pixel, s, opts.seed)); |
| 1959 | let jitter = rng.next_vec2(); |
| 1960 | let ray = camera.ray_for_pixel_jittered(pixel, image_size, jitter); |
| 1961 | accum += trace_path(&scenario, ray, opts.max_bounces, &mut rng); |
| 1962 | } |
| 1963 | let color_linear = accum / opts.spp as f32; |
| 1964 | let color_mapped = tonemap_aces(color_linear); |
| 1965 | let r = linear_to_srgb(color_mapped.x).clamp(0.0, 1.0); |
| 1966 | let g = linear_to_srgb(color_mapped.y).clamp(0.0, 1.0); |
| 1967 | let b = linear_to_srgb(color_mapped.z).clamp(0.0, 1.0); |
| 1968 | let base = x * 3; |
| 1969 | row[base] = (r * 255.0) as u8; |
| 1970 | row[base + 1] = (g * 255.0) as u8; |
| 1971 | row[base + 2] = (b * 255.0) as u8; |
| 1972 | } |
| 1973 | }); |
| 1974 | |
| 1975 | pixels |
| 1976 | } |
| 1977 | |
| 1978 | // ============================================================ |
| 1979 | // CLI |
no test coverage detected