Skip to content

Commit b62a97d

Browse files
committed
Feat: add dielectric to path tracer
1 parent 70acd08 commit b62a97d

File tree

6 files changed

+76
-19
lines changed

6 files changed

+76
-19
lines changed

examples/cuda/cpu/path_tracer/src/main.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub mod viewer;
77

88
use common::Camera;
99
use path_tracer_gpu::{
10-
material::{DiffuseMaterial, MaterialKind, MetallicMaterial},
10+
material::{DielectricMaterial, DiffuseMaterial, MaterialKind, MetallicMaterial},
1111
scene::Scene,
1212
sphere::Sphere,
1313
Object,
@@ -37,13 +37,19 @@ fn main() -> Result<(), Box<dyn Error>> {
3737
}),
3838
MaterialKind::Metallic(MetallicMaterial {
3939
color: Vec3::new(1.0, 0.7, 0.7),
40-
roughness: 0.02,
40+
roughness: 0.2,
41+
}),
42+
MaterialKind::Dielectric(DielectricMaterial {
43+
ior: 1.0,
44+
color: Vec3::new(1.0, 1.0, 1.0),
4145
}),
4246
];
4347

4448
let objects = vec![
4549
Object::Sphere(Sphere::new(Vec3::new(0.0, 0.0, -1.0), 0.5, 0)),
4650
Object::Sphere(Sphere::new(Vec3::new(1.1, 0.2, -0.7), 0.2, 2)),
51+
Object::Sphere(Sphere::new(Vec3::new(-0.5, 0.4, -0.9), 0.3, 3)),
52+
Object::Sphere(Sphere::new(Vec3::new(0.7, 0.0, -0.2), 0.2, 1)),
4753
// Object::Sphere(Sphere::new(Vec3::new(0.0, -200.5, -1.0), 200.0, 1)),
4854
];
4955
let cpu_scene = Scene {

examples/cuda/gpu/path_tracer_gpu/src/material.rs

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
use crate::{
2-
hittable::HitRecord,
3-
math::{random_in_unit_sphere, reflect},
4-
Ray, Vec3,
5-
};
1+
use crate::{hittable::HitRecord, math::*, Ray, Vec3};
62
use cust_core::DeviceCopy;
73
use enum_dispatch::enum_dispatch;
8-
use gpu_rand::DefaultRand;
4+
use gpu_rand::{DefaultRand, GpuRand};
95

106
#[enum_dispatch]
117
pub trait Material {
@@ -18,6 +14,7 @@ pub trait Material {
1814
pub enum MaterialKind {
1915
Diffuse(DiffuseMaterial),
2016
Metallic(MetallicMaterial),
17+
Dielectric(DielectricMaterial),
2118
}
2219

2320
#[derive(Clone, Copy, PartialEq, DeviceCopy)]
@@ -63,3 +60,47 @@ impl Material for MetallicMaterial {
6360
}
6461
}
6562
}
63+
64+
#[derive(Clone, Copy, PartialEq, DeviceCopy)]
65+
pub struct DielectricMaterial {
66+
pub ior: f32,
67+
pub color: Vec3,
68+
}
69+
70+
impl Material for DielectricMaterial {
71+
fn scatter(&self, incoming: Ray, hit: HitRecord, rng: &mut DefaultRand) -> (Vec3, Option<Ray>) {
72+
let outward_norm;
73+
let ni_over_nt: f32;
74+
let cos: f32;
75+
76+
if incoming.dir.dot(hit.normal) > 0.0 {
77+
outward_norm = -hit.normal;
78+
ni_over_nt = self.ior;
79+
cos = self.ior * incoming.dir.dot(hit.normal) / incoming.dir.magnitude();
80+
} else {
81+
outward_norm = hit.normal;
82+
ni_over_nt = 1.0 / self.ior;
83+
cos = -incoming.dir.dot(hit.normal) / incoming.dir.magnitude();
84+
}
85+
86+
if let Some(refracted) = refract(incoming.dir, outward_norm, ni_over_nt) {
87+
if rng.normal_f32() > schlick(cos, self.ior) {
88+
return (
89+
self.color,
90+
Some(Ray {
91+
origin: hit.point,
92+
dir: refracted,
93+
}),
94+
);
95+
}
96+
}
97+
98+
(
99+
self.color,
100+
Some(Ray {
101+
origin: hit.point,
102+
dir: reflect(incoming.dir.normalized(), hit.normal),
103+
}),
104+
)
105+
}
106+
}

examples/cuda/gpu/path_tracer_gpu/src/math.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,19 @@ pub fn reflect(v: Vec3, n: Vec3) -> Vec3 {
3535
v - 2.0 * v.dot(n) * n
3636
}
3737

38-
pub fn refract(uv: Vec3, n: Vec3, etai_over_etat: f32) -> Vec3 {
39-
let cos_t = (-uv).dot(n).min(1.0);
40-
let r_out_perp = etai_over_etat * (uv + cos_t * n);
41-
let r_out_parallel = -((1.0 - r_out_perp.magnitude_squared()).abs()).sqrt() * n;
42-
r_out_perp + r_out_parallel
38+
pub fn refract(v: Vec3, n: Vec3, ni_over_nt: f32) -> Option<Vec3> {
39+
let uv = v.normalized();
40+
let dt = uv.dot(n);
41+
let discriminant = 1.0 - ni_over_nt * ni_over_nt * (1.0 - dt * dt);
42+
if discriminant > 0.0 {
43+
Some(ni_over_nt * (uv - n * dt) - discriminant.sqrt() * n)
44+
} else {
45+
None
46+
}
47+
}
48+
49+
pub fn schlick(cos: f32, ref_idx: f32) -> f32 {
50+
let r0 = (1.0 - ref_idx) / (1.0 + ref_idx);
51+
let r0sq = r0 * r0;
52+
r0sq + (1.0 - r0sq) * (1.0 - cos).powf(5.0)
4353
}

examples/cuda/gpu/path_tracer_gpu/src/optix.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use crate::{
22
hittable::{HitRecord, Hittable},
3+
material::Material,
34
render::{self, generate_ray},
45
scene::{Scene, MAX_BOUNCES},
56
sphere::Sphere,
67
Ray, Vec2, Vec3, Viewport,
78
};
89
use cuda_std::kernel;
910
use cust_core::DeviceCopy;
10-
use gpu_rand::DefaultRand;
11+
use gpu_rand::{DefaultRand, GpuRand};
1112
use optix_device::{
1213
closesthit, get_launch_index,
1314
glam::Vec3Swizzles,

examples/cuda/gpu/path_tracer_gpu/src/render.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
use crate::*;
22

3+
const BACKGROUND_BLUE_MULTIPLIER: f32 = 0.7;
4+
35
pub fn color(ray: Ray) -> Vec3 {
46
let unit = ray.dir.normalized();
5-
let t = 0.5 * (unit.y + 1.0);
7+
let t = BACKGROUND_BLUE_MULTIPLIER * (unit.y + 1.0);
68
(1.0 - t) * Vec3::one() + t * Vec3::new(0.5, 0.7, 1.0)
79
}
810

examples/cuda/gpu/path_tracer_gpu/src/scene.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,7 @@ impl Scene<'_> {
5858
return Vec3::zero();
5959
}
6060
} else {
61-
let unit = cur_ray.dir.normalized();
62-
let t = 0.5 * (unit.y + 1.0);
63-
let c = (1.0 - t) * Vec3::one() + t * Vec3::new(0.5, 0.7, 1.0);
64-
return attenuation * c;
61+
return attenuation * render::color(cur_ray);
6562
}
6663
}
6764
Vec3::zero()

0 commit comments

Comments
 (0)