Skip to content

Instantly share code, notes, and snippets.

@MaikKlein
Created January 30, 2019 15:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save MaikKlein/6e36b579d1a14cb52a49b1df6ddb52ab to your computer and use it in GitHub Desktop.
Save MaikKlein/6e36b579d1a14cb52a49b1df6ddb52ab to your computer and use it in GitHub Desktop.
use rlsl_math::prelude::*;
use rlsl_math::Array;
#[derive(Copy, Clone)]
pub struct Ray {
pub origin: Vec3<f32>,
pub dir: Unit<Vec3<f32>>,
}
impl Ray {
pub fn position(self, t: f32) -> Vec3<f32> {
self.origin + *self.dir * t
}
}
#[derive(Copy, Clone)]
pub struct Sphere {
pub origin: Vec3<f32>,
pub radius: f32,
pub color: Vec3<f32>,
}
impl Sphere {
pub fn intersect(self, ray: Ray) -> Option<RayHit> {
use rlsl_math::polynomial::quadratic;
let oc = ray.origin - self.origin;
//a is always one if the direction is a unit vector
let a = 1.0f32;
let b = 2.0 * ray.dir.dot(oc);
let c = Vec3::dot(oc, oc) - self.radius * self.radius;
let t = quadratic(a, b, c)?.min();
if t < 0.0 {
return None;
}
let position = ray.position(t);
let normal = position - self.origin;
let hit = RayHit {
position,
normal: normal.to_unit(),
color: self.color,
};
Some(hit)
}
}
pub struct RayHit {
pub position: Vec3<f32>,
pub normal: Unit<Vec3<f32>>,
pub color: Vec3<f32>,
}
fn color(
rng: &mut Rng,
mut ray: Ray,
spheres: &impl Array<Sphere>,
depth: usize,
) -> Option<Vec3<f32>> {
let mut color = intersect_spheres(ray, spheres).map(|hit| hit.color)?;
let mut i = 0usize;
while let Some(hit) = intersect_spheres(ray, spheres) {
//let dir =ray.dir.reflect(*hit.normal).to_unit();
let dir = hit.normal;
let random = Vec3::new(rng.random(), rng.random(), rng.random()).normalize();
let dir = (*dir + random).to_unit();
ray = Ray {
origin: hit.position,
dir,
};
color = color * hit.color;
i += 1;
if i > depth {
break;
}
}
Some(color)
}
fn intersect_spheres(ray: Ray, spheres: &impl Array<Sphere>) -> Option<RayHit> {
let mut hit = None;
let mut i = 0usize;
while i < spheres.length() {
if let Some(h) = spheres.get(i).intersect(ray) {
hit = Some(h);
}
i += 1;
}
hit
}
pub fn render(uv: Vec2<f32>, time: f32) -> Vec4<f32> {
let mut rng = Rng::from_seed(0.0);
let look = Vec3::new(0.0, 0.0, 1.0);
let coord = (uv * 2.0 - 1.0).extend(0.0) * Vec3::new(1.0, -1.0, 1.0);
let origin = Vec3::single(0.0f32);
let dir = look + coord;
let ray = Ray {
origin,
dir: dir.to_unit(),
};
let floor = Sphere {
origin: Vec3::new(0.0, -100.5, -1.0),
radius: 100.0,
color: Vec3::new(0.4, 0.4, 0.4),
};
let sphere2 = Sphere {
origin: Vec3::new(0.0, 0.0, 1.0),
radius: 0.5,
color: Vec3::new(1.0, 0.2, 0.1),
};
let spheres = [floor, sphere2];
let color = color(&mut rng, ray, &spheres, 5000).unwrap_or_else(move || {
let blue = Vec3::new(0.2, 0.5, 1.0);
let white = Vec3::single(1.0f32);
blue.lerp(white, uv.y)
});
color.extend(1.0)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment