render percentage, new test scene but currently buggy
This commit is contained in:
+6
-2
@@ -4,8 +4,10 @@ pub const COLOR_CHANNELS: usize = 4;
|
||||
|
||||
pub const EPSILON: f64 = 1. / 1024.;
|
||||
pub const LIGHT_EPSILON: f64 = 1. / 512.;
|
||||
pub const MAX_DIST: f64 = 16.;
|
||||
//pub const MAX_DIST: f64 = 16.;
|
||||
pub const MAX_DIST: f64 = 32.;
|
||||
pub const MAX_STEPS: u32 = 1024;
|
||||
//pub const MAX_STEPS: u32 = u32::MAX;
|
||||
|
||||
pub const DIST_FIX_CORRECTION: f64 = 0.5;
|
||||
pub const DIST_CORRECTION: f64 = 3.;
|
||||
@@ -35,8 +37,10 @@ pub const RAYS_PER_PIXEL: usize = 500;
|
||||
//pub const MAX_BOUNCES: u32 = 8;
|
||||
pub const MAX_BOUNCES: u32 = 10;
|
||||
|
||||
//pub const THREAD_COUNT: usize = 1;
|
||||
pub const THREAD_COUNT: usize = 12;
|
||||
pub const SLICES_PER_THREAD: usize = 4;
|
||||
pub const SLICES_PER_THREAD: usize = 16;
|
||||
pub const REPORT_STATUS: bool = true;
|
||||
|
||||
pub const UP: Vec3 = Y;
|
||||
pub const RIGHT: Vec3 = X;
|
||||
|
||||
+18
@@ -9,6 +9,7 @@ use crate::consts::*;
|
||||
use crate::structs::*;
|
||||
use crate::material::*;
|
||||
use image::{ColorType, ImageFormat};
|
||||
use crate::light::Light;
|
||||
|
||||
fn default_cam() -> Cam {
|
||||
Cam::new_pointing(Y*3. - X*5., O, 0.5)
|
||||
@@ -64,6 +65,23 @@ fn default_scene2() -> Scene {
|
||||
Scene::new(Union::new(Union::new(sphere, Union::new(wall, backwall)), Union::new(light, mirror)))
|
||||
}
|
||||
|
||||
fn default_scene3() -> Scene {
|
||||
//TODO fix this scene
|
||||
let s1 = WithMaterial::new(Sphere::new_xyz(4., 0., 0., 1.), WHITE);
|
||||
let s2 = WithMaterial::new(Sphere::new_xyz(3., 1., 1., 0.5), GREEN);
|
||||
let navion = WithMaterial::new(Plane::new_xyz(0., 1., -1., 3.), BLUE);
|
||||
let backwall = WithMaterial::new(Plane::new_xyz(-1., -1., -0.5, 8.), RED);
|
||||
let boiboite = Cuboid::new_xyz(4., 1.1, -1.1, 0.5, 0.275, 0.275);
|
||||
let decal = AffineTransform::new_translate(boiboite, Vec3::new(-0.25, 0., 0.5));
|
||||
let nope = Exclusion::new(s1, Sphere::new_xyz(3.75, 0.75, 0.75, 1.));
|
||||
let walls = Union::new(navion, backwall);
|
||||
let spheres = Union::new(AffineTransform::new_linear(nope, scale(0.75)), s2);
|
||||
let scene = Union::new(spheres, Union::new(walls, decal));
|
||||
let light = WithMaterial::new(Plane::new_xyz(0., -1., 0., 8.), BRIGHT_AF_LIGHTSOURCE);
|
||||
let scene = WithLight::new_one(scene, Light::new(Y*3.-X*5., ColorVec::new([2., 3., 4., 0.])));
|
||||
Scene::new(Union::new(scene, light))
|
||||
}
|
||||
|
||||
fn main() {
|
||||
// get scene and camera
|
||||
let scene = default_scene2();
|
||||
|
||||
@@ -71,6 +71,12 @@ pub const STRONG_LIGHTSOURCE: Material = Material::new_from_diagonal(
|
||||
Stop
|
||||
);
|
||||
|
||||
pub const BRIGHT_AF_LIGHTSOURCE: Material = Material::new_from_diagonal(
|
||||
ColorVec::new([25., 25., 25., 0.]),
|
||||
COLOR_ZERO,
|
||||
Stop
|
||||
);
|
||||
|
||||
pub const UV_LIGHTSOURCE: Material = Material::new_from_diagonal(
|
||||
ColorVec::new_one(3),
|
||||
ColorVec::new([0.25, 0.25, 0.25, 1.]),
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
use crate::object::Obj;
|
||||
use crate::light::Light;
|
||||
use crate::structs::Vec3;
|
||||
use std::vec;
|
||||
use crate::material::Material;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct Exclusion<A: Obj, B: Obj> {
|
||||
a: A,
|
||||
b: B
|
||||
}
|
||||
|
||||
impl<A: Obj, B: Obj> Exclusion<A, B> {
|
||||
pub fn new(a: A, b: B) -> Exclusion<A, B> {
|
||||
Exclusion { a, b }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Obj, B: Obj> Obj for Exclusion<A, B> {
|
||||
fn distance_to(&self, point: Vec3) -> f64 {
|
||||
f64::max(self.a.distance_to(point), -self.b.distance_to(point))
|
||||
}
|
||||
fn material_at(&self, point: Vec3) -> Material {
|
||||
self.a.material_at(point)
|
||||
}
|
||||
fn get_lights(&self) -> vec::Vec<Light> {
|
||||
self.a.get_lights()
|
||||
}
|
||||
fn node_count(&self) -> u32 {
|
||||
self.a.node_count() + self.b.node_count() + 1
|
||||
}
|
||||
}
|
||||
@@ -20,13 +20,6 @@ impl<A: Obj, B: Obj> Obj for Intersection<A, B> {
|
||||
fn distance_to(&self, point: Vec3) -> f64 {
|
||||
f64::max(self.a.distance_to(point), self.b.distance_to(point))
|
||||
}
|
||||
fn normal_at(&self, point: Vec3) -> Vec3 {
|
||||
if self.a.distance_to(point) > self.b.distance_to(point) {
|
||||
self.a.normal_at(point)
|
||||
} else {
|
||||
self.b.normal_at(point)
|
||||
}
|
||||
}
|
||||
fn material_at(&self, point: Vec3) -> Material {
|
||||
if self.a.distance_to(point) > self.b.distance_to(point) {
|
||||
self.a.material_at(point)
|
||||
|
||||
+5
-1
@@ -9,6 +9,7 @@ mod sphere;
|
||||
mod plane;
|
||||
mod union;
|
||||
mod intersection;
|
||||
mod exclusion;
|
||||
mod cuboid;
|
||||
mod cylinder;
|
||||
mod torus;
|
||||
@@ -36,7 +37,9 @@ pub trait Obj: Send + Sync {
|
||||
fn get_lights(&self) -> Vec<Light> {
|
||||
Vec::new()
|
||||
}
|
||||
fn node_count(&self) -> u32 { 1 }
|
||||
fn node_count(&self) -> u32 {
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Obj> Obj for &T {
|
||||
@@ -61,6 +64,7 @@ pub use sphere::Sphere;
|
||||
pub use plane::Plane;
|
||||
pub use union::Union;
|
||||
pub use intersection::Intersection;
|
||||
pub use exclusion::Exclusion;
|
||||
pub use cuboid::Cuboid;
|
||||
pub use cylinder::Cylinder;
|
||||
pub use torus::Torus;
|
||||
|
||||
@@ -63,7 +63,7 @@ impl<T: Obj + Clone> Obj for AffineTransform<T> {
|
||||
self.obj.distance_to(self.apply_rev(point))
|
||||
}
|
||||
fn normal_at(&self, point: Vec3) -> Vec3 {
|
||||
self.apply_fwd(self.obj.normal_at(self.apply_rev(point)))
|
||||
self.apply_fwd(self.obj.normal_at(self.apply_rev(point))).unit()
|
||||
}
|
||||
fn material_at(&self, point: Vec3) -> Material {
|
||||
self.obj.material_at(self.apply_rev(point))
|
||||
|
||||
+47
-8
@@ -7,6 +7,7 @@ use std::f64::consts::PI;
|
||||
use rand::prelude::*;
|
||||
use crossbeam_channel::unbounded;
|
||||
use std::ops::{Mul, Add, Sub};
|
||||
use std::io::Write;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct Cam {
|
||||
@@ -99,10 +100,10 @@ fn shoot_ray_at<T: Obj>(scene: &T, pos: Vec3, dest: Vec3) -> bool {
|
||||
let point = ray.point(dist);
|
||||
let sd = scene.distance_to(point);
|
||||
let dd = dest.distance_to(point);
|
||||
if sd < 0. {
|
||||
if sd <= 0. {
|
||||
return false;
|
||||
}
|
||||
if dd < sd {
|
||||
if dd <= sd {
|
||||
return true;
|
||||
}
|
||||
dist += if sd < EPSILON { EPSILON } else { sd };
|
||||
@@ -121,6 +122,12 @@ impl Cam {
|
||||
}
|
||||
|
||||
pub fn render_singlethreaded<T: Obj>(&self, scene: &T) -> Image {
|
||||
let mut stderr = std::io::stderr();
|
||||
if REPORT_STATUS {
|
||||
stderr.write_all(format!("Rendering... 0/{} rows (0.00%)", IMG_HEIGHT).as_bytes()).unwrap();
|
||||
stderr.flush();
|
||||
}
|
||||
|
||||
let lights = scene.get_lights();
|
||||
let mut pixels = [0; IMG_BYTE_SIZE];
|
||||
for y in 0..IMG_HEIGHT {
|
||||
@@ -128,7 +135,18 @@ impl Cam {
|
||||
let field_pos = (x + y*IMG_WIDTH) * 3;
|
||||
self.render_single(scene, &lights, x, y, &mut pixels[field_pos..(field_pos+3)]);
|
||||
}
|
||||
|
||||
if REPORT_STATUS {
|
||||
stderr.write_all(format!("\x1b[1K\x1b[GRendering... {}/{} rows ({:.2}%)", y+1, IMG_HEIGHT, (y+1) as f64/IMG_HEIGHT as f64).as_bytes());
|
||||
stderr.flush();
|
||||
}
|
||||
}
|
||||
|
||||
if REPORT_STATUS {
|
||||
stderr.write_all(format!("\x1b[1K\x1b[GRendering... Done\n").as_bytes());
|
||||
stderr.flush();
|
||||
}
|
||||
|
||||
pixels
|
||||
}
|
||||
|
||||
@@ -176,6 +194,7 @@ impl Cam {
|
||||
drop(data_tx);
|
||||
|
||||
// send the slice data
|
||||
let mut total_slices = 0u32;
|
||||
let mut y = 0;
|
||||
while y < IMG_HEIGHT {
|
||||
let mut x = 0;
|
||||
@@ -184,12 +203,23 @@ impl Cam {
|
||||
let h = usize::min(slice_height, IMG_HEIGHT - y);
|
||||
slice_tx.send(Slice { x, y, w, h }).unwrap();
|
||||
x += slice_width;
|
||||
|
||||
if REPORT_STATUS {
|
||||
total_slices += 1;
|
||||
}
|
||||
}
|
||||
y += slice_height;
|
||||
}
|
||||
drop(slice_tx);
|
||||
|
||||
// merge stuff as we get it
|
||||
let mut stderr = std::io::stderr();
|
||||
if REPORT_STATUS {
|
||||
stderr.write_all(format!("Rendering... 0/{} slices (0.00%), 0.00% pixels", total_slices).as_bytes()).unwrap();
|
||||
stderr.flush();
|
||||
}
|
||||
let mut rendered_slices = 0u32;
|
||||
let mut rendered_pixels = 0u64;
|
||||
for (slice, data) in data_rx {
|
||||
let data = data.as_slice();
|
||||
for sy in 0..slice.h {
|
||||
@@ -204,6 +234,19 @@ impl Cam {
|
||||
pixels[pi + 2] = data[si + 2];
|
||||
}
|
||||
}
|
||||
|
||||
if REPORT_STATUS {
|
||||
rendered_slices += 1;
|
||||
rendered_pixels += (slice.w*slice.h) as u64;
|
||||
let pct_slices = rendered_slices as f64 / total_slices as f64 * 100.;
|
||||
let pct_pixels = rendered_pixels as f64 / (IMG_WIDTH * IMG_HEIGHT) as f64 * 100.;
|
||||
stderr.write_all(format!("\x1b[1K\x1b[GRendering... {}/{} slices ({:.02}%), {:.02}% pixels", rendered_slices, total_slices, pct_slices, pct_pixels).as_bytes()).unwrap();
|
||||
stderr.flush();
|
||||
}
|
||||
}
|
||||
if REPORT_STATUS {
|
||||
stderr.write_all(format!("\x1b[1K\x1b[GRendering... Done\n").as_bytes());
|
||||
stderr.flush();
|
||||
}
|
||||
}).unwrap();
|
||||
|
||||
@@ -269,7 +312,7 @@ impl Cam {
|
||||
match hit {
|
||||
Some(hit) => {
|
||||
i += 1;
|
||||
pos = hit.pos - dir * EPSILON;
|
||||
pos = hit.pos + (hit.normal - dir) * EPSILON;
|
||||
match hit.material.surface() {
|
||||
SurfaceType::Stop => break,
|
||||
SurfaceType::Diffuse => {
|
||||
@@ -281,11 +324,7 @@ impl Cam {
|
||||
let x = r1.cos()*r2.sqrt();
|
||||
let y = r1.sin()*r2.sqrt();
|
||||
let z = (1.-r2).sqrt();
|
||||
if w.x().abs() < 0.5 {
|
||||
dir = (u*x + v*y + w*z).unit();
|
||||
} else {
|
||||
dir = (u*x + v*y + w*z).unit();
|
||||
}
|
||||
dir = (u*x + v*y + w*z).unit();
|
||||
},
|
||||
SurfaceType::Reflective => {
|
||||
dir = dir - hit.normal * (hit.normal * dir) * 2.;
|
||||
|
||||
Reference in New Issue
Block a user