added hemispherical scattering, switched to ppm version 6
This commit is contained in:
38
src/color.rs
38
src/color.rs
@@ -1,21 +1,33 @@
|
|||||||
use std::io::{Write};
|
use std::io::Write;
|
||||||
|
|
||||||
use crate::{vec3::*, rtweekend::clamp};
|
use crate::{vec3::*, rtweekend::clamp};
|
||||||
|
|
||||||
pub fn write_color<T: Write>(buffer: &mut T, pixel_color: Color, samples_per_pixel: i32) {
|
fn get_scaled_color_components(c: Color, samples_per_pixel: i32) -> (u8, u8, u8) {
|
||||||
let mut r = pixel_color.x();
|
let r = c.x();
|
||||||
let mut g = pixel_color.y();
|
let g = c.y();
|
||||||
let mut b = pixel_color.z();
|
let b = c.z();
|
||||||
|
|
||||||
// Divide the color by the number of samples
|
// Divide the color by the number of samples
|
||||||
let scale = 1.0 / samples_per_pixel as f64;
|
let scale = 1.0 / samples_per_pixel as f64;
|
||||||
r *= scale;
|
let r = (scale * r).sqrt();
|
||||||
g *= scale;
|
let g = (scale * g).sqrt();
|
||||||
b *= scale;
|
let b = (scale * b).sqrt();
|
||||||
|
|
||||||
write!(buffer, "{} {} {} ",
|
(
|
||||||
(256.0 * clamp(r, 0.0, 0.999)) as i32,
|
(255.0 * clamp(r, 0.0, 1.0)) as u8,
|
||||||
(256.0 * clamp(g, 0.0, 0.999)) as i32,
|
(255.0 * clamp(g, 0.0, 1.0)) as u8,
|
||||||
(256.0 * clamp(b, 0.0, 0.999)) as i32,)
|
(255.0 * clamp(b, 0.0, 1.0)) as u8,
|
||||||
.expect("Error writing Pixel");
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_color<T: Write>(writer: &mut T, pixel_color: Color, samples_per_pixel: i32) {
|
||||||
|
let (r, g, b) = get_scaled_color_components(pixel_color, samples_per_pixel);
|
||||||
|
write!(writer, "{r} {g} {b} ").expect("Can write pixel data");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_color_bin<T: Write>(writer: &mut T, pixel_color: Color, samples_per_pixel: i32) {
|
||||||
|
let (r, g, b) = get_scaled_color_components(pixel_color, samples_per_pixel);
|
||||||
|
let binary_data = [r, g, b];
|
||||||
|
|
||||||
|
writer.write(&binary_data).expect("Can write binary pixel data!");
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use crate::material::Material;
|
||||||
use crate::ray::*;
|
use crate::ray::*;
|
||||||
use crate::vec3::*;
|
use crate::vec3::*;
|
||||||
|
|
||||||
@@ -5,13 +8,14 @@ use crate::vec3::*;
|
|||||||
pub struct HitRecord {
|
pub struct HitRecord {
|
||||||
pub p: Point3,
|
pub p: Point3,
|
||||||
pub normal: Vec3,
|
pub normal: Vec3,
|
||||||
|
pub mat_ptr: Rc<Material>,
|
||||||
pub t: f64,
|
pub t: f64,
|
||||||
pub front_face: bool,
|
pub front_face: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HitRecord {
|
impl HitRecord {
|
||||||
pub fn new_empty() -> Self {
|
pub fn new_empty() -> Self {
|
||||||
HitRecord { p: Point3::new(0.0, 0.0, 0.0), normal: Vec3::new(0.0, 0.0, 0.0), t: 0.0, front_face: false }
|
HitRecord { p: Point3::new(0.0, 0.0, 0.0), normal: Vec3::new(0.0, 0.0, 0.0), t: 0.0, front_face: false, mat_ptr: Rc::new(Material { }) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_face_normal(&mut self, r: &Ray, outward_normal: &Vec3) {
|
pub fn set_face_normal(&mut self, r: &Ray, outward_normal: &Vec3) {
|
||||||
|
|||||||
23
src/main.rs
23
src/main.rs
@@ -6,8 +6,9 @@ pub mod hittable;
|
|||||||
pub mod hittable_list;
|
pub mod hittable_list;
|
||||||
pub mod rtweekend;
|
pub mod rtweekend;
|
||||||
pub mod camera;
|
pub mod camera;
|
||||||
|
pub mod material;
|
||||||
|
|
||||||
use std::{io::{BufWriter, Write}, fs::File, time::Instant};
|
use std::{io::{BufWriter, Write, stdout}, fs::File, time::Instant};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
color::*,
|
color::*,
|
||||||
@@ -28,8 +29,8 @@ fn ray_color(r: &Ray, world: &mut dyn Hittable, depth: i32) -> Color {
|
|||||||
return Color::new(0.0, 0.0, 0.0);
|
return Color::new(0.0, 0.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if world.hit(r, 0.0, INFINITY, &mut rec) {
|
if world.hit(r, 0.001, INFINITY, &mut rec) {
|
||||||
let target = rec.p + rec.normal + random_in_unit_sphere();
|
let target = rec.p + random_in_hemisphere(&rec.normal);
|
||||||
return 0.5 * ray_color(&Ray::new(rec.p, target - rec.p), world, depth - 1)
|
return 0.5 * ray_color(&Ray::new(rec.p, target - rec.p), world, depth - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ fn ray_color(r: &Ray, world: &mut dyn Hittable, depth: i32) -> Color {
|
|||||||
fn main() {
|
fn main() {
|
||||||
// Image
|
// Image
|
||||||
let aspect_ratio: f64 = 1.0 / 1.0;
|
let aspect_ratio: f64 = 1.0 / 1.0;
|
||||||
let image_width: i32 = 512;
|
let image_width: i32 = 1024;
|
||||||
let image_height: i32 = (image_width as f64 / aspect_ratio as f64) as i32;
|
let image_height: i32 = (image_width as f64 / aspect_ratio as f64) as i32;
|
||||||
let samples_per_pixel: i32 = 100;
|
let samples_per_pixel: i32 = 100;
|
||||||
let max_depth: i32 = 4;
|
let max_depth: i32 = 4;
|
||||||
@@ -60,24 +61,26 @@ fn main() {
|
|||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
let mut file = BufWriter::new(File::create("img.ppm").expect("File creation failed"));
|
let mut file = BufWriter::new(File::create("img.ppm").expect("File creation failed"));
|
||||||
|
|
||||||
write!(file, "P3\n{image_width} {image_height}\n255").expect("Error while writing Magic Byte");
|
write!(file, "P6\n{image_width} {image_height}\n255\n").expect("Error while writing Magic Byte");
|
||||||
|
|
||||||
for j in (0..image_width).rev() {
|
for j in (0..image_width).rev() {
|
||||||
write!(file, "\n").expect("Error writing to File");
|
|
||||||
|
|
||||||
for i in 0..image_height {
|
for i in 0..image_height {
|
||||||
let mut pixel_color = Color::new(0.0, 0.0, 0.0);
|
let mut pixel_color = Color::new(0.0, 0.0, 0.0);
|
||||||
|
|
||||||
for _s in 0..samples_per_pixel {
|
for _ in 0..samples_per_pixel {
|
||||||
let u = (i as f64 + random_f64()) / (image_width - 1) as f64;
|
let u = (i as f64 + random_f64()) / (image_width - 1) as f64;
|
||||||
let v = (j as f64 + random_f64()) / (image_height - 1) as f64;
|
let v = (j as f64 + random_f64()) / (image_height - 1) as f64;
|
||||||
let r: Ray = cam.get_ray(u, v);
|
let r: Ray = cam.get_ray(u, v);
|
||||||
pixel_color += ray_color(&r, &mut world, max_depth)
|
pixel_color += ray_color(&r, &mut world, max_depth)
|
||||||
}
|
}
|
||||||
write_color(&mut file, pixel_color, samples_per_pixel);
|
write_color_bin(&mut file, pixel_color, samples_per_pixel);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("[ {:.2} % ]", (1.0 - ((j + 1) as f64 / image_width as f64)) * 100.0);
|
print!(
|
||||||
|
"[ {:.2} % ]\r",
|
||||||
|
(1.0 - ((j + 1) as f64 / image_width as f64)) * 100.0
|
||||||
|
);
|
||||||
|
stdout().flush().expect("Can flush stdout");
|
||||||
}
|
}
|
||||||
println!("Took {:.6}ms", now.elapsed().as_millis());
|
println!("Took {:.6}ms", now.elapsed().as_millis());
|
||||||
println!("Took {:.6}s", now.elapsed().as_secs_f64());
|
println!("Took {:.6}s", now.elapsed().as_secs_f64());
|
||||||
|
|||||||
13
src/material.rs
Normal file
13
src/material.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
use crate::hittable::HitRecord;
|
||||||
|
use crate::ray::Ray;
|
||||||
|
use crate::rtweekend::*;
|
||||||
|
use crate::hittable_list::*;
|
||||||
|
use crate::vec3::Color;
|
||||||
|
|
||||||
|
pub struct Material {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Scatter {
|
||||||
|
fn scatter(r_in: &Ray, rec: HitRecord, attenuation: &Color, scattered: &Ray) -> bool;
|
||||||
|
}
|
||||||
29
src/vec3.rs
29
src/vec3.rs
@@ -1,4 +1,4 @@
|
|||||||
use std::{ops::{Add, Sub, AddAssign, SubAssign, Mul, Div, MulAssign, DivAssign}};
|
use std::ops::{Add, Sub, AddAssign, SubAssign, Mul, Div, MulAssign, DivAssign, Neg};
|
||||||
|
|
||||||
use crate::rtweekend::{random_f64, random_range_f64};
|
use crate::rtweekend::{random_f64, random_range_f64};
|
||||||
|
|
||||||
@@ -89,6 +89,20 @@ impl Sub for Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Neg for Vec3 {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn neg(self) -> Self::Output {
|
||||||
|
Self {
|
||||||
|
elements: [
|
||||||
|
-self.x(),
|
||||||
|
-self.y(),
|
||||||
|
-self.z()
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul<f64> for Vec3 {
|
impl Mul<f64> for Vec3 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
@@ -186,3 +200,16 @@ pub fn random_in_unit_sphere() -> Vec3 {
|
|||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn random_unit_vector() -> Vec3 {
|
||||||
|
random_in_unit_sphere().unit_vector()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn random_in_hemisphere(normal: &Vec3) -> Vec3 {
|
||||||
|
let in_unit_sphere = random_in_unit_sphere();
|
||||||
|
if in_unit_sphere.dot(&normal) > 0.0 {
|
||||||
|
return in_unit_sphere;
|
||||||
|
} else {
|
||||||
|
return -in_unit_sphere;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user