Implement diffuse lighting, and gamma correction.
This commit is contained in:
parent
4584eeb08f
commit
73ca5c8454
@ -10,9 +10,26 @@ use rtiow::ray::Ray;
|
|||||||
use rtiow::sphere::Sphere;
|
use rtiow::sphere::Sphere;
|
||||||
use rtiow::vec3::Vec3;
|
use rtiow::vec3::Vec3;
|
||||||
|
|
||||||
|
fn random_in_unit_sphere() -> Vec3 {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let v = Vec3::new(1., 1., 1.);
|
||||||
|
loop {
|
||||||
|
let p = 2. * Vec3::new(
|
||||||
|
rng.gen_range::<f32>(0., 1.),
|
||||||
|
rng.gen_range::<f32>(0., 1.),
|
||||||
|
rng.gen_range::<f32>(0., 1.),
|
||||||
|
) - v;
|
||||||
|
if p.squared_length() < 1. {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn color(r: Ray, world: &Hit) -> Vec3 {
|
fn color(r: Ray, world: &Hit) -> Vec3 {
|
||||||
if let Some(rec) = world.hit(r, 0., std::f32::MAX) {
|
if let Some(rec) = world.hit(r, 0.001, std::f32::MAX) {
|
||||||
return (rec.normal + 1.) * 0.5;
|
let target = rec.p + rec.normal + random_in_unit_sphere();
|
||||||
|
// 50% grey material
|
||||||
|
return 0.5 * color(Ray::new(rec.p, target - rec.p), world);
|
||||||
}
|
}
|
||||||
|
|
||||||
// No hit, choose color from background.
|
// No hit, choose color from background.
|
||||||
@ -43,6 +60,9 @@ fn main() -> Result<(), std::io::Error> {
|
|||||||
col = col + color(r, &world);
|
col = col + color(r, &world);
|
||||||
}
|
}
|
||||||
col = col / ns as f32;
|
col = col / ns as f32;
|
||||||
|
// Gamma correct, use gamma 2 correction, which is 1/gamma where gamma=2 which is 1/2
|
||||||
|
// or sqrt.
|
||||||
|
col = Vec3::new(col[0].sqrt(), col[1].sqrt(), col[2].sqrt());
|
||||||
let ir = (255.99 * col[0]) as u32;
|
let ir = (255.99 * col[0]) as u32;
|
||||||
let ig = (255.99 * col[1]) as u32;
|
let ig = (255.99 * col[1]) as u32;
|
||||||
let ib = (255.99 * col[2]) as u32;
|
let ib = (255.99 * col[2]) as u32;
|
||||||
|
|||||||
73
rtiow/src/bin/tracer_diffuse.rs
Normal file
73
rtiow/src/bin/tracer_diffuse.rs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
extern crate rand;
|
||||||
|
extern crate rtiow;
|
||||||
|
|
||||||
|
use rand::Rng;
|
||||||
|
|
||||||
|
use rtiow::camera::Camera;
|
||||||
|
use rtiow::hitable::Hit;
|
||||||
|
use rtiow::hitable_list::HitableList;
|
||||||
|
use rtiow::ray::Ray;
|
||||||
|
use rtiow::sphere::Sphere;
|
||||||
|
use rtiow::vec3::Vec3;
|
||||||
|
|
||||||
|
fn random_in_unit_sphere() -> Vec3 {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let v = Vec3::new(1., 1., 1.);
|
||||||
|
loop {
|
||||||
|
let p = 2. * Vec3::new(
|
||||||
|
rng.gen_range::<f32>(0., 1.),
|
||||||
|
rng.gen_range::<f32>(0., 1.),
|
||||||
|
rng.gen_range::<f32>(0., 1.),
|
||||||
|
) - v;
|
||||||
|
if p.squared_length() < 1. {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn color(r: Ray, world: &Hit) -> Vec3 {
|
||||||
|
if let Some(rec) = world.hit(r, 0.001, std::f32::MAX) {
|
||||||
|
let target = rec.p + rec.normal + random_in_unit_sphere();
|
||||||
|
// 50% grey material
|
||||||
|
return 0.5 * color(Ray::new(rec.p, target - rec.p), world);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No hit, choose color from background.
|
||||||
|
let unit_direction = r.direction().unit_vector();
|
||||||
|
let t = 0.5 * (unit_direction.y + 1.);
|
||||||
|
Vec3::new(1., 1., 1.) * (1. - t) + Vec3::new(0.5, 0.7, 1.) * t
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), std::io::Error> {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let nx = 200;
|
||||||
|
let ny = 100;
|
||||||
|
let ns = 100;
|
||||||
|
println!("P3\n{} {}\n255", nx, ny);
|
||||||
|
let objects = vec![
|
||||||
|
Sphere::new(Vec3::new(0., 0., -1.), 0.5),
|
||||||
|
Sphere::new(Vec3::new(0., -100.5, -1.), 100.),
|
||||||
|
];
|
||||||
|
let cam = Camera::new2x1();
|
||||||
|
let world = HitableList::new(objects.iter().map(|o| o).collect());
|
||||||
|
for j in (0..ny).rev() {
|
||||||
|
for i in 0..nx {
|
||||||
|
let mut col: Vec3 = Default::default();
|
||||||
|
for _ in 0..ns {
|
||||||
|
let u = (rng.gen_range::<f32>(0., 1.) + i as f32) / nx as f32;
|
||||||
|
let v = (rng.gen_range::<f32>(0., 1.) + j as f32) / ny as f32;
|
||||||
|
let r = cam.get_ray(u, v);
|
||||||
|
col = col + color(r, &world);
|
||||||
|
}
|
||||||
|
col = col / ns as f32;
|
||||||
|
// Gamma correct, use gamma 2 correction, which is 1/gamma where gamma=2 which is 1/2
|
||||||
|
// or sqrt.
|
||||||
|
col = Vec3::new(col[0].sqrt(), col[1].sqrt(), col[2].sqrt());
|
||||||
|
let ir = (255.99 * col[0]) as u32;
|
||||||
|
let ig = (255.99 * col[1]) as u32;
|
||||||
|
let ib = (255.99 * col[2]) as u32;
|
||||||
|
println!("{} {} {}", ir, ig, ib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
@ -131,6 +131,18 @@ impl Mul for Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Mul<Vec3> for f32 {
|
||||||
|
type Output = Vec3;
|
||||||
|
|
||||||
|
fn mul(self, v: Vec3) -> Vec3 {
|
||||||
|
Vec3 {
|
||||||
|
x: v.x * self,
|
||||||
|
y: v.y * self,
|
||||||
|
z: v.z * self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul<f32> for Vec3 {
|
impl Mul<f32> for Vec3 {
|
||||||
type Output = Vec3;
|
type Output = Vec3;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user