some objects to trace

This commit is contained in:
numzero 2025-11-14 04:18:59 +03:00
parent 64401937b9
commit f05390291c
3 changed files with 110 additions and 13 deletions

View File

@ -2,7 +2,7 @@
use std::{convert::identity, error::Error, f32::consts::PI, sync::Arc};
use glam::{Mat4, vec3};
use glam::{Mat4, Vec3, vec3};
use winit::{
application::ApplicationHandler,
event::WindowEvent,
@ -13,7 +13,7 @@ use winit::{
use crate::{
camera::OrbitalCamera,
render::lines::{LookParams, Mesh, Pipeline, Vertex},
trace::Source,
trace::{Scene, Source, Sphere},
};
mod camera;
@ -155,20 +155,54 @@ impl MainWindow {
self.pipeline
.render(&mut pass, [&Mesh::new(&self.device, &contour)]);
const BASE_R: f32 = 2.;
const BASE_POS: Vec3 = vec3(0., 0., -BASE_R);
const BASE: Sphere = Sphere {
position: vec3(0., 0., -BASE_R),
radius: BASE_R,
};
fn sphere(pos: Vec3) -> Sphere {
Sphere {
position: pos,
radius: BASE_POS.distance(pos) - BASE_R,
}
}
let scene = Scene {
objects: vec![
BASE,
sphere(vec3(0., 0., 0.1)),
sphere(vec3(0.3, 0., 0.1)),
sphere(vec3(0.1, 0.3, 0.1)),
],
};
let mut prng = rand_pcg::Pcg64::new(42, 0);
let rays: Vec<Vertex> = (0..1000)
let rays: Vec<Vertex> = (0..10000)
.flat_map(|_| {
let ray = source.make_ray(&mut prng);
[
Vertex {
pos: ray.base,
color: vec3(0., 0., 0.),
},
Vertex {
pos: ray.base + 0.1 * ray.dir,
color: vec3(1., 1., 1.),
},
]
if let Some(ray) = scene.trace_ray(ray) {
[
Vertex {
pos: ray.base - 0.02 * ray.dir,
color: vec3(1., 1., 1.),
},
Vertex {
pos: ray.base,
color: vec3(0., 1., 0.),
},
]
} else {
[
Vertex {
pos: ray.base,
color: vec3(1., 1., 1.),
},
Vertex {
pos: ray.base + 0.1 * ray.dir,
color: vec3(1., 0., 0.),
},
]
}
})
.collect();
self.pipeline

View File

@ -1,6 +1,27 @@
use glam::Vec3;
#[derive(Debug, Clone, Copy)]
pub struct Ray {
pub base: Vec3,
pub dir: Vec3,
}
impl Ray {
pub fn new(base: Vec3, dir: Vec3) -> Self {
Ray { base, dir }
}
pub fn normalize(self) -> Self {
Self {
base: self.base,
dir: self.dir.normalize(),
}
}
pub fn advance(self, amount: f32) -> Self {
Self {
base: self.base + amount * self.dir,
dir: self.dir,
}
}
}

View File

@ -71,3 +71,45 @@ impl Source {
}
}
}
#[derive(Debug, Clone)]
pub struct Sphere {
pub position: Vec3,
pub radius: f32,
}
impl Sphere {
fn trace_ray(&self, ray: Ray) -> Option<f32> {
// let t: f32;
// let hit = ray.base + t * ray.dir;
// (hit - self.position).length() == self.radius;
let Ray { base, dir } = ray;
let rel = base - self.position;
// (rel + t⋅dir)² == r²
// rel² r² + 2⋅t⋅rel⋅dir + t²⋅dir² = 0
let a = dir.length_squared();
let b2 = rel.dot(dir);
let c = rel.length_squared() - self.radius.powi(2);
let d4 = b2.powi(2) - a * c;
if d4 < 0. {
return None;
}
Some((-b2 - d4.sqrt()) / a)
}
}
#[derive(Debug)]
pub struct Scene {
pub objects: Vec<Sphere>,
}
impl Scene {
pub fn trace_ray(&self, ray: Ray) -> Option<Ray> {
let dist = self
.objects
.iter()
.filter_map(|obj| obj.trace_ray(ray))
.min_by(f32::total_cmp);
Some(ray.advance(dist?))
}
}