1use std::sync::Arc;
3use crate::core::bssrdf::SeparableBssrdfAdapter;
5use crate::core::interaction::SurfaceInteraction;
6use crate::core::material::{Material, TransportMode};
7use crate::core::microfacet::{
8 BeckmannDistribution, MicrofacetDistribution, TrowbridgeReitzDistribution,
9};
10use crate::core::pbrt::{Float, Spectrum};
11use crate::core::reflection::{
12 Bxdf, FourierBSDF, Fresnel, FresnelBlend, FresnelConductor, FresnelDielectric, FresnelNoOp,
13 FresnelSpecular, LambertianReflection, LambertianTransmission, MicrofacetReflection,
14 MicrofacetTransmission, OrenNayar, SpecularReflection, SpecularTransmission,
15};
16use crate::core::texture::Texture;
17use crate::materials::disney::{
18 DisneyClearCoat, DisneyDiffuse, DisneyFakeSS, DisneyMicrofacetDistribution, DisneyRetro,
19 DisneySheen,
20};
21use crate::materials::hair::HairBSDF;
22
23pub struct MixMaterial {
29 pub m1: Arc<Material>,
30 pub m2: Arc<Material>,
31 pub scale: Arc<dyn Texture<Spectrum> + Sync + Send>, }
33
34impl MixMaterial {
35 pub fn new(
36 m1: Arc<Material>,
37 m2: Arc<Material>,
38 scale: Arc<dyn Texture<Spectrum> + Send + Sync>,
39 ) -> Self {
40 MixMaterial { m1, m2, scale }
41 }
42 pub fn compute_scattering_functions(
44 &self,
45 si: &mut SurfaceInteraction,
46 mode: TransportMode,
48 allow_multiple_lobes: bool,
49 _material: Option<Arc<Material>>,
50 _scale: Option<Spectrum>,
51 ) {
52 let s1: Spectrum = self
53 .scale
54 .evaluate(si)
55 .clamp(0.0 as Float, std::f32::INFINITY as Float);
56 let s2: Spectrum =
57 (Spectrum::new(1.0 as Float) - s1).clamp(0.0 as Float, std::f32::INFINITY as Float);
58 let mut si2: SurfaceInteraction = SurfaceInteraction::new(
59 &si.common.p,
60 &si.common.p_error,
61 si.uv,
62 &si.common.wo,
63 &si.dpdu,
64 &si.dpdv,
65 &si.dndu,
66 &si.dndv,
67 si.common.time,
68 si.shape,
69 );
70 self.m1
71 .compute_scattering_functions(si, mode, allow_multiple_lobes, None, Some(s1));
72 self.m2
73 .compute_scattering_functions(&mut si2, mode, allow_multiple_lobes, None, Some(s2));
74 if let Some(bsdf1) = &mut si.bsdf {
75 if let Some(bsdf2) = &si2.bsdf {
76 for bxdf2 in bsdf2.bxdfs.as_slice() {
78 match bxdf2 {
79 Bxdf::Empty(_bxdf) => break,
80 Bxdf::SpecRefl(bxdf) => {
81 let fresnel = match &bxdf.fresnel {
82 Fresnel::Conductor(fresnel) => {
83 Fresnel::Conductor(FresnelConductor {
84 eta_i: fresnel.eta_i,
85 eta_t: fresnel.eta_t,
86 k: fresnel.k,
87 })
88 }
89 Fresnel::Dielectric(fresnel) => {
90 Fresnel::Dielectric(FresnelDielectric {
91 eta_i: fresnel.eta_i,
92 eta_t: fresnel.eta_t,
93 })
94 }
95 _ => Fresnel::NoOp(FresnelNoOp {}),
96 };
97 bsdf1.add(Bxdf::SpecRefl(SpecularReflection::new(
98 bxdf.r,
99 fresnel,
100 bxdf.sc_opt,
101 )))
102 }
103 Bxdf::SpecTrans(bxdf) => {
104 bsdf1.add(Bxdf::SpecTrans(SpecularTransmission::new(
105 bxdf.t,
106 bxdf.eta_a,
107 bxdf.eta_b,
108 bxdf.mode,
109 bxdf.sc_opt,
110 )))
111 }
112 Bxdf::FresnelSpec(bxdf) => {
113 bsdf1.add(Bxdf::FresnelSpec(FresnelSpecular::new(
114 bxdf.r,
115 bxdf.t,
116 bxdf.eta_a,
117 bxdf.eta_b,
118 bxdf.mode,
119 bxdf.sc_opt,
120 )))
121 }
122 Bxdf::LambertianRefl(bxdf) => bsdf1.add(Bxdf::LambertianRefl(
123 LambertianReflection::new(bxdf.r, bxdf.sc_opt),
124 )),
125 Bxdf::LambertianTrans(bxdf) => bsdf1.add(Bxdf::LambertianTrans(
126 LambertianTransmission::new(bxdf.t, bxdf.sc_opt),
127 )),
128 Bxdf::OrenNayarRefl(bxdf) => bsdf1.add(Bxdf::OrenNayarRefl(OrenNayar {
129 r: bxdf.r,
130 a: bxdf.a,
131 b: bxdf.b,
132 sc_opt: bxdf.sc_opt,
133 })),
134 Bxdf::MicrofacetRefl(bxdf) => {
135 let distribution = match &bxdf.distribution {
136 MicrofacetDistribution::Beckmann(distribution) => {
137 MicrofacetDistribution::Beckmann(BeckmannDistribution {
138 alpha_x: distribution.alpha_x,
139 alpha_y: distribution.alpha_y,
140 sample_visible_area: distribution.sample_visible_area,
141 })
142 }
143 MicrofacetDistribution::TrowbridgeReitz(distribution) => {
144 MicrofacetDistribution::TrowbridgeReitz(
145 TrowbridgeReitzDistribution {
146 alpha_x: distribution.alpha_x,
147 alpha_y: distribution.alpha_y,
148 sample_visible_area: distribution.sample_visible_area,
149 },
150 )
151 }
152 MicrofacetDistribution::DisneyMicrofacet(distribution) => {
153 MicrofacetDistribution::DisneyMicrofacet(
154 DisneyMicrofacetDistribution::new(
155 distribution.inner.alpha_x,
156 distribution.inner.alpha_y,
157 ),
158 )
159 }
160 };
161 let fresnel = match &bxdf.fresnel {
162 Fresnel::Conductor(fresnel) => {
163 Fresnel::Conductor(FresnelConductor {
164 eta_i: fresnel.eta_i,
165 eta_t: fresnel.eta_t,
166 k: fresnel.k,
167 })
168 }
169 Fresnel::Dielectric(fresnel) => {
170 Fresnel::Dielectric(FresnelDielectric {
171 eta_i: fresnel.eta_i,
172 eta_t: fresnel.eta_t,
173 })
174 }
175 _ => Fresnel::NoOp(FresnelNoOp {}),
176 };
177 bsdf1.add(Bxdf::MicrofacetRefl(MicrofacetReflection::new(
178 bxdf.r,
179 distribution,
180 fresnel,
181 bxdf.sc_opt,
182 )))
183 }
184 Bxdf::MicrofacetTrans(bxdf) => {
185 let distribution = match &bxdf.distribution {
186 MicrofacetDistribution::Beckmann(distribution) => {
187 MicrofacetDistribution::Beckmann(BeckmannDistribution {
188 alpha_x: distribution.alpha_x,
189 alpha_y: distribution.alpha_y,
190 sample_visible_area: distribution.sample_visible_area,
191 })
192 }
193 MicrofacetDistribution::TrowbridgeReitz(distribution) => {
194 MicrofacetDistribution::TrowbridgeReitz(
195 TrowbridgeReitzDistribution {
196 alpha_x: distribution.alpha_x,
197 alpha_y: distribution.alpha_y,
198 sample_visible_area: distribution.sample_visible_area,
199 },
200 )
201 }
202 MicrofacetDistribution::DisneyMicrofacet(distribution) => {
203 MicrofacetDistribution::DisneyMicrofacet(
204 DisneyMicrofacetDistribution::new(
205 distribution.inner.alpha_x,
206 distribution.inner.alpha_y,
207 ),
208 )
209 }
210 };
211 bsdf1.add(Bxdf::MicrofacetTrans(MicrofacetTransmission::new(
212 bxdf.t,
213 distribution,
214 bxdf.eta_a,
215 bxdf.eta_b,
216 bxdf.mode,
217 bxdf.sc_opt,
218 )))
219 }
220 Bxdf::FresnelBlnd(bxdf) => {
221 let mut distrib: Option<MicrofacetDistribution> = None;
222 if let Some(distribution) = &bxdf.distribution {
223 distrib = match &distribution {
224 MicrofacetDistribution::Beckmann(distribution) => Some(
225 MicrofacetDistribution::Beckmann(BeckmannDistribution {
226 alpha_x: distribution.alpha_x,
227 alpha_y: distribution.alpha_y,
228 sample_visible_area: distribution.sample_visible_area,
229 }),
230 ),
231 MicrofacetDistribution::TrowbridgeReitz(distribution) => {
232 Some(MicrofacetDistribution::TrowbridgeReitz(
233 TrowbridgeReitzDistribution {
234 alpha_x: distribution.alpha_x,
235 alpha_y: distribution.alpha_y,
236 sample_visible_area: distribution
237 .sample_visible_area,
238 },
239 ))
240 }
241 MicrofacetDistribution::DisneyMicrofacet(distribution) => {
242 Some(MicrofacetDistribution::DisneyMicrofacet(
243 DisneyMicrofacetDistribution::new(
244 distribution.inner.alpha_x,
245 distribution.inner.alpha_y,
246 ),
247 ))
248 }
249 }
250 }
251 bsdf1.add(Bxdf::FresnelBlnd(FresnelBlend::new(
252 bxdf.rd,
253 bxdf.rs,
254 distrib,
255 bxdf.sc_opt,
256 )))
257 }
258 Bxdf::Fourier(bxdf) => bsdf1.add(Bxdf::Fourier(FourierBSDF::new(
259 bxdf.bsdf_table.clone(),
260 bxdf.mode,
261 bxdf.sc_opt,
262 ))),
263 Bxdf::Bssrdf(bxdf) => bsdf1.add(Bxdf::Bssrdf(SeparableBssrdfAdapter {
264 bssrdf: bxdf.bssrdf.clone(),
265 mode: bxdf.mode,
266 eta2: bxdf.eta2,
267 })),
268 Bxdf::DisDiff(bxdf) => {
269 bsdf1.add(Bxdf::DisDiff(DisneyDiffuse::new(bxdf.r, bxdf.sc_opt)))
270 }
271 Bxdf::DisSS(bxdf) => bsdf1.add(Bxdf::DisSS(DisneyFakeSS::new(
272 bxdf.r,
273 bxdf.roughness,
274 bxdf.sc_opt,
275 ))),
276 Bxdf::DisRetro(bxdf) => bsdf1.add(Bxdf::DisRetro(DisneyRetro::new(
277 bxdf.r,
278 bxdf.roughness,
279 bxdf.sc_opt,
280 ))),
281 Bxdf::DisSheen(bxdf) => {
282 bsdf1.add(Bxdf::DisSheen(DisneySheen::new(bxdf.r, bxdf.sc_opt)))
283 }
284 Bxdf::DisClearCoat(bxdf) => bsdf1.add(Bxdf::DisClearCoat(
285 DisneyClearCoat::new(bxdf.weight, bxdf.gloss, bxdf.sc_opt),
286 )),
287 Bxdf::Hair(bxdf) => bsdf1.add(Bxdf::Hair(HairBSDF {
288 h: bxdf.h,
289 gamma_o: bxdf.gamma_o,
290 eta: bxdf.eta,
291 sigma_a: bxdf.sigma_a,
292 beta_m: bxdf.beta_m,
293 beta_n: bxdf.beta_n,
294 v: bxdf.v,
295 s: bxdf.s,
296 sin_2k_alpha: bxdf.sin_2k_alpha,
297 cos_2k_alpha: bxdf.cos_2k_alpha,
298 sc_opt: bxdf.sc_opt,
299 })),
300 };
301 }
302 }
303 }
304 }
305}