A valid, if incorrect PPM raytracer
This commit is contained in:
commit
9a2d3405a1
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/target
|
7
Cargo.lock
generated
Normal file
7
Cargo.lock
generated
Normal 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
8
Cargo.toml
Normal 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]
|
89
src/main.rs
Normal file
89
src/main.rs
Normal 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
6
src/ray.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
use crate::utils::Position3D;
|
||||||
|
|
||||||
|
pub struct Ray {
|
||||||
|
pub origin: Position3D,
|
||||||
|
pub direction: Position3D,
|
||||||
|
}
|
133
src/utils.rs
Normal file
133
src/utils.rs
Normal 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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue