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 let mut si_eval: SurfaceInteraction = si.clone();
17
18 let mut du = 0.5 * (Float::abs(si.dudx) + Float::abs(si.dudy));
20 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 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 {
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}