Skip to content

Commit

Permalink
Add PointLight and support runtime selection of light type
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Oom committed Oct 30, 2024
1 parent 1707b69 commit 46bb2b4
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 35 deletions.
6 changes: 4 additions & 2 deletions kdtree-tester-cli/src/ray_bouncer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@ use kdtree::{IntersectionAccelerator, KdNode};
use rand::{rngs::SmallRng, SeedableRng};
use std::ops::RangeInclusive;
use tracing::{
camera::Pinhole, light::SphericalLight, material::{Material, Surface},
camera::Pinhole,
light::Light,
material::{Material, Surface},
sampling::uniform_sample_unit_square,
};

pub struct RayBouncer {
pub geometries: Vec<Geometry>,
pub properties: Vec<GeometryProperties<usize>>,
pub materials: Vec<Material>,
pub lights: Vec<SphericalLight>,
pub lights: Vec<Light>,
pub kdtree: KdNode,
pub camera: Pinhole,
pub bounces: u32,
Expand Down
4 changes: 2 additions & 2 deletions kdtree-tester-cli/src/ray_tester.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{
io::{BufWriter, Write},
path::PathBuf,
};
use tracing::{camera::Pinhole, light::SphericalLight, material::Material};
use tracing::{camera::Pinhole, light::Light, material::Material};
use wavefront::read_obj_and_mtl_with_print_logging;

use crate::{ray_bouncer::RayBouncer, size::Size};
Expand Down Expand Up @@ -35,7 +35,7 @@ pub(crate) fn kdtree_ray_tester(
.iter()
.map(|m| Material::load_from_mtl(image_directory, m))
.collect(),
lights: mtl.lights.iter().map(SphericalLight::from).collect(),
lights: mtl.lights.iter().map(Light::from).collect(),
kdtree,
camera,
size: size.as_uvec2(),
Expand Down
13 changes: 6 additions & 7 deletions material-tester-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use std::{
use time::Duration;
use tracing::{
camera::{Camera, Pinhole},
light::SphericalLight,
light::{Light, PointLight},
material::Material,
pathtracer::Pathtracer,
worker::render_parallel_iterations,
Expand Down Expand Up @@ -172,18 +172,17 @@ fn main() {
let materials = (0..spheres.len())
.map(|i| material(i as f32 * 1.0 / (spheres.len() - 1) as f32))
.collect();
let lights = vec![SphericalLight::new(
Vec3::new(-10.0, -5.0, 1.0) * 100.0,
0.1,
Vec3::ONE * 100.0 * 100.0f32.powi(2),
)];
let lights = [PointLight {
center: Vec3::new(-10.0, -5.0, 1.0) * 100.0,
intensity: Vec3::ONE * 100.0 * 100.0f32.powi(2),
}];
let accelerator = NoAccelerator {};
let pathtracer = Pathtracer {
max_bounces: args.max_bounces,
geometries: spheres.map(Geometry::from).to_vec(),
properties,
materials,
lights,
lights: lights.map(Light::from).to_vec(),
environment: Vec3::new(0.8, 0.8, 0.8),
accelerator,
};
Expand Down
4 changes: 2 additions & 2 deletions pathtracer-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::{
};
use time::Duration;
use tracing::{
camera::Pinhole, light::SphericalLight, material::Material, pathtracer::Pathtracer,
camera::Pinhole, light::Light, material::Material, pathtracer::Pathtracer,
worker::render_parallel_iterations,
};
use wavefront::read_obj_and_mtl_with_print_logging;
Expand Down Expand Up @@ -147,7 +147,7 @@ fn main() {
.iter()
.map(|m| Material::load_from_mtl(image_directory, m))
.collect();
let lights = mtl.lights.iter().map(SphericalLight::from).collect();
let lights = mtl.lights.iter().map(Light::from).collect();
let pathtracer = Pathtracer {
max_bounces: args.max_bounces,
geometries,
Expand Down
4 changes: 2 additions & 2 deletions pathtracer-gui/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use glam::Vec3;
use kdtree::{build::build_kdtree, sah::SahCost};
use miniquad::conf::Conf;
use stage::Stage;
use tracing::{light::SphericalLight, material::Material, pathtracer::Pathtracer};
use tracing::{light::Light, material::Material, pathtracer::Pathtracer};
use wavefront::read_obj_and_mtl_with_print_logging;

mod stage;
Expand Down Expand Up @@ -47,7 +47,7 @@ fn main() {
.iter()
.map(|m| Material::load_from_mtl(image_directory, m))
.collect();
let lights = mtl.lights.iter().map(SphericalLight::from).collect();
let lights = mtl.lights.iter().map(Light::from).collect();
let pathtracer = Pathtracer {
max_bounces: 16,
geometries,
Expand Down
69 changes: 52 additions & 17 deletions tracing/src/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,36 +5,71 @@ use wavefront::mtl::{self};
use crate::sampling::uniform_sample_unit_sphere;

#[derive(Clone, Debug)]
pub struct SphericalLight {
pub struct PointLight {
pub center: Vec3,
pub radius: f32,
pub intensity: Vec3,
}

impl PointLight {
pub fn emitted(&self, point: &Vec3) -> Vec3 {
self.intensity / (self.center - point).length_squared()
}
}

#[derive(Clone, Debug)]
pub struct SphericalLight {
pub point: PointLight,
pub radius: f32,
}

impl SphericalLight {
pub fn new(center: Vec3, radius: f32, intensity: Vec3) -> SphericalLight {
SphericalLight {
center,
intensity,
radius,
}
pub fn sample(&self, rng: &mut SmallRng) -> Vec3 {
self.point.center + uniform_sample_unit_sphere(rng) * self.radius
}
}

pub fn emitted(&self, point: Vec3) -> Vec3 {
self.intensity / (self.center - point).length_squared()
#[derive(Clone, Debug)]
pub enum Light {
PointLight(PointLight),
SphericalLight(SphericalLight),
}

impl Light {
pub fn emitted(&self, point: &Vec3) -> Vec3 {
match self {
Light::PointLight(light) => light.emitted(point),
Light::SphericalLight(light) => light.point.emitted(point),
}
}

pub fn sample(&self, rng: &mut SmallRng) -> Vec3 {
self.center + uniform_sample_unit_sphere(rng) * self.radius
match self {
Light::PointLight(light) => light.center,
Light::SphericalLight(light) => light.sample(rng),
}
}
}

impl From<&mtl::Light> for SphericalLight {
impl From<&mtl::Light> for Light {
fn from(value: &mtl::Light) -> Self {
Self::new(
value.position.into(),
value.radius,
Vec3::from(value.color) * value.intensity,
)
Self::SphericalLight(SphericalLight {
point: PointLight {
center: value.position.into(),
intensity: Vec3::from(value.color) * value.intensity,
},
radius: value.radius,
})
}
}

impl From<PointLight> for Light {
fn from(value: PointLight) -> Self {
Self::PointLight(value)
}
}

impl From<SphericalLight> for Light {
fn from(value: SphericalLight) -> Self {
Self::SphericalLight(value)
}
}
6 changes: 3 additions & 3 deletions tracing/src/pathtracer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{
camera::Pinhole,
image_buffer::ImageBuffer,
light::SphericalLight,
light::Light,
material::{Material, Surface},
raylogger::{RayLoggerWithIteration, RayLoggerWithIterationAndPixel},
sampling::uniform_sample_unit_square,
Expand All @@ -19,7 +19,7 @@ pub struct Pathtracer<Accelerator> {
pub geometries: Vec<Geometry>,
pub properties: Vec<GeometryProperties<usize>>,
pub materials: Vec<Material>,
pub lights: Vec<SphericalLight>,
pub lights: Vec<Light>,
pub environment: Vec3,
pub accelerator: Accelerator,
}
Expand Down Expand Up @@ -83,7 +83,7 @@ where
if intersection.is_some() {
return Vec3::ZERO;
}
let radiance = light.emitted(point);
let radiance = light.emitted(&point);
let brdf = material.brdf(&Surface { wi, n, uv });
let wo = shadow_ray.direction.normalize();
brdf * radiance * wo.dot(n).abs()
Expand Down

0 comments on commit 46bb2b4

Please sign in to comment.