Add solid and checker texture
This commit is contained in:
parent
93cbb67b39
commit
28105145c4
@ -1,14 +1,18 @@
|
||||
use crate::{Point3, Ray, Vec3};
|
||||
use crate::material::{Material};
|
||||
use crate::aabb::Aabb;
|
||||
use std::f64::consts::PI;
|
||||
|
||||
pub type HittableList = Vec<Box<dyn Hittable + Sync>>;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
//#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct HitRecord<'material> {
|
||||
pub point: Point3,
|
||||
pub normal: Vec3,
|
||||
pub t: f64,
|
||||
pub u: f64,
|
||||
pub v: f64,
|
||||
pub front_face: bool,
|
||||
pub material: &'material Material
|
||||
}
|
||||
@ -18,7 +22,7 @@ pub trait Hittable {
|
||||
fn bounding_box(&self, time0: f64, time1: f64) -> Option<Aabb>;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
//#[derive(Clone)]
|
||||
pub struct Sphere {
|
||||
pub center: Point3,
|
||||
pub radius: f64,
|
||||
@ -28,6 +32,19 @@ impl Sphere {
|
||||
pub fn new(center: Point3, radius: f64, material: Material) -> Sphere {
|
||||
Sphere { center, radius, material }
|
||||
}
|
||||
pub fn uv(point: &Point3) -> (f64, f64) {
|
||||
// p: a given point on the sphere of radius one, centered at the origin.
|
||||
// u: returned value [0,1] of angle around the Y axis from X=-1.
|
||||
// v: returned value [0,1] of angle from Y=-1 to Y=+1.
|
||||
// <1 0 0> yields <0.50 0.50> <-1 0 0> yields <0.00 0.50>
|
||||
// <0 1 0> yields <0.50 1.00> < 0 -1 0> yields <0.50 0.00>
|
||||
// <0 0 1> yields <0.25 0.50> < 0 0 -1> yields <0.75 0.50>
|
||||
|
||||
let theta = -(point.y()).acos();
|
||||
let phi = -(point.z()).atan2(point.x()) + PI;
|
||||
|
||||
(phi / (2.0 * PI), theta / PI)
|
||||
}
|
||||
}
|
||||
impl Default for Sphere {
|
||||
fn default() -> Self {
|
||||
@ -57,11 +74,14 @@ impl Hittable for Sphere {
|
||||
let normal = (point - self.center) / self.radius;
|
||||
let dot = ray.direction().dot(&normal);
|
||||
let front_face = dot < 0.0;
|
||||
let (u, v) = Sphere::uv(&normal);
|
||||
let normal = if front_face { normal } else { -normal };
|
||||
Some(HitRecord {
|
||||
point,
|
||||
normal,
|
||||
t: root,
|
||||
u,
|
||||
v,
|
||||
front_face,
|
||||
material: &self.material
|
||||
})
|
||||
@ -75,7 +95,7 @@ impl Hittable for Sphere {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
//#[derive(Clone)]
|
||||
pub struct MovableSphere {
|
||||
pub center0: Point3,
|
||||
pub center1: Point3,
|
||||
@ -130,13 +150,16 @@ impl Hittable for MovableSphere {
|
||||
let normal = (point - self.center(ray.time())) / self.radius;
|
||||
let dot = ray.direction().dot(&normal);
|
||||
let front_face = dot < 0.0;
|
||||
let (u, v) = Sphere::uv(&normal);
|
||||
let normal = if front_face { normal } else { -normal };
|
||||
Some(HitRecord {
|
||||
point,
|
||||
normal,
|
||||
t: root,
|
||||
u,
|
||||
v,
|
||||
front_face,
|
||||
material: &self.material
|
||||
material: &self.material,
|
||||
})
|
||||
}
|
||||
fn bounding_box(&self, time0: f64, time1: f64) -> Option<Aabb> {
|
||||
|
@ -13,6 +13,7 @@ use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||
use crate::material::{Dielectric, Lambertian, Material, Metal};
|
||||
use crate::aabb::Aabb;
|
||||
use crate::bvh::BVH;
|
||||
use crate::texture::CheckerTexture;
|
||||
|
||||
mod vec3;
|
||||
mod ray;
|
||||
@ -22,11 +23,16 @@ mod camera;
|
||||
mod output;
|
||||
mod aabb;
|
||||
mod bvh;
|
||||
mod texture;
|
||||
|
||||
fn random_scene() -> HittableList {
|
||||
let mut world:HittableList = Vec::new();
|
||||
|
||||
let material_ground = Material::Lambertian(Lambertian::new(Color::new(0.5, 0.5, 0.5)));
|
||||
//let material_ground = Material::Lambertian(Lambertian::new(Color::new(0.5, 0.5, 0.5)));
|
||||
let checker = CheckerTexture::colored(
|
||||
Color::new(0.2, 0.3, 0.1),
|
||||
Color::new(0.9, 0.9, 0.9));
|
||||
let material_ground = Material::Lambertian(Lambertian::textured(Box::new(checker)));
|
||||
let ground = Sphere {
|
||||
center: Point3::new(0.0, -1000.0, 0.0),
|
||||
radius: 1000.0,
|
||||
|
@ -1,12 +1,13 @@
|
||||
use rand::Rng;
|
||||
use crate::hittable::HitRecord;
|
||||
use crate::{Color, Ray, Vec3};
|
||||
use crate::texture::{SolidColor, Texture};
|
||||
|
||||
pub trait Scatterable {
|
||||
fn scatter(&self, ray: &Ray, hit_record: &HitRecord) -> Option<(Option<Ray>, Color)>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
//#[derive(Debug, Clone)]
|
||||
pub enum Material {
|
||||
Lambertian(Lambertian),
|
||||
Metal(Metal),
|
||||
@ -29,12 +30,16 @@ impl Scatterable for Material {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
//#[derive(Debug, Clone)]
|
||||
pub struct Lambertian {
|
||||
pub albedo: Color
|
||||
pub albedo: Box<dyn Texture>
|
||||
}
|
||||
impl Lambertian {
|
||||
pub fn new(albedo: Color) -> Self {
|
||||
let texture = SolidColor::from(albedo);
|
||||
Lambertian { albedo: Box::new(texture) }
|
||||
}
|
||||
pub fn textured(albedo: Box<dyn Texture>) -> Self {
|
||||
Lambertian { albedo }
|
||||
}
|
||||
}
|
||||
@ -46,7 +51,7 @@ impl Scatterable for Lambertian {
|
||||
direction = hit_record.normal;
|
||||
}
|
||||
let scattered = Ray::new(hit_record.point, direction, ray.time());
|
||||
Some((Some(scattered), self.albedo))
|
||||
Some((Some(scattered), self.albedo.value(hit_record.u, hit_record.v, &hit_record.point)))
|
||||
}
|
||||
}
|
||||
|
||||
|
56
src/texture.rs
Normal file
56
src/texture.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use crate::{Point3, Color};
|
||||
|
||||
pub trait Texture: Sync {
|
||||
fn value(&self, u: f64, v: f64, point: &Point3) -> Color;
|
||||
}
|
||||
|
||||
pub struct SolidColor {
|
||||
color_value: Color
|
||||
}
|
||||
|
||||
impl SolidColor {
|
||||
pub fn new(red: f64, green: f64, blue: f64) -> Self {
|
||||
SolidColor {
|
||||
color_value: Color::new(red, green, blue)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl From<Color> for SolidColor {
|
||||
fn from(color: Color) -> Self {
|
||||
SolidColor { color_value: color }
|
||||
}
|
||||
}
|
||||
|
||||
impl Texture for SolidColor {
|
||||
fn value(&self, _u: f64, _v: f64, _point: &Point3) -> Color {
|
||||
self.color_value
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CheckerTexture {
|
||||
pub odd: Box<dyn Texture>,
|
||||
pub even: Box<dyn Texture>
|
||||
}
|
||||
|
||||
impl CheckerTexture {
|
||||
pub fn colored(color1: Color, color2: Color) -> Self {
|
||||
CheckerTexture {
|
||||
even: Box::new(SolidColor::from(color1)),
|
||||
odd: Box::new(SolidColor::from(color2)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Texture for CheckerTexture {
|
||||
fn value(&self, u: f64, v: f64, point: &Point3) -> Color {
|
||||
let sines = (10.0 * point.x().sin()) *
|
||||
(10.0 * point.y().sin()) *
|
||||
(10.0 * point.z().sin());
|
||||
match sines {
|
||||
sines if sines < 0.0 => self.odd.value(u, v, point),
|
||||
_ => self.even.value(u, v, point),
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user