ft: 4: ray class + simpl gradient
This commit is contained in:
51
src/main.rs
51
src/main.rs
@@ -1,31 +1,62 @@
|
|||||||
#![feature(core_float_math)]
|
#![feature(core_float_math)]
|
||||||
|
|
||||||
|
mod ray;
|
||||||
mod vec3;
|
mod vec3;
|
||||||
|
|
||||||
use crate::vec3::Vec3;
|
use std::cmp::max;
|
||||||
|
|
||||||
|
use crate::ray::Ray;
|
||||||
|
use crate::vec3::{Colour, Vec3};
|
||||||
use log::info;
|
use log::info;
|
||||||
use pretty_env_logger;
|
use pretty_env_logger;
|
||||||
|
|
||||||
|
fn ray_colour(r: &Ray) -> Colour {
|
||||||
|
let unit_dir = r.dir().get_unit();
|
||||||
|
let a = 0.5 * (unit_dir.y() + 1.);
|
||||||
|
|
||||||
|
(1.0 - a) * Colour::new(1., 1., 1.) + a * Colour::new(0.5, 0.7, 1.0)
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let v = Vec3::rgb(255., 0., 255.);
|
// use structs so rust-analyzer can provide lsp
|
||||||
|
let v = Vec3::new(255., 0., 255.);
|
||||||
|
let _ = Ray::new(v.clone(), v.clone());
|
||||||
|
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
|
|
||||||
let image_width = 256;
|
let aspect_ratio = 16. / 9.;
|
||||||
let image_height = 256;
|
let image_width = 400;
|
||||||
|
let image_height = max(1, (image_width as f32 / aspect_ratio) as u32);
|
||||||
|
|
||||||
|
//camera
|
||||||
|
let focal_length = 1.;
|
||||||
|
let viewport_height = 2.;
|
||||||
|
let viewport_width = viewport_height * (image_width as f32 / image_height as f32);
|
||||||
|
let camera_center = Vec3::nil();
|
||||||
|
|
||||||
|
//viewport
|
||||||
|
let viewport_u = Vec3::new(viewport_width as f32, 0., 0.);
|
||||||
|
let viewport_v = Vec3::new(0., -viewport_height as f32, 0.);
|
||||||
|
|
||||||
|
let pixel_delta_u = viewport_u / image_width as f32;
|
||||||
|
let pixel_delta_v = viewport_v / image_height as f32;
|
||||||
|
|
||||||
|
let viewport_upper_left =
|
||||||
|
camera_center - Vec3::new(0., 0., focal_length) - viewport_u / 2 - viewport_v / 2;
|
||||||
|
let pixel00_loc = viewport_upper_left + 0.5 * (pixel_delta_u + pixel_delta_v);
|
||||||
|
|
||||||
let mut imgbuf = image::ImageBuffer::new(image_width, image_height);
|
let mut imgbuf = image::ImageBuffer::new(image_width, image_height);
|
||||||
|
|
||||||
|
// render
|
||||||
for j in 0..image_height {
|
for j in 0..image_height {
|
||||||
info!("{}\tScanlines remaining.", (image_height - j));
|
info!("{}\tScanlines remaining.", (image_height - j));
|
||||||
for i in 0..image_width {
|
for i in 0..image_width {
|
||||||
let rgb = Vec3::rgb(
|
let pixel_center = pixel00_loc + (i * pixel_delta_u) + (j * pixel_delta_v);
|
||||||
i as f32 / (image_width - 1) as f32,
|
let ray_dir = pixel_center - camera_center;
|
||||||
j as f32 / (image_height - 1) as f32,
|
let r = Ray::new(camera_center, ray_dir);
|
||||||
0.0,
|
|
||||||
);
|
|
||||||
|
|
||||||
let pixel = imgbuf.get_pixel_mut(i, j);
|
let pixel = imgbuf.get_pixel_mut(i, j);
|
||||||
*pixel = rgb.output();
|
*pixel = ray_colour(&r).output();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
27
src/ray.rs
Normal file
27
src/ray.rs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
use crate::vec3::Vec3;
|
||||||
|
|
||||||
|
pub struct Ray {
|
||||||
|
origin: Vec3,
|
||||||
|
dir: Vec3,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ray {
|
||||||
|
pub fn at(self, t: f32) -> Vec3 {
|
||||||
|
self.origin + t * self.dir
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new(origin: Vec3, dir: Vec3) -> Ray {
|
||||||
|
Ray {
|
||||||
|
origin: origin,
|
||||||
|
dir: dir,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn origin(&self) -> &Vec3 {
|
||||||
|
&self.origin
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dir(&self) -> &Vec3 {
|
||||||
|
&self.dir
|
||||||
|
}
|
||||||
|
}
|
||||||
99
src/vec3.rs
99
src/vec3.rs
@@ -4,22 +4,46 @@ use std::{
|
|||||||
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
|
ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
pub struct Vec3 {
|
pub struct Vec3 {
|
||||||
r: f32,
|
r: f32,
|
||||||
g: f32,
|
g: f32,
|
||||||
b: f32,
|
b: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type Colour = Vec3;
|
||||||
|
|
||||||
impl Vec3 {
|
impl Vec3 {
|
||||||
pub fn rgb(r: f32, g: f32, b: f32) -> Vec3 {
|
pub fn new(r: f32, g: f32, b: f32) -> Vec3 {
|
||||||
return Self { r: r, g: g, b: b };
|
Self { r: r, g: g, b: b }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn nil() -> Vec3 {
|
||||||
|
Self {
|
||||||
|
r: 0.,
|
||||||
|
g: 0.,
|
||||||
|
b: 0.,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn x(&self) -> &f32 {
|
||||||
|
&self.r
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn y(&self) -> &f32 {
|
||||||
|
&self.g
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn z(&self) -> &f32 {
|
||||||
|
&self.b
|
||||||
|
}
|
||||||
|
|
||||||
pub fn length(&self) -> f32 {
|
pub fn length(&self) -> f32 {
|
||||||
return sqrt(self.length_squared());
|
sqrt(self.length_squared())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn length_squared(&self) -> f32 {
|
pub fn length_squared(&self) -> f32 {
|
||||||
return (self.r * self.r + self.g * self.g + self.b * self.b) as f32;
|
(self.r * self.r + self.g * self.g + self.b * self.b) as f32
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dot(self, other: Vec3) -> Vec3 {
|
pub fn dot(self, other: Vec3) -> Vec3 {
|
||||||
@@ -38,10 +62,14 @@ impl Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unit(mut self) {
|
pub fn make_unit(mut self) {
|
||||||
self /= self.length();
|
self /= self.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_unit(self) -> Vec3 {
|
||||||
|
self / self.length()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn output(self) -> image::Rgb<u8> {
|
pub fn output(self) -> image::Rgb<u8> {
|
||||||
let ir = (255.599 * self.r) as u8;
|
let ir = (255.599 * self.r) as u8;
|
||||||
let ig = (255.599 * self.g) as u8;
|
let ig = (255.599 * self.g) as u8;
|
||||||
@@ -49,6 +77,14 @@ impl Vec3 {
|
|||||||
|
|
||||||
image::Rgb([ir, ig, ib])
|
image::Rgb([ir, ig, ib])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clone(&self) -> Vec3 {
|
||||||
|
Vec3 {
|
||||||
|
r: self.r,
|
||||||
|
g: self.g,
|
||||||
|
b: self.b,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Neg for Vec3 {
|
impl Neg for Vec3 {
|
||||||
@@ -67,11 +103,11 @@ impl Add<Vec3> for Vec3 {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn add(self, _rhs: Self) -> Self {
|
fn add(self, _rhs: Self) -> Self {
|
||||||
return Self {
|
Self {
|
||||||
r: self.r + _rhs.r,
|
r: self.r + _rhs.r,
|
||||||
g: self.g + _rhs.g,
|
g: self.g + _rhs.g,
|
||||||
b: self.b + _rhs.b,
|
b: self.b + _rhs.b,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,11 +115,11 @@ impl Add<f32> for Vec3 {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn add(self, f: f32) -> Self {
|
fn add(self, f: f32) -> Self {
|
||||||
return Self {
|
Self {
|
||||||
r: self.r + f,
|
r: self.r + f,
|
||||||
g: self.g + f,
|
g: self.g + f,
|
||||||
b: self.b + f,
|
b: self.b + f,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,11 +147,11 @@ impl Sub<Vec3> for Vec3 {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn sub(self, rhs: Self) -> Self {
|
fn sub(self, rhs: Self) -> Self {
|
||||||
return Self {
|
Self {
|
||||||
r: self.r - rhs.r,
|
r: self.r - rhs.r,
|
||||||
g: self.g - rhs.g,
|
g: self.g - rhs.g,
|
||||||
b: self.b - rhs.b,
|
b: self.b - rhs.b,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,11 +159,11 @@ impl Sub<f32> for Vec3 {
|
|||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
fn sub(self, f: f32) -> Self {
|
fn sub(self, f: f32) -> Self {
|
||||||
return Self {
|
Self {
|
||||||
r: self.r - f,
|
r: self.r - f,
|
||||||
g: self.g - f,
|
g: self.g - f,
|
||||||
b: self.b - f,
|
b: self.b - f,
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -163,6 +199,19 @@ impl Mul<Vec3> for Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Mul<Vec3> for u32 {
|
||||||
|
type Output = Vec3;
|
||||||
|
|
||||||
|
fn mul(self, rhs: Vec3) -> Self::Output {
|
||||||
|
let f = self as f32;
|
||||||
|
Vec3 {
|
||||||
|
r: rhs.r * f,
|
||||||
|
g: rhs.g * f,
|
||||||
|
b: rhs.b * f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Mul<f32> for Vec3 {
|
impl Mul<f32> for Vec3 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
@@ -175,6 +224,18 @@ impl Mul<f32> for Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Mul<Vec3> for f32 {
|
||||||
|
type Output = Vec3;
|
||||||
|
|
||||||
|
fn mul(self, rhs: Vec3) -> Self::Output {
|
||||||
|
Vec3 {
|
||||||
|
r: rhs.r * self,
|
||||||
|
g: rhs.g * self,
|
||||||
|
b: rhs.b * self,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl MulAssign<Vec3> for Vec3 {
|
impl MulAssign<Vec3> for Vec3 {
|
||||||
fn mul_assign(&mut self, rhs: Self) {
|
fn mul_assign(&mut self, rhs: Self) {
|
||||||
*self = Self {
|
*self = Self {
|
||||||
@@ -206,6 +267,18 @@ impl Div<Vec3> for Vec3 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl Div<i32> for Vec3 {
|
||||||
|
type Output = Self;
|
||||||
|
|
||||||
|
fn div(self, i: i32) -> Self::Output {
|
||||||
|
let f: f32 = i as f32;
|
||||||
|
Self {
|
||||||
|
r: self.r / f,
|
||||||
|
g: self.g / f,
|
||||||
|
b: self.b / f,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Div<f32> for Vec3 {
|
impl Div<f32> for Vec3 {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|||||||
Reference in New Issue
Block a user