Compare commits
2 commits
main
...
selective-
Author | SHA1 | Date | |
---|---|---|---|
|
5f33c86566 | ||
|
69cedf3af2 |
5 changed files with 201 additions and 22 deletions
91
Cargo.lock
generated
91
Cargo.lock
generated
|
@ -61,6 +61,19 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31"
|
||||
dependencies = [
|
||||
"encode_unicode",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"terminal_size",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
|
@ -130,6 +143,12 @@ version = "1.7.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be"
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.7"
|
||||
|
@ -165,12 +184,30 @@ dependencies = [
|
|||
"png",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indicatif"
|
||||
version = "0.16.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d207dc617c7a380ab07ff572a6e52fa202a2a8f355860ac9c38e23f8196be1b"
|
||||
dependencies = [
|
||||
"console",
|
||||
"lazy_static",
|
||||
"number_prefix",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jpeg-decoder"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9478aa10f73e7528198d75109c8be5cd7d15fb530238040148d5f9a22d4c5b3b"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.126"
|
||||
|
@ -235,6 +272,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "number_prefix"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.13.0"
|
||||
|
@ -313,11 +356,27 @@ dependencies = [
|
|||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
|
||||
dependencies = [
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
|
||||
|
||||
[[package]]
|
||||
name = "renderer"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"image",
|
||||
"indicatif",
|
||||
"rand",
|
||||
"rayon",
|
||||
"tobj",
|
||||
|
@ -329,6 +388,16 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "terminal_size"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tobj"
|
||||
version = "3.2.3"
|
||||
|
@ -349,3 +418,25 @@ name = "wasi"
|
|||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
|
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||
|
||||
[dependencies]
|
||||
image = { version = "0.24.2", default-features = false, features = ["jpeg", "png", "pnm"] }
|
||||
indicatif = "0.16.2"
|
||||
rand = { version = "0.8.5", features = ["small_rng"] }
|
||||
rayon = "1.5.3"
|
||||
tobj = "3.2.3"
|
||||
|
|
10
src/color.rs
10
src/color.rs
|
@ -1,22 +1,22 @@
|
|||
use super::{utility, Color, Rgb, RgbImage};
|
||||
|
||||
pub fn put_color(img: &mut RgbImage, pixel_color: &Color, x: u32, y: u32, samples_per_pixel: u32) {
|
||||
let mut r = pixel_color.x();
|
||||
/*let mut r = pixel_color.x();
|
||||
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();
|
||||
b = (scale * b).sqrt();*/
|
||||
|
||||
img.put_pixel(
|
||||
x,
|
||||
y,
|
||||
Rgb([
|
||||
(256.0 * utility::clamp(r, 0.0, 0.999)) as u8,
|
||||
(256.0 * utility::clamp(g, 0.0, 0.999)) as u8,
|
||||
(256.0 * utility::clamp(b, 0.0, 0.999)) as u8,
|
||||
(256.0 * utility::clamp(pixel_color.x(), 0.0, 0.999)) as u8,
|
||||
(256.0 * utility::clamp(pixel_color.y(), 0.0, 0.999)) as u8,
|
||||
(256.0 * utility::clamp(pixel_color.z(), 0.0, 0.999)) as u8,
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
|
117
src/main.rs
117
src/main.rs
|
@ -13,11 +13,11 @@ use camera::Camera;
|
|||
use hittable::{HitRecord, Hittable, Sphere, Triangle};
|
||||
use hittable_list::HittableList;
|
||||
use image::{Rgb, RgbImage};
|
||||
use indicatif::ProgressBar;
|
||||
use material::{Dielectric, Lambertian, Material, Metal};
|
||||
use ray::Ray;
|
||||
use rayon::prelude::*;
|
||||
use std::env;
|
||||
use std::sync::atomic::{AtomicU32, Ordering};
|
||||
use std::sync::Arc;
|
||||
use tobj;
|
||||
use vec3::{Color, Point3, Vec3};
|
||||
|
@ -296,10 +296,11 @@ fn main() {
|
|||
|
||||
// Image
|
||||
let aspect_ratio = 16.0 / 9.0;
|
||||
let image_width = 1200;
|
||||
let image_width = 800;
|
||||
let image_height = (image_width as f64 / aspect_ratio) as u32;
|
||||
let samples_per_pixel = 50_u32;
|
||||
let samples_per_pixel = 50 as 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);
|
||||
|
@ -315,6 +316,7 @@ fn main() {
|
|||
}
|
||||
|
||||
// World
|
||||
eprintln!("[1/4] Loading meshes from file...");
|
||||
let world = from_obj("obj/suzanne.obj");
|
||||
// let world = random_world();
|
||||
|
||||
|
@ -335,48 +337,129 @@ fn main() {
|
|||
default_file = &args[1];
|
||||
}
|
||||
|
||||
eprintln!("[2/4] Gerenating image without antialiasing...");
|
||||
let bar = ProgressBar::new(image_height as u64);
|
||||
|
||||
let mut image = RgbImage::new(image_width, image_height);
|
||||
|
||||
let atomic_counter = Arc::new(AtomicU32::new(0));
|
||||
let color_lines: Vec<_> = (0..image_height)
|
||||
.into_par_iter() // threadded/parallel variant
|
||||
//.into_iter() // iterative variant
|
||||
.rev()
|
||||
.map(|j| {
|
||||
let v = atomic_counter.fetch_add(1, Ordering::Relaxed);
|
||||
eprint!("\rScanlines remaining: {:5}", image_height - v);
|
||||
bar.inc(1);
|
||||
|
||||
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;
|
||||
})
|
||||
.collect();
|
||||
eprint!("\rScanlines remaining: {:5}", 0);
|
||||
bar.finish_and_clear();
|
||||
|
||||
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);
|
||||
pixel_color += ray_color(&r, &world, max_depth);
|
||||
}
|
||||
|
||||
// Correct antialiasing gamma
|
||||
pixel_color = Color::new(
|
||||
((1.0 / samples_per_pixel as f64) * pixel_color.x()),
|
||||
((1.0 / samples_per_pixel as f64) * pixel_color.y()),
|
||||
((1.0 / samples_per_pixel as f64) * 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,
|
||||
);
|
||||
})
|
||||
});
|
||||
|
|
|
@ -62,6 +62,10 @@ impl Vec3 {
|
|||
return (self.e[0].abs() < s) && (self.e[1].abs() < s) && (self.e[2].abs() < s);
|
||||
}
|
||||
|
||||
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 random_f64() -> Vec3 {
|
||||
Vec3::new(
|
||||
utility::random_f64(),
|
||||
|
|
Loading…
Reference in a new issue