pbrt_r3/core/
material.rs

1use crate::core::base::*;
2use crate::core::interaction::SurfaceInteraction;
3use crate::core::memory::MemoryArena;
4use crate::core::texture::Texture;
5
6use std::sync::Arc;
7
8#[derive(Copy, Clone, Debug, PartialEq)]
9pub enum TransportMode {
10    Radiance,
11    Importance,
12}
13
14pub fn material_bump(d: &Arc<dyn Texture<Float>>, si: &mut SurfaceInteraction) {
15    // Compute offset positions and evaluate displacement texture
16    let mut si_eval: SurfaceInteraction = si.clone();
17
18    // Shift _siEval_ _du_ in the $u$ direction
19    let mut du = 0.5 * (Float::abs(si.dudx) + Float::abs(si.dudy));
20    // The most common reason for du to be zero is for ray that start from
21    // light sources, where no differentials are available. In this case,
22    // we try to choose a small enough du so that we still get a decently
23    // accurate bump value.
24    if du == 0.0 {
25        du = 0.0005;
26    }
27    si_eval.p = si.p + du * si.shading.dpdu;
28    si_eval.uv = si.uv + Vector2f::new(du, 0.0);
29    si_eval.n = (Vector3f::cross(&si.shading.dpdu, &si.shading.dpdv) + du * si.dndu).normalize();
30    let u_displace = d.as_ref().evaluate(&si_eval);
31
32    // Shift _siEval_ _dv_ in the $v$ direction
33    let mut dv = 0.5 * (Float::abs(si.dvdx) + Float::abs(si.dvdy));
34    if dv == 0.0 {
35        dv = 0.0005;
36    }
37    si_eval.p = si.p + dv * si.shading.dpdv;
38    si_eval.uv = si.uv + Vector2f::new(0.0, dv);
39    si_eval.n = (Vector3f::cross(&si.shading.dpdu, &si.shading.dpdv) + dv * si.dndv).normalize();
40    let v_displace = d.as_ref().evaluate(&si_eval);
41    let displace = d.as_ref().evaluate(si);
42
43    // Compute bump-mapped differential geometry
44    {
45        let dpdu = si.shading.dpdu
46            + (u_displace - displace) / du * si.shading.n
47            + displace * si.shading.dndu;
48        let dpdv = si.shading.dpdv
49            + (v_displace - displace) / dv * si.shading.n
50            + displace * si.shading.dndv;
51        let dndu = si.shading.dndu;
52        let dndv = si.shading.dndv;
53        si.set_shading_geometry(&dpdu, &dpdv, &dndu, &dndv, false);
54    }
55}
56
57pub trait Material {
58    fn compute_scattering_functions(
59        &self,
60        si: &mut SurfaceInteraction,
61        arena: &mut MemoryArena,
62        mode: TransportMode,
63        _allow_multiple_lobes: bool,
64    );
65
66    fn bump(&self, d: &Arc<dyn Texture<Float>>, si: &mut SurfaceInteraction) {
67        material_bump(d, si);
68    }
69}