A valid, if incorrect PPM raytracer

master
able 2022-06-15 16:43:20 -05:00
commit 9a2d3405a1
7 changed files with 307450 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

7
Cargo.lock generated Normal file
View File

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "raytracer"
version = "0.1.0"

8
Cargo.toml Normal file
View File

@ -0,0 +1,8 @@
[package]
name = "raytracer"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

307206
img.ppm Normal file

File diff suppressed because it is too large Load Diff

89
src/main.rs Normal file
View File

@ -0,0 +1,89 @@
use crate::{
ray::Ray,
utils::{Color3D, Header, Position3D, PpmFormat, Vec3},
};
pub mod ray;
pub mod utils;
pub const WIDTH: u32 = 640;
pub const HEIGHT: u32 = 480;
pub const ASPECT_RATIO: f32 = WIDTH as f32 / HEIGHT as f32;
fn main() {
let viewport_height = 2.0;
let viewport_width = viewport_height * ASPECT_RATIO;
let focal_length = 1.0;
let origin = Position3D {
x: 0.0,
y: 0.0,
z: 0.0,
};
let horizontal = Position3D {
x: viewport_width,
y: 0.0,
z: 0.0,
};
let vertical = Position3D {
x: 0.0,
y: viewport_height,
z: 0.0,
};
let lower_left_corner = origin - horizontal / 2.0 - vertical / 2.0 - focal_length;
let header = Header {
format: PpmFormat::P3,
width: WIDTH,
height: HEIGHT,
max_color: 255,
};
println!("# {}", ASPECT_RATIO);
println!("{}", header);
// Code block to measure.
{
for y in 0..HEIGHT {
for x in 0..WIDTH {
let u = (x / WIDTH) as f32 - 1.0;
let v = (y / HEIGHT) as f32 - 1.0;
let bcr = lower_left_corner + u * horizontal + v * vertical - origin;
let ray = Ray {
origin,
direction: bcr,
};
let rgb_color = ray_color(&ray);
println!("{}", rgb_color);
}
}
}
}
fn unit_vector(v: &Vec3) -> Vec3 {
*v / v.length()
}
fn ray_color(ray: &ray::Ray) -> Color3D {
let unit_dir = unit_vector(&ray.direction);
let t = 0.5 * (unit_dir.y + 1.0);
let color1 = Color3D {
x: 1.0,
y: 1.0,
z: 1.0,
};
let color2 = Color3D {
x: 0.5,
y: 0.7,
z: 1.0,
};
return (1.0 - t) * color1 + t * color2;
}

6
src/ray.rs Normal file
View File

@ -0,0 +1,6 @@
use crate::utils::Position3D;
pub struct Ray {
pub origin: Position3D,
pub direction: Position3D,
}

133
src/utils.rs Normal file
View File

@ -0,0 +1,133 @@
use std::{
fmt::Display,
ops::{Add, Div, Mul, Sub},
};
pub type Position3D = Vec3;
pub type Color3D = Vec3;
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
pub struct Vec3 {
pub x: f32,
pub y: f32,
pub z: f32,
}
impl Vec3 {
pub fn new(x: f32, y: f32, z: f32) -> Self {
Self { x, y, z }
}
pub fn zero() -> Self {
Self::new(0.0, 0.0, 0.0)
}
pub fn length(&self) -> f32 {
self.length_squared().sqrt()
}
pub fn length_squared(&self) -> f32 {
self.x * self.x + self.y * self.y + self.z * self.z
}
}
impl Mul<f32> for Vec3 {
type Output = Vec3;
fn mul(self, rhs: f32) -> Vec3 {
Vec3 {
x: self.x * rhs,
y: self.y * rhs,
z: self.z * rhs,
}
}
}
impl Add<f32> for Vec3 {
type Output = Vec3;
fn add(self, rhs: f32) -> Vec3 {
Vec3 {
x: self.x + rhs,
y: self.y + rhs,
z: self.z + rhs,
}
}
}
impl Add<Vec3> for Vec3 {
type Output = Vec3;
fn add(self, rhs: Vec3) -> Vec3 {
Vec3 {
x: self.x + rhs.x,
y: self.y + rhs.y,
z: self.z + rhs.z,
}
}
}
impl Sub<f32> for Vec3 {
type Output = Vec3;
fn sub(self, rhs: f32) -> Vec3 {
Vec3 {
x: self.x - rhs,
y: self.y - rhs,
z: self.z - rhs,
}
}
}
impl Sub<Vec3> for Vec3 {
type Output = Vec3;
fn sub(self, rhs: Vec3) -> Vec3 {
Vec3 {
x: self.x - rhs.x,
y: self.y - rhs.y,
z: self.z - rhs.z,
}
}
}
impl Div<f32> for Vec3 {
type Output = Vec3;
fn div(self, rhs: f32) -> Vec3 {
Vec3 {
x: self.x / rhs,
y: self.y / rhs,
z: self.z / rhs,
}
}
}
impl Mul<Vec3> for f32 {
type Output = Vec3;
fn mul(self, rhs: Vec3) -> Vec3 {
Vec3 {
x: self * rhs.x,
y: self * rhs.y,
z: self * rhs.z,
}
}
}
impl Display for Vec3 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{} {} {}", self.x as u8, self.y as u8, self.z as u8)
}
}
#[derive(Debug)]
pub enum PpmFormat {
P3,
}
pub struct Header {
pub format: PpmFormat,
pub width: u32,
pub height: u32,
pub max_color: u8,
}
impl Display for Header {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"# HEADER BEGIN
{:?}\n{} {}\n{}
# HEADER END",
self.format, self.width, self.height, self.max_color
)
}
}