Skip to content

Commit

Permalink
feat: add a ConeLight material
Browse files Browse the repository at this point in the history
  • Loading branch information
Walther committed Oct 3, 2023
1 parent bbe64b1 commit 9eeb85c
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 55 deletions.
4 changes: 4 additions & 0 deletions clovers/src/materials.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use core::fmt::Debug;

use crate::{color::Color, hitable::HitRecord, pdf::PDF, ray::Ray, Float, Vec3};
pub mod cone_light;
pub mod dielectric;
pub mod diffuse_light;
pub mod dispersive;
Expand All @@ -12,6 +13,7 @@ pub mod isotropic;
pub mod lambertian;
pub mod metal;

pub use cone_light::*;
pub use dielectric::*;
pub use diffuse_light::*;
pub use dispersive::*;
Expand Down Expand Up @@ -93,6 +95,8 @@ pub enum Material {
Dispersive(Dispersive),
/// Lambertian material
Lambertian(Lambertian),
/// ConeLight material
ConeLight(ConeLight),
/// DiffuseLight material
DiffuseLight(DiffuseLight),
/// Metal material
Expand Down
91 changes: 91 additions & 0 deletions clovers/src/materials/cone_light.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//! A cone light material.

use super::{MaterialTrait, ScatterRecord};
use crate::{
color::Color,
hitable::HitRecord,
ray::Ray,
textures::{SolidColor, Texture, TextureTrait},
Float, Vec3,
};
use rand::prelude::SmallRng;

/// A cone light material. The material emits light if the incoming ray is within a certain amount of degrees from the surface normal.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde-derive", derive(serde::Serialize, serde::Deserialize))]
pub struct ConeLight {
spread: Float,
emit: Texture,
}

impl Default for ConeLight {
/// Creates a new [`ConeLight`] with white light at intensity `100.0` and a spread of 10 degrees.
fn default() -> Self {
ConeLight {
spread: 10.0,
emit: Texture::SolidColor(SolidColor::new(Color::new(100.0, 100.0, 100.0))),
}
}
}

impl MaterialTrait for ConeLight {
/// Scatter method for the [`ConeLight`] material. Always returns `None`, as diffuse light does not scatter.
#[allow(clippy::unused_self)]
#[must_use]
fn scatter(
&self,
_ray: &Ray,
_hit_record: &HitRecord,
_rng: &mut SmallRng,
) -> Option<ScatterRecord> {
None
}

/// Scattering probability density function for the [`ConeLight`] material. Always returns 0, as diffuse light does not scatter.
#[allow(clippy::unused_self)] // TODO:
#[must_use]
fn scattering_pdf(
&self,
_hit_record: &HitRecord,
_scattered: &Ray,
_rng: &mut SmallRng,
) -> Option<Float> {
None
}

/// Emission function for [`ConeLight`]. If the given [`HitRecord`] has been hit on the `front_face`, emit a color based on the texture and surface coordinates. Otherwise, emit pure black.
#[must_use]
fn emit(&self, ray: &Ray, hit_record: &HitRecord, u: Float, v: Float, position: Vec3) -> Color {
// If we don't hit the front face, return black
if !hit_record.front_face {
return Color::new(0.0, 0.0, 0.0);
}

// We have hit the front. Calculate the angle of incidence
let spread_radians = self.spread.to_radians();
let angle = (-ray.direction.dot(&hit_record.normal)
/ (ray.direction.magnitude() * hit_record.normal.magnitude()))
.acos();

let emit = self.emit.color(u, v, position);
if angle <= spread_radians {
emit
} else {
// Make sure that the front face of the lamp is tinted, even outside the main lighting angle
let scaling_factor = Vec3::from(emit).max();
if scaling_factor > 1.0 {
emit / scaling_factor
} else {
emit
}
}
}
}

impl ConeLight {
/// Creates a new [`ConeLight`] material with the given [Texture].
#[must_use]
pub fn new(spread: Float, emit: Texture) -> Self {
ConeLight { spread, emit }
}
}
87 changes: 32 additions & 55 deletions scenes/dispersive.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
"time_0": 0,
"time_1": 1,
"camera": {
"look_from": [-150, 278, -800],
"look_at": [450, 275, 555],
"look_from": [-600, 310, -400],
"look_at": [0, 310, 0],
"up": [0, 1, 0],
"vertical_fov": 40,
"vertical_fov": 35,
"aperture": 0,
"focus_distance": 10
},
Expand All @@ -21,55 +21,23 @@
},
{
"kind": "Quad",
"q": [0, 0, 0],
"u": [555, 0, 0],
"v": [0, 0, 555],
"material": "grey wall",
"comment": "floor"
},
{
"kind": "Quad",
"q": [0, 555, 0],
"u": [555, 0, 0],
"v": [0, 0, 555],
"material": "grey wall",
"comment": "ceiling"
"q": [113, 555, 127],
"u": [330, 0, 0],
"v": [0, 0, 305],
"material": "big lamp",
"comment": "big ceiling light"
},
{
"kind": "Quad",
"q": [277, 554, 120],
"u": [2, 0, 0],
"v": [0, 0, 200],
"material": "strong lamp",
"q": [277, 554, 140],
"u": [10, 0, 0],
"v": [0, 0, 278],
"material": "narrow lamp",
"comment": "narrow ceiling light"
},
{
"kind": "Quad",
"q": [279, 554, 120],
"u": [0, -40, 0],
"v": [0, 0, 200],
"material": "grey wall",
"comment": "light guide, left"
},
{
"kind": "Quad",
"q": [277, 554, 120],
"u": [0, -40, 0],
"v": [0, 0, 200],
"material": "grey wall",
"comment": "light guide, right"
},
{
"kind": "Quad",
"q": [0, 0, 555],
"u": [555, 0, 0],
"v": [0, 555, 0],
"material": "grey wall",
"comment": "back wall"
},
{
"kind": "STL",
"center": [300, 350, 250],
"center": [300, 350, 278],
"scale": 20,
"rotation": [0, 0, -30],
"path": "stl/prism.stl",
Expand All @@ -80,15 +48,23 @@
"priority_objects": [
{
"kind": "Quad",
"q": [277, 554, 120],
"u": [2, 0, 0],
"v": [0, 0, 200],
"material": "strong lamp",
"q": [113, 555, 127],
"u": [330, 0, 0],
"v": [0, 0, 305],
"material": "big lamp",
"comment": "big ceiling light"
},
{
"kind": "Quad",
"q": [277, 554, 140],
"u": [10, 0, 0],
"v": [0, 0, 278],
"material": "narrow lamp",
"comment": "narrow ceiling light"
},
{
"kind": "STL",
"center": [300, 350, 250],
"center": [300, 350, 278],
"scale": 20,
"rotation": [0, 0, -30],
"path": "stl/prism.stl",
Expand Down Expand Up @@ -146,19 +122,20 @@
"cauchy_b": 0.5
},
{
"name": "weak lamp",
"name": "big lamp",
"kind": "DiffuseLight",
"emit": {
"kind": "SolidColor",
"color": [10, 10, 10]
"color": [2, 2, 2]
}
},
{
"name": "strong lamp",
"kind": "DiffuseLight",
"name": "narrow lamp",
"kind": "ConeLight",
"spread": 2.0,
"emit": {
"kind": "SolidColor",
"color": [1000, 1000, 1000]
"color": [500, 500, 500]
}
},
{
Expand Down

0 comments on commit 9eeb85c

Please sign in to comment.