Add images
6
.gitignore
vendored
|
@ -1,6 +1,6 @@
|
|||
/target
|
||||
*.ppm
|
||||
*.jpg
|
||||
*.png
|
||||
/*.ppm
|
||||
/*.jpg
|
||||
/*.png
|
||||
flamegraph.svg
|
||||
perf.data*
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
# Renderer - Grafik-AG
|
||||
|
||||
Following [Raytracing In One Weekend](https://raytracing.github.io/books/RayTracingInOneWeekend.html).
|
||||
|
||||
Rendered images in `images/`.
|
||||
|
||||
![RaytracingInOneWeekend](images/RayTracingInOneWeekend2.png)
|
||||
|
||||
![Suzanne Rainbow](images/suzanne_rainbow.png)
|
||||
|
||||
***
|
||||
### Performance analysis with Flamegraph
|
||||
https://github.com/flamegraph-rs/flamegraph
|
||||
|
|
BIN
images/Baum_without_Antialiasing.png
Normal file
After Width: | Height: | Size: 738 KiB |
BIN
images/RayTracingInOneWeekend1.jpg
Normal file
After Width: | Height: | Size: 256 KiB |
BIN
images/RayTracingInOneWeekend2.png
Normal file
After Width: | Height: | Size: 4 MiB |
BIN
images/RayTracingInOneWeekend3.png
Normal file
After Width: | Height: | Size: 2.1 MiB |
BIN
images/RayTracingInOneWeekend4.png
Normal file
After Width: | Height: | Size: 578 KiB |
BIN
images/cat.png
Normal file
After Width: | Height: | Size: 674 KiB |
BIN
images/suzanne_rainbow.png
Normal file
After Width: | Height: | Size: 454 KiB |
BIN
images/suzanne_rainbow2.png
Normal file
After Width: | Height: | Size: 520 KiB |
|
@ -5,10 +5,10 @@ pub fn put_color(img: &mut RgbImage, pixel_color: &Color, x: u32, y: u32, sample
|
|||
let mut g = pixel_color.y();
|
||||
let mut b = pixel_color.z();
|
||||
|
||||
let scale = 1.0 / samples_per_pixel as f64;
|
||||
r = (scale * r).sqrt();
|
||||
g = (scale * g).sqrt();
|
||||
b = (scale * b).sqrt();
|
||||
//let scale = 1.0 / samples_per_pixel as f64;
|
||||
//r = r/samples_per_pixel as f64; //(scale * r).sqrt();
|
||||
//g = g/samples_per_pixel as f64; //(scale * g).sqrt();
|
||||
//b = b/samples_per_pixel as f64; //(scale * b).sqrt();
|
||||
|
||||
img.put_pixel(
|
||||
x,
|
||||
|
|
116
src/main.rs
|
@ -292,33 +292,33 @@ Current world view:
|
|||
/ z \ x
|
||||
|
||||
*/
|
||||
|
||||
fn main() {
|
||||
// File
|
||||
let mut default_file = "image.ppm";
|
||||
|
||||
// Image
|
||||
let aspect_ratio = 10.0/7.5; //16.0 / 9.0;
|
||||
let image_width = 1000;
|
||||
let aspect_ratio = 10.0 / 7.5; //16.0 / 9.0;
|
||||
let image_width = 400;
|
||||
let image_height = (image_width as f64 / aspect_ratio) as u32;
|
||||
let samples_per_pixel = 100_u32;
|
||||
let samples_per_pixel = 50_u32;
|
||||
let max_depth = 50;
|
||||
let antialiasing_threshold = 0.3; // at what diff between two colors will a pixel be antialiased
|
||||
|
||||
let vfov = 40.0;
|
||||
let lookfrom = Point3::new(2.0, 0.8, 3.0);
|
||||
let lookat = Point3::new(0.0, 0.0, 0.0);
|
||||
let vup = Vec3::new(0.0, 1.0, 0.0);
|
||||
let dist_to_focus = 3.0;
|
||||
let aperture = 0.1;
|
||||
let aperture = 0.0; // disable depth of field
|
||||
|
||||
// limit rayon multithreading thread count
|
||||
let thread_count = 6; // if 0, for each logical cpu core a thread wil be created
|
||||
let thread_count = 4; // if 0, for each logical cpu core a thread wil be created
|
||||
if thread_count > 0 {
|
||||
env::set_var("RAYON_NUM_THREADS", thread_count.to_string());
|
||||
}
|
||||
|
||||
// World
|
||||
eprintln!("[1/3] Loading meshes from file...");
|
||||
eprintln!("[1/4] Loading meshes from file...");
|
||||
let world = from_obj("obj/suzanne.obj");
|
||||
// let world = random_world();
|
||||
|
||||
|
@ -339,7 +339,7 @@ fn main() {
|
|||
default_file = &args[1];
|
||||
}
|
||||
|
||||
eprintln!("[2/3] Gerenating image...");
|
||||
eprintln!("[2/4] Generating image...");
|
||||
let bar = ProgressBar::new(image_height as u64);
|
||||
|
||||
let mut image = RgbImage::new(image_width, image_height);
|
||||
|
@ -353,20 +353,14 @@ fn main() {
|
|||
|
||||
let mut colors = Vec::new();
|
||||
for i in 0..image_width {
|
||||
let mut pixel_color = ray_color(
|
||||
let pixel_color = ray_color(
|
||||
&cam.get_ray(
|
||||
i as f64 / (image_width - 1) as f64,
|
||||
j as f64 / (image_height - 1) as f64,
|
||||
),
|
||||
&world,
|
||||
max_depth,
|
||||
); // first ray not antialiased to disable antialiasing on value 1
|
||||
for _ in 1..samples_per_pixel {
|
||||
let u = (i as f64 + utility::random_f64()) / (image_width - 1) as f64;
|
||||
let v = (j as f64 + utility::random_f64()) / (image_height - 1) as f64;
|
||||
let r = cam.get_ray(u, v);
|
||||
pixel_color += ray_color(&r, &world, max_depth);
|
||||
}
|
||||
);
|
||||
colors.push(pixel_color);
|
||||
}
|
||||
return colors;
|
||||
|
@ -374,15 +368,99 @@ fn main() {
|
|||
.collect();
|
||||
bar.finish_and_clear();
|
||||
|
||||
eprintln!("[3/3] Exporting image to disk...");
|
||||
eprintln!("[3/4] Antialiasing image...");
|
||||
let mut antialiasing: Vec<Vec<bool>> = Vec::new();
|
||||
let mut antialiasing_counter = 0;
|
||||
let mut antialiasing_col_counter = 0;
|
||||
let mut antialiases_per_line: Vec<u64> = Vec::new();
|
||||
(0..image_height).into_iter().for_each(|j| {
|
||||
antialiasing.push(Vec::new());
|
||||
(0..image_width).into_iter().for_each(|i| {
|
||||
if j != 0
|
||||
&& Color::diff(
|
||||
&color_lines[(j - 1) as usize][i as usize],
|
||||
&color_lines[j as usize][i as usize],
|
||||
) >= antialiasing_threshold
|
||||
{
|
||||
antialiasing[j as usize].push(true);
|
||||
antialiasing_col_counter += 1;
|
||||
} else if j != image_height - 1
|
||||
&& Color::diff(
|
||||
&color_lines[(j + 1) as usize][i as usize],
|
||||
&color_lines[j as usize][i as usize],
|
||||
) >= antialiasing_threshold
|
||||
{
|
||||
antialiasing[j as usize].push(true);
|
||||
antialiasing_col_counter += 1;
|
||||
} else if i != 0
|
||||
&& Color::diff(
|
||||
&color_lines[j as usize][(i - 1) as usize],
|
||||
&color_lines[j as usize][i as usize],
|
||||
) >= antialiasing_threshold
|
||||
{
|
||||
antialiasing[j as usize].push(true);
|
||||
antialiasing_col_counter += 1;
|
||||
} else if i != image_width - 1
|
||||
&& Color::diff(
|
||||
&color_lines[j as usize][(i + 1) as usize],
|
||||
&color_lines[j as usize][i as usize],
|
||||
) >= antialiasing_threshold
|
||||
{
|
||||
antialiasing[j as usize].push(true);
|
||||
antialiasing_col_counter += 1;
|
||||
}
|
||||
if antialiasing[j as usize].len() < (i + 1) as usize {
|
||||
antialiasing[j as usize].push(false);
|
||||
}
|
||||
});
|
||||
antialiases_per_line.push(antialiasing_col_counter);
|
||||
antialiasing_counter += antialiasing_col_counter;
|
||||
antialiasing_col_counter = 0;
|
||||
});
|
||||
|
||||
let bar = ProgressBar::new(antialiasing_counter as u64);
|
||||
let color_lines_antialiased: Vec<_> = (0..image_height)
|
||||
.into_par_iter() // threadded/parallel variant
|
||||
//.into_iter() // iterative variant
|
||||
.map(|j| {
|
||||
let mut colors = Vec::new();
|
||||
for i in 0..image_width {
|
||||
if samples_per_pixel > 0 && antialiasing[j as usize][i as usize] {
|
||||
let mut pixel_color = Color::null();
|
||||
for _ in 0..samples_per_pixel {
|
||||
let u = (i as f64 + utility::random_f64()) / (image_width - 1) as f64;
|
||||
let v = (j as f64 + utility::random_f64()) / (image_height - 1) as f64;
|
||||
let r = cam.get_ray(u, v);
|
||||
dbg!(ray_color(&r, &world, max_depth));
|
||||
pixel_color += ray_color(&r, &world, max_depth);
|
||||
}
|
||||
// Correct antialiasing gamma
|
||||
pixel_color = Color::new(
|
||||
pixel_color.x() / samples_per_pixel as f64,
|
||||
pixel_color.y() / samples_per_pixel as f64,
|
||||
pixel_color.z() / samples_per_pixel as f64,
|
||||
);
|
||||
println!("x: {}, y: {}, z: {}", pixel_color.x(), pixel_color.y(), pixel_color.z());
|
||||
colors.push(pixel_color);
|
||||
} else {
|
||||
colors.push(color_lines[j as usize][i as usize]);
|
||||
}
|
||||
}
|
||||
bar.inc(antialiases_per_line[j as usize]);
|
||||
return colors;
|
||||
})
|
||||
.collect();
|
||||
bar.finish_and_clear();
|
||||
|
||||
eprintln!("[4/4] Exporting image to disk...");
|
||||
(0..image_height).into_iter().rev().for_each(|j| {
|
||||
(0..image_width).into_iter().for_each(|i| {
|
||||
color::put_color(
|
||||
&mut image,
|
||||
&color_lines[(image_height - j - 1) as usize][i as usize],
|
||||
&color_lines_antialiased[(image_height - j - 1) as usize][i as usize],
|
||||
i,
|
||||
image_height - j - 1,
|
||||
samples_per_pixel,
|
||||
1,
|
||||
);
|
||||
})
|
||||
});
|
||||
|
|
|
@ -17,9 +17,7 @@ pub struct Dielectric {
|
|||
ir: f64,
|
||||
}
|
||||
|
||||
pub struct Rainbow {
|
||||
|
||||
}
|
||||
pub struct Rainbow {}
|
||||
|
||||
pub trait Material: Sync + Send {
|
||||
fn scatter(
|
||||
|
@ -183,12 +181,13 @@ impl Material for Rainbow {
|
|||
}
|
||||
|
||||
*scattered = Ray::new(rec.p, scatter_direction);
|
||||
let color = 0.5*Color::new(
|
||||
rec.normal.x()+1.0,
|
||||
rec.normal.y()+1.0,
|
||||
rec.normal.z()+1.0
|
||||
);
|
||||
let color = 0.5
|
||||
* Color::new(
|
||||
rec.normal.x() + 1.0,
|
||||
rec.normal.y() + 1.0,
|
||||
rec.normal.z() + 1.0,
|
||||
);
|
||||
*attenuation = color;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,10 @@ impl Vec3 {
|
|||
self.e[0] * self.e[0] + self.e[1] * self.e[1] + self.e[2] * self.e[2]
|
||||
}
|
||||
|
||||
pub fn diff(a: &Self, b: &Self) -> f64 {
|
||||
(a.x() - b.x()).abs() + (a.y() - b.y()).abs() + (a.z() - b.z()).abs()
|
||||
}
|
||||
|
||||
pub fn cross(a: Vec3, b: Vec3) -> Vec3 {
|
||||
Vec3::new(
|
||||
a.y() * b.z() - a.z() * b.y(),
|
||||
|
|