pbrt_r3/shapes/
alphamask.rs1use crate::core::prelude::*;
2
3use std::sync::Arc;
4
5#[derive(Clone)]
6pub enum AlphaMaskInfo {
7 Texture { texture: Arc<dyn Texture<Float>> },
8 Value { value: Float },
9}
10
11pub struct AlphaMaskShape {
12 shape: Arc<dyn Shape>,
13 test_intersection: bool,
14 test_intersection_p: bool,
15 alpha_mask_texture: Option<Arc<dyn Texture<Float>>>,
16 shadow_alpha_mask_texture: Option<Arc<dyn Texture<Float>>>,
17}
18
19impl AlphaMaskShape {
20 pub fn new(
21 shape: &Arc<dyn Shape>,
22 alpha_mask_info: &Option<AlphaMaskInfo>,
23 shadow_alpha_mask_info: &Option<AlphaMaskInfo>,
24 ) -> Self {
25 let mut test_intersection = true;
26 let mut test_intersection_p = true;
27 let mut alpha_mask_texture = None;
28 let mut shadow_alpha_mask_texture = None;
29 if let Some(info) = alpha_mask_info.as_ref() {
30 match info {
31 AlphaMaskInfo::Texture { texture } => {
32 alpha_mask_texture = Some(Arc::clone(texture));
33 }
34 AlphaMaskInfo::Value { value: alpha } => {
35 if *alpha <= 0.0 {
36 test_intersection = false;
37 test_intersection_p = false;
38 }
39 }
40 }
41 }
42 if let Some(info) = shadow_alpha_mask_info.as_ref() {
43 match info {
44 AlphaMaskInfo::Texture { texture } => {
45 shadow_alpha_mask_texture = Some(Arc::clone(texture));
46 }
47 AlphaMaskInfo::Value { value: alpha } => {
48 if *alpha <= 0.0 {
49 test_intersection_p = false;
50 }
51 }
52 }
53 }
54 AlphaMaskShape {
55 shape: Arc::clone(shape),
56 test_intersection,
57 test_intersection_p,
58 alpha_mask_texture,
59 shadow_alpha_mask_texture,
60 }
61 }
62}
63
64impl Shape for AlphaMaskShape {
65 fn object_bound(&self) -> Bounds3f {
66 let shape = self.shape.as_ref();
67 return shape.object_bound();
68 }
69 fn world_bound(&self) -> Bounds3f {
70 let shape = self.shape.as_ref();
71 return shape.world_bound();
72 }
73 fn intersect(&self, r: &Ray) -> Option<(Float, SurfaceInteraction)> {
74 if self.test_intersection {
75 let shape = self.shape.as_ref();
76 let t_max = r.t_max.get();
77 if let Some((t, si)) = shape.intersect(r) {
78 if let Some(mask) = self.alpha_mask_texture.as_ref() {
79 let a = mask.evaluate(&si);
80 if a <= 0.0 {
81 r.t_max.set(t_max);
82 return None;
83 }
84 }
85 return Some((t, si));
86 }
87 }
88 return None;
89 }
90
91 fn intersect_p(&self, r: &Ray) -> bool {
92 if self.test_intersection_p {
93 let shape = self.shape.as_ref();
94 let t_max = r.t_max.get();
95 if let Some((_, si)) = shape.intersect(r) {
96 r.t_max.set(t_max);
97 if let Some(mask) = self.alpha_mask_texture.as_ref() {
98 let a = mask.evaluate(&si);
99 if a <= 0.0 {
100 return false;
101 }
102 }
103 if let Some(mask) = self.shadow_alpha_mask_texture.as_ref() {
104 let a = mask.evaluate(&si);
105 if a <= 0.0 {
106 return false;
107 }
108 }
109 return true;
110 }
111 }
112 return false;
113 }
114
115 fn area(&self) -> Float {
116 let shape = self.shape.as_ref();
117 return shape.area();
118 }
119
120 fn pdf(&self, inter: &Interaction) -> Float {
121 let shape = self.shape.as_ref();
125 return shape.pdf(inter);
126 }
127
128 fn pdf_from(&self, inter: &Interaction, wi: &Vector3f) -> Float {
129 let shape = self.shape.as_ref();
130 return shape.pdf_from(inter, wi);
131 }
132
133 fn sample(&self, u: &Point2f) -> Option<(Interaction, Float)> {
134 let shape = self.shape.as_ref();
135 return shape.sample(u);
136 }
137
138 fn sample_from(&self, inter: &Interaction, u: &Point2f) -> Option<(Interaction, Float)> {
139 let shape = self.shape.as_ref();
140 return shape.sample_from(inter, u);
141 }
142
143 fn solid_angle(&self, p: &Point3f, n_samples: i32) -> Float {
144 let shape = self.shape.as_ref();
145 return shape.solid_angle(p, n_samples);
146 }
147}