Blender  V2.93
bsdf_microfacet_multi.h
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2016 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
18 
19 /* Most of the code is based on the supplemental implementations from
20  * https://eheitzresearch.wordpress.com/240-2/. */
21 
22 /* === GGX Microfacet distribution functions === */
23 
24 /* Isotropic GGX microfacet distribution */
26 {
27  wm.z *= wm.z;
28  alpha *= alpha;
29  float tmp = (1.0f - wm.z) + alpha * wm.z;
30  return alpha / max(M_PI_F * tmp * tmp, 1e-7f);
31 }
32 
33 /* Anisotropic GGX microfacet distribution */
35 {
36  float slope_x = -wm.x / alpha.x;
37  float slope_y = -wm.y / alpha.y;
38  float tmp = wm.z * wm.z + slope_x * slope_x + slope_y * slope_y;
39 
40  return 1.0f / max(M_PI_F * tmp * tmp * alpha.x * alpha.y, 1e-7f);
41 }
42 
43 /* Sample slope distribution (based on page 14 of the supplemental implementation). */
45  const float randx,
46  const float randy)
47 {
48  if (cosI > 0.9999f || fabsf(cosI) < 1e-6f) {
49  const float r = sqrtf(randx / max(1.0f - randx, 1e-7f));
50  const float phi = M_2PI_F * randy;
51  return make_float2(r * cosf(phi), r * sinf(phi));
52  }
53 
54  const float sinI = safe_sqrtf(1.0f - cosI * cosI);
55  const float tanI = sinI / cosI;
56  const float projA = 0.5f * (cosI + 1.0f);
57  if (projA < 0.0001f)
58  return make_float2(0.0f, 0.0f);
59  const float A = 2.0f * randx * projA / cosI - 1.0f;
60  float tmp = A * A - 1.0f;
61  if (fabsf(tmp) < 1e-7f)
62  return make_float2(0.0f, 0.0f);
63  tmp = 1.0f / tmp;
64  const float D = safe_sqrtf(tanI * tanI * tmp * tmp - (A * A - tanI * tanI) * tmp);
65 
66  const float slopeX2 = tanI * tmp + D;
67  const float slopeX = (A < 0.0f || slopeX2 > 1.0f / tanI) ? (tanI * tmp - D) : slopeX2;
68 
69  float U2;
70  if (randy >= 0.5f)
71  U2 = 2.0f * (randy - 0.5f);
72  else
73  U2 = 2.0f * (0.5f - randy);
74  const float z = (U2 * (U2 * (U2 * 0.27385f - 0.73369f) + 0.46341f)) /
75  (U2 * (U2 * (U2 * 0.093073f + 0.309420f) - 1.0f) + 0.597999f);
76  const float slopeY = z * sqrtf(1.0f + slopeX * slopeX);
77 
78  if (randy >= 0.5f)
79  return make_float2(slopeX, slopeY);
80  else
81  return make_float2(slopeX, -slopeY);
82 }
83 
84 /* Visible normal sampling for the GGX distribution
85  * (based on page 7 of the supplemental implementation). */
87  const float2 alpha,
88  const float randx,
89  const float randy)
90 {
91  const float3 wi_11 = normalize(make_float3(alpha.x * wi.x, alpha.y * wi.y, wi.z));
92  const float2 slope_11 = mf_sampleP22_11(wi_11.z, randx, randy);
93 
94  const float3 cossin_phi = safe_normalize(make_float3(wi_11.x, wi_11.y, 0.0f));
95  const float slope_x = alpha.x * (cossin_phi.x * slope_11.x - cossin_phi.y * slope_11.y);
96  const float slope_y = alpha.y * (cossin_phi.y * slope_11.x + cossin_phi.x * slope_11.y);
97 
98  kernel_assert(isfinite(slope_x));
99  return normalize(make_float3(-slope_x, -slope_y, 1.0f));
100 }
101 
102 /* === Phase functions: Glossy and Glass === */
103 
104 /* Phase function for reflective materials. */
106  float3 *weight,
107  const float3 wm)
108 {
109  return -wi + 2.0f * wm * dot(wi, wm);
110 }
111 
113  const float lambda,
114  const float3 wo,
115  const float2 alpha)
116 {
117  if (w.z > 0.9999f)
118  return make_float3(0.0f, 0.0f, 0.0f);
119 
120  const float3 wh = normalize(wo - w);
121  if (wh.z < 0.0f)
122  return make_float3(0.0f, 0.0f, 0.0f);
123 
124  float pArea = (w.z < -0.9999f) ? 1.0f : lambda * w.z;
125 
126  const float dotW_WH = dot(-w, wh);
127  if (dotW_WH < 0.0f)
128  return make_float3(0.0f, 0.0f, 0.0f);
129 
130  float phase = max(0.0f, dotW_WH) * 0.25f / max(pArea * dotW_WH, 1e-7f);
131  if (alpha.x == alpha.y)
132  phase *= D_ggx(wh, alpha.x);
133  else
134  phase *= D_ggx_aniso(wh, alpha);
135 
136  return make_float3(phase, phase, phase);
137 }
138 
139 /* Phase function for dielectric transmissive materials, including both reflection and refraction
140  * according to the dielectric fresnel term. */
142  const float3 wi, const float eta, const float3 wm, const float randV, bool *outside)
143 {
144  float cosI = dot(wi, wm);
145  float f = fresnel_dielectric_cos(cosI, eta);
146  if (randV < f) {
147  *outside = true;
148  return -wi + 2.0f * wm * cosI;
149  }
150  *outside = false;
151  float inv_eta = 1.0f / eta;
152  float cosT = -safe_sqrtf(1.0f - (1.0f - cosI * cosI) * inv_eta * inv_eta);
153  return normalize(wm * (cosI * inv_eta + cosT) - wi * inv_eta);
154 }
155 
157  const float lambda,
158  const float3 wo,
159  const bool wo_outside,
160  const float2 alpha,
161  const float eta)
162 {
163  if (w.z > 0.9999f)
164  return make_float3(0.0f, 0.0f, 0.0f);
165 
166  float pArea = (w.z < -0.9999f) ? 1.0f : lambda * w.z;
167  float v;
168  if (wo_outside) {
169  const float3 wh = normalize(wo - w);
170  if (wh.z < 0.0f)
171  return make_float3(0.0f, 0.0f, 0.0f);
172 
173  const float dotW_WH = dot(-w, wh);
174  v = fresnel_dielectric_cos(dotW_WH, eta) * max(0.0f, dotW_WH) * D_ggx(wh, alpha.x) * 0.25f /
175  (pArea * dotW_WH);
176  }
177  else {
178  float3 wh = normalize(wo * eta - w);
179  if (wh.z < 0.0f)
180  wh = -wh;
181  const float dotW_WH = dot(-w, wh), dotWO_WH = dot(wo, wh);
182  if (dotW_WH < 0.0f)
183  return make_float3(0.0f, 0.0f, 0.0f);
184 
185  float temp = dotW_WH + eta * dotWO_WH;
186  v = (1.0f - fresnel_dielectric_cos(dotW_WH, eta)) * max(0.0f, dotW_WH) * max(0.0f, -dotWO_WH) *
187  D_ggx(wh, alpha.x) / (pArea * temp * temp);
188  }
189 
190  return make_float3(v, v, v);
191 }
192 
193 /* === Utility functions for the random walks === */
194 
195 /* Smith Lambda function for GGX (based on page 12 of the supplemental implementation). */
197 {
198  if (w.z > 0.9999f)
199  return 0.0f;
200  else if (w.z < -0.9999f)
201  return -0.9999f;
202 
203  const float inv_wz2 = 1.0f / max(w.z * w.z, 1e-7f);
204  const float2 wa = make_float2(w.x, w.y) * alpha;
205  float v = sqrtf(1.0f + dot(wa, wa) * inv_wz2);
206  if (w.z <= 0.0f)
207  v = -v;
208 
209  return 0.5f * (v - 1.0f);
210 }
211 
212 /* Height distribution CDF (based on page 4 of the supplemental implementation). */
213 ccl_device_forceinline float mf_invC1(const float h)
214 {
215  return 2.0f * saturate(h) - 1.0f;
216 }
217 
218 ccl_device_forceinline float mf_C1(const float h)
219 {
220  return saturate(0.5f * (h + 1.0f));
221 }
222 
223 /* Masking function (based on page 16 of the supplemental implementation). */
224 ccl_device_forceinline float mf_G1(const float3 w, const float C1, const float lambda)
225 {
226  if (w.z > 0.9999f)
227  return 1.0f;
228  if (w.z < 1e-5f)
229  return 0.0f;
230  return powf(C1, lambda);
231 }
232 
233 /* Sampling from the visible height distribution (based on page 17 of the supplemental
234  * implementation). */
236  const float3 w, float *h, float *C1, float *G1, float *lambda, const float U)
237 {
238  if (w.z > 0.9999f)
239  return false;
240  if (w.z < -0.9999f) {
241  *C1 *= U;
242  *h = mf_invC1(*C1);
243  *G1 = mf_G1(w, *C1, *lambda);
244  }
245  else if (fabsf(w.z) >= 0.0001f) {
246  if (U > 1.0f - *G1)
247  return false;
248  if (*lambda >= 0.0f) {
249  *C1 = 1.0f;
250  }
251  else {
252  *C1 *= powf(1.0f - U, -1.0f / *lambda);
253  }
254  *h = mf_invC1(*C1);
255  *G1 = mf_G1(w, *C1, *lambda);
256  }
257  return true;
258 }
259 
260 /* === PDF approximations for the different phase functions. ===
261  * As explained in bsdf_microfacet_multi_impl.h, using approximations with MIS still produces an
262  * unbiased result. */
263 
264 /* Approximation for the albedo of the single-scattering GGX distribution,
265  * the missing energy is then approximated as a diffuse reflection for the PDF. */
267 {
268  float albedo = 0.806495f * expf(-1.98712f * r * r) + 0.199531f;
269  albedo -= ((((((1.76741f * r - 8.43891f) * r + 15.784f) * r - 14.398f) * r + 6.45221f) * r -
270  1.19722f) *
271  r +
272  0.027803f) *
273  r +
274  0.00568739f;
275  return saturate(albedo);
276 }
277 
279 {
280  if (ior < 1.0f) {
281  ior = 1.0f / ior;
282  }
283  a = saturate(a);
284  ior = clamp(ior, 1.0f, 3.0f);
285  float I_1 = 0.0476898f * expf(-0.978352f * (ior - 0.65657f) * (ior - 0.65657f)) -
286  0.033756f * ior + 0.993261f;
287  float R_1 = (((0.116991f * a - 0.270369f) * a + 0.0501366f) * a - 0.00411511f) * a + 1.00008f;
288  float I_2 = (((-2.08704f * ior + 26.3298f) * ior - 127.906f) * ior + 292.958f) * ior - 287.946f +
289  199.803f / (ior * ior) - 101.668f / (ior * ior * ior);
290  float R_2 = ((((5.3725f * a - 24.9307f) * a + 22.7437f) * a - 3.40751f) * a + 0.0986325f) * a +
291  0.00493504f;
292 
293  return saturate(1.0f + I_2 * R_2 * 0.0019127f - (1.0f - I_1) * (1.0f - R_1) * 9.3205f);
294 }
295 
296 ccl_device_forceinline float mf_ggx_pdf(const float3 wi, const float3 wo, const float alpha)
297 {
298  float D = D_ggx(normalize(wi + wo), alpha);
299  float lambda = mf_lambda(wi, make_float2(alpha, alpha));
300  float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
301 
302  float multiscatter = wo.z * M_1_PI_F;
303 
304  float albedo = mf_ggx_albedo(alpha);
305  return albedo * singlescatter + (1.0f - albedo) * multiscatter;
306 }
307 
309 {
310  float D = D_ggx_aniso(normalize(wi + wo), alpha);
311  float lambda = mf_lambda(wi, alpha);
312  float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
313 
314  float multiscatter = wo.z * M_1_PI_F;
315 
316  float albedo = mf_ggx_albedo(sqrtf(alpha.x * alpha.y));
317  return albedo * singlescatter + (1.0f - albedo) * multiscatter;
318 }
319 
321  const float3 wo,
322  const float alpha,
323  const float eta)
324 {
325  bool reflective = (wi.z * wo.z > 0.0f);
326 
327  float wh_len;
328  float3 wh = normalize_len(wi + (reflective ? wo : (wo * eta)), &wh_len);
329  if (wh.z < 0.0f)
330  wh = -wh;
331  float3 r_wi = (wi.z < 0.0f) ? -wi : wi;
332  float lambda = mf_lambda(r_wi, make_float2(alpha, alpha));
333  float D = D_ggx(wh, alpha);
334  float fresnel = fresnel_dielectric_cos(dot(r_wi, wh), eta);
335 
336  float multiscatter = fabsf(wo.z * M_1_PI_F);
337  if (reflective) {
338  float singlescatter = 0.25f * D / max((1.0f + lambda) * r_wi.z, 1e-7f);
339  float albedo = mf_ggx_albedo(alpha);
340  return fresnel * (albedo * singlescatter + (1.0f - albedo) * multiscatter);
341  }
342  else {
343  float singlescatter = fabsf(dot(r_wi, wh) * dot(wo, wh) * D * eta * eta /
344  max((1.0f + lambda) * r_wi.z * wh_len * wh_len, 1e-7f));
345  float albedo = mf_ggx_transmission_albedo(alpha, eta);
346  return (1.0f - fresnel) * (albedo * singlescatter + (1.0f - albedo) * multiscatter);
347  }
348 }
349 
350 /* === Actual random walk implementations === */
351 /* One version of mf_eval and mf_sample per phase function. */
352 
353 #define MF_NAME_JOIN(x, y) x##_##y
354 #define MF_NAME_EVAL(x, y) MF_NAME_JOIN(x, y)
355 #define MF_FUNCTION_FULL_NAME(prefix) MF_NAME_EVAL(prefix, MF_PHASE_FUNCTION)
356 
357 #define MF_PHASE_FUNCTION glass
358 #define MF_MULTI_GLASS
360 
361 #define MF_PHASE_FUNCTION glossy
362 #define MF_MULTI_GLOSSY
364 
366 {
367  MicrofacetBsdf *bsdf = (MicrofacetBsdf *)sc;
368 
369  bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
370  bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
371 }
372 
373 /* === Closure implementations === */
374 
375 /* Multiscattering GGX Glossy closure */
376 
378 {
379  bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
380  bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
381  bsdf->extra->color = saturate3(bsdf->extra->color);
382  bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0);
383 
385 }
386 
388 {
389  if (is_zero(bsdf->T))
390  bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
391 
393 
395 }
396 
398 {
399  if (is_zero(bsdf->T))
400  bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
401 
403 
405 
407 }
408 
410 {
411  bsdf->alpha_y = bsdf->alpha_x;
412 
414 
416 }
417 
419  const float3 I,
420  const float3 omega_in,
421  float *pdf,
422  ccl_addr_space uint *lcg_state)
423 {
424  *pdf = 0.0f;
425  return make_float3(0.0f, 0.0f, 0.0f);
426 }
427 
429  const float3 I,
430  const float3 omega_in,
431  float *pdf,
432  ccl_addr_space uint *lcg_state)
433 {
434  const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
435 
436  if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
437  return make_float3(0.0f, 0.0f, 0.0f);
438  }
439 
440  bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
441 
442  bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
443  float3 X, Y, Z;
444  Z = bsdf->N;
445  if (is_aniso)
446  make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
447  else
448  make_orthonormals(Z, &X, &Y);
449 
450  float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
451  float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
452 
453  if (is_aniso)
454  *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
455  else
456  *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
457  return mf_eval_glossy(localI,
458  localO,
459  true,
460  bsdf->extra->color,
461  bsdf->alpha_x,
462  bsdf->alpha_y,
463  lcg_state,
464  bsdf->ior,
465  use_fresnel,
466  bsdf->extra->cspec0);
467 }
468 
470  const ShaderClosure *sc,
471  float3 Ng,
472  float3 I,
473  float3 dIdx,
474  float3 dIdy,
475  float randu,
476  float randv,
477  float3 *eval,
478  float3 *omega_in,
479  float3 *domega_in_dx,
480  float3 *domega_in_dy,
481  float *pdf,
482  ccl_addr_space uint *lcg_state)
483 {
484  const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
485 
486  float3 X, Y, Z;
487  Z = bsdf->N;
488 
489  if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
490  *omega_in = 2 * dot(Z, I) * Z - I;
491  *pdf = 1e6f;
492  *eval = make_float3(1e6f, 1e6f, 1e6f);
493 #ifdef __RAY_DIFFERENTIALS__
494  *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
495  *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
496 #endif
497  return LABEL_REFLECT | LABEL_SINGULAR;
498  }
499 
500  bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
501 
502  bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
503  if (is_aniso)
504  make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
505  else
506  make_orthonormals(Z, &X, &Y);
507 
508  float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
509  float3 localO;
510 
511  *eval = mf_sample_glossy(localI,
512  &localO,
513  bsdf->extra->color,
514  bsdf->alpha_x,
515  bsdf->alpha_y,
516  lcg_state,
517  bsdf->ior,
518  use_fresnel,
519  bsdf->extra->cspec0);
520  if (is_aniso)
521  *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
522  else
523  *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
524  *eval *= *pdf;
525 
526  *omega_in = X * localO.x + Y * localO.y + Z * localO.z;
527 
528 #ifdef __RAY_DIFFERENTIALS__
529  *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
530  *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
531 #endif
532  return LABEL_REFLECT | LABEL_GLOSSY;
533 }
534 
535 /* Multiscattering GGX Glass closure */
536 
538 {
539  bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
540  bsdf->alpha_y = bsdf->alpha_x;
541  bsdf->ior = max(0.0f, bsdf->ior);
542  bsdf->extra->color = saturate3(bsdf->extra->color);
543 
545 
547 }
548 
550  const ShaderData *sd)
551 {
552  bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
553  bsdf->alpha_y = bsdf->alpha_x;
554  bsdf->ior = max(0.0f, bsdf->ior);
555  bsdf->extra->color = saturate3(bsdf->extra->color);
556  bsdf->extra->cspec0 = saturate3(bsdf->extra->cspec0);
557 
559 
561 
563 }
564 
566  const float3 I,
567  const float3 omega_in,
568  float *pdf,
569  ccl_addr_space uint *lcg_state)
570 {
571  const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
572 
573  if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
574  return make_float3(0.0f, 0.0f, 0.0f);
575  }
576 
577  float3 X, Y, Z;
578  Z = bsdf->N;
579  make_orthonormals(Z, &X, &Y);
580 
581  float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
582  float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
583 
584  *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
585  return mf_eval_glass(localI,
586  localO,
587  false,
588  bsdf->extra->color,
589  bsdf->alpha_x,
590  bsdf->alpha_y,
591  lcg_state,
592  bsdf->ior,
593  false,
594  bsdf->extra->color);
595 }
596 
598  const float3 I,
599  const float3 omega_in,
600  float *pdf,
601  ccl_addr_space uint *lcg_state)
602 {
603  const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
604 
605  if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
606  return make_float3(0.0f, 0.0f, 0.0f);
607  }
608 
609  bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
610 
611  float3 X, Y, Z;
612  Z = bsdf->N;
613  make_orthonormals(Z, &X, &Y);
614 
615  float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
616  float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
617 
618  *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
619  return mf_eval_glass(localI,
620  localO,
621  true,
622  bsdf->extra->color,
623  bsdf->alpha_x,
624  bsdf->alpha_y,
625  lcg_state,
626  bsdf->ior,
627  use_fresnel,
628  bsdf->extra->cspec0);
629 }
630 
632  const ShaderClosure *sc,
633  float3 Ng,
634  float3 I,
635  float3 dIdx,
636  float3 dIdy,
637  float randu,
638  float randv,
639  float3 *eval,
640  float3 *omega_in,
641  float3 *domega_in_dx,
642  float3 *domega_in_dy,
643  float *pdf,
644  ccl_addr_space uint *lcg_state)
645 {
646  const MicrofacetBsdf *bsdf = (const MicrofacetBsdf *)sc;
647 
648  float3 X, Y, Z;
649  Z = bsdf->N;
650 
651  if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
652  float3 R, T;
653 #ifdef __RAY_DIFFERENTIALS__
654  float3 dRdx, dRdy, dTdx, dTdy;
655 #endif
656  bool inside;
657  float fresnel = fresnel_dielectric(bsdf->ior,
658  Z,
659  I,
660  &R,
661  &T,
663  dIdx,
664  dIdy,
665  &dRdx,
666  &dRdy,
667  &dTdx,
668  &dTdy,
669 #endif
670  &inside);
671 
672  *pdf = 1e6f;
673  *eval = make_float3(1e6f, 1e6f, 1e6f);
674  if (randu < fresnel) {
675  *omega_in = R;
676 #ifdef __RAY_DIFFERENTIALS__
677  *domega_in_dx = dRdx;
678  *domega_in_dy = dRdy;
679 #endif
680  return LABEL_REFLECT | LABEL_SINGULAR;
681  }
682  else {
683  *omega_in = T;
684 #ifdef __RAY_DIFFERENTIALS__
685  *domega_in_dx = dTdx;
686  *domega_in_dy = dTdy;
687 #endif
689  }
690  }
691 
692  bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
693 
694  make_orthonormals(Z, &X, &Y);
695 
696  float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
697  float3 localO;
698 
699  *eval = mf_sample_glass(localI,
700  &localO,
701  bsdf->extra->color,
702  bsdf->alpha_x,
703  bsdf->alpha_y,
704  lcg_state,
705  bsdf->ior,
706  use_fresnel,
707  bsdf->extra->cspec0);
708  *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
709  *eval *= *pdf;
710 
711  *omega_in = X * localO.x + Y * localO.y + Z * localO.z;
712  if (localO.z * localI.z > 0.0f) {
713 #ifdef __RAY_DIFFERENTIALS__
714  *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
715  *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
716 #endif
717  return LABEL_REFLECT | LABEL_GLOSSY;
718  }
719  else {
720 #ifdef __RAY_DIFFERENTIALS__
721  float cosI = dot(Z, I);
722  float dnp = max(sqrtf(1.0f - (bsdf->ior * bsdf->ior * (1.0f - cosI * cosI))), 1e-7f);
723  *domega_in_dx = -(bsdf->ior * dIdx) +
724  ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdx, Z)) * Z;
725  *domega_in_dy = -(bsdf->ior * dIdy) +
726  ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdy, Z)) * Z;
727 #endif
728 
729  return LABEL_TRANSMIT | LABEL_GLOSSY;
730  }
731 }
732 
MINLINE float safe_sqrtf(float a)
unsigned int uint
Definition: BLI_sys_types.h:83
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble z
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
#define X
Definition: GeomUtils.cpp:213
#define Z
Definition: GeomUtils.cpp:215
#define Y
Definition: GeomUtils.cpp:214
#define U
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define A
ccl_device_forceinline void bsdf_microfacet_fresnel_color(const ShaderData *sd, MicrofacetBsdf *bsdf)
ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state)
ccl_device_forceinline bool mf_sample_height(const float3 w, float *h, float *C1, float *G1, float *lambda, const float U)
ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state)
ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w, const float lambda, const float3 wo, const float2 alpha)
ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state)
ccl_device void bsdf_microfacet_multi_ggx_blur(ShaderClosure *sc, float roughness)
ccl_device_forceinline float D_ggx_aniso(const float3 wm, const float2 alpha)
ccl_device_forceinline float mf_C1(const float h)
ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state)
ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(const ShaderClosure *sc, const float3 I, const float3 omega_in, float *pdf, ccl_addr_space uint *lcg_state)
ccl_device_forceinline float mf_lambda(const float3 w, const float2 alpha)
ccl_device_forceinline float mf_invC1(const float h)
ccl_device_forceinline float3 mf_eval_phase_glass(const float3 w, const float lambda, const float3 wo, const bool wo_outside, const float2 alpha, const float eta)
ccl_device int bsdf_microfacet_multi_ggx_setup(MicrofacetBsdf *bsdf)
ccl_device_forceinline float3 mf_sample_phase_glass(const float3 wi, const float eta, const float3 wm, const float randV, bool *outside)
ccl_device_forceinline float mf_ggx_aniso_pdf(const float3 wi, const float3 wo, const float2 alpha)
ccl_device_forceinline float mf_glass_pdf(const float3 wi, const float3 wo, const float alpha, const float eta)
CCL_NAMESPACE_BEGIN ccl_device_forceinline float D_ggx(float3 wm, float alpha)
ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(MicrofacetBsdf *bsdf)
ccl_device_forceinline float3 mf_sample_vndf(const float3 wi, const float2 alpha, const float randx, const float randy)
ccl_device_forceinline float2 mf_sampleP22_11(const float cosI, const float randx, const float randy)
ccl_device_forceinline float3 mf_sample_phase_glossy(const float3 wi, float3 *weight, const float3 wm)
ccl_device_inline float mf_ggx_transmission_albedo(float a, float ior)
ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(MicrofacetBsdf *bsdf, const ShaderData *sd)
ccl_device_forceinline float mf_G1(const float3 w, const float C1, const float lambda)
ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals *kg, const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, float3 *eval, float3 *omega_in, float3 *domega_in_dx, float3 *domega_in_dy, float *pdf, ccl_addr_space uint *lcg_state)
ccl_device int bsdf_microfacet_multi_ggx_glass_setup(MicrofacetBsdf *bsdf)
ccl_device_forceinline float mf_ggx_albedo(float r)
ccl_device_forceinline float mf_ggx_pdf(const float3 wi, const float3 wo, const float alpha)
ccl_device int bsdf_microfacet_multi_ggx_common_setup(MicrofacetBsdf *bsdf)
ccl_device float fresnel_dielectric_cos(float cosi, float eta)
Definition: bsdf_util.h:104
CCL_NAMESPACE_BEGIN ccl_device float fresnel_dielectric(float eta, const float3 N, const float3 I, float3 *R, float3 *T, bool *is_inside)
Definition: bsdf_util.h:38
unsigned int U
Definition: btGjkEpa3.h:78
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
static CCL_NAMESPACE_BEGIN const double alpha
#define kernel_assert(cond)
#define ccl_addr_space
#define ccl_device_forceinline
#define sinf(x)
#define cosf(x)
#define ccl_device
#define expf(x)
#define ccl_device_inline
#define powf(x, y)
#define CCL_NAMESPACE_END
#define fmaxf(x, y)
#define make_float2(x, y)
#define fabsf(x)
#define sqrtf(x)
#define make_float3(x, y, z)
ccl_device void make_orthonormals_tangent(const float3 N, const float3 T, float3 *a, float3 *b)
@ SD_BSDF_HAS_EVAL
Definition: kernel_types.h:849
@ SD_BSDF_NEEDS_LCG
Definition: kernel_types.h:861
@ SD_BSDF
Definition: kernel_types.h:847
ShaderData
#define __RAY_DIFFERENTIALS__
Definition: kernel_types.h:91
@ LABEL_TRANSMIT
Definition: kernel_types.h:328
@ LABEL_SINGULAR
Definition: kernel_types.h:332
@ LABEL_GLOSSY
Definition: kernel_types.h:331
@ LABEL_REFLECT
Definition: kernel_types.h:329
ShaderClosure
Definition: kernel_types.h:831
#define T
#define R
bool isfinite(uchar)
Definition: image.cpp:44
static unsigned a[3]
Definition: RandGen.cpp:92
static const pxr::TfToken roughness("roughness", pxr::TfToken::Immortal)
#define I
MicrofacetExtra * extra
float z
Definition: sky_float3.h:35
float y
Definition: sky_float3.h:35
float x
Definition: sky_float3.h:35
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID
Definition: svm_types.h:548
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID
Definition: svm_types.h:560
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID
Definition: svm_types.h:563
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID
Definition: svm_types.h:549
float max
ccl_device_inline float saturate(float a)
Definition: util_math.h:315
ccl_device_inline void make_orthonormals(const float3 N, float3 *a, float3 *b)
Definition: util_math.h:477
#define M_2PI_F
Definition: util_math.h:69
#define M_1_PI_F
Definition: util_math.h:52
#define M_PI_F
Definition: util_math.h:43
ccl_device_inline int clamp(int a, int mn, int mx)
Definition: util_math.h:283
ccl_device_inline float2 normalize(const float2 &a)
ccl_device_inline float dot(const float2 &a, const float2 &b)
ccl_device_inline float2 safe_normalize(const float2 &a)
ccl_device_inline float2 normalize_len(const float2 &a, float *t)
ccl_device_inline bool is_zero(const float2 &a)
ccl_device_inline float3 saturate3(float3 a)
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:29