Blender  V3.3
bsdf_microfacet_multi.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #pragma once
5 
6 #include "kernel/sample/lcg.h"
8 
10 
11 /* Most of the code is based on the supplemental implementations from
12  * https://eheitzresearch.wordpress.com/240-2/. */
13 
14 /* === GGX Microfacet distribution functions === */
15 
16 /* Isotropic GGX microfacet distribution */
17 ccl_device_forceinline float D_ggx(float3 wm, float alpha)
18 {
19  wm.z *= wm.z;
20  alpha *= alpha;
21  float tmp = (1.0f - wm.z) + alpha * wm.z;
22  return alpha / max(M_PI_F * tmp * tmp, 1e-7f);
23 }
24 
25 /* Anisotropic GGX microfacet distribution */
26 ccl_device_forceinline float D_ggx_aniso(const float3 wm, const float2 alpha)
27 {
28  float slope_x = -wm.x / alpha.x;
29  float slope_y = -wm.y / alpha.y;
30  float tmp = wm.z * wm.z + slope_x * slope_x + slope_y * slope_y;
31 
32  return 1.0f / max(M_PI_F * tmp * tmp * alpha.x * alpha.y, 1e-7f);
33 }
34 
35 /* Sample slope distribution (based on page 14 of the supplemental implementation). */
37  const float randx,
38  const float randy)
39 {
40  if (cosI > 0.9999f || fabsf(cosI) < 1e-6f) {
41  const float r = sqrtf(randx / max(1.0f - randx, 1e-7f));
42  const float phi = M_2PI_F * randy;
43  return make_float2(r * cosf(phi), r * sinf(phi));
44  }
45 
46  const float sinI = safe_sqrtf(1.0f - cosI * cosI);
47  const float tanI = sinI / cosI;
48  const float projA = 0.5f * (cosI + 1.0f);
49  if (projA < 0.0001f)
50  return make_float2(0.0f, 0.0f);
51  const float A = 2.0f * randx * projA / cosI - 1.0f;
52  float tmp = A * A - 1.0f;
53  if (fabsf(tmp) < 1e-7f)
54  return make_float2(0.0f, 0.0f);
55  tmp = 1.0f / tmp;
56  const float D = safe_sqrtf(tanI * tanI * tmp * tmp - (A * A - tanI * tanI) * tmp);
57 
58  const float slopeX2 = tanI * tmp + D;
59  const float slopeX = (A < 0.0f || slopeX2 > 1.0f / tanI) ? (tanI * tmp - D) : slopeX2;
60 
61  float U2;
62  if (randy >= 0.5f)
63  U2 = 2.0f * (randy - 0.5f);
64  else
65  U2 = 2.0f * (0.5f - randy);
66  const float z = (U2 * (U2 * (U2 * 0.27385f - 0.73369f) + 0.46341f)) /
67  (U2 * (U2 * (U2 * 0.093073f + 0.309420f) - 1.0f) + 0.597999f);
68  const float slopeY = z * sqrtf(1.0f + slopeX * slopeX);
69 
70  if (randy >= 0.5f)
71  return make_float2(slopeX, slopeY);
72  else
73  return make_float2(slopeX, -slopeY);
74 }
75 
76 /* Visible normal sampling for the GGX distribution
77  * (based on page 7 of the supplemental implementation). */
79  const float2 alpha,
80  const float randx,
81  const float randy)
82 {
83  const float3 wi_11 = normalize(make_float3(alpha.x * wi.x, alpha.y * wi.y, wi.z));
84  const float2 slope_11 = mf_sampleP22_11(wi_11.z, randx, randy);
85 
86  const float3 cossin_phi = safe_normalize(make_float3(wi_11.x, wi_11.y, 0.0f));
87  const float slope_x = alpha.x * (cossin_phi.x * slope_11.x - cossin_phi.y * slope_11.y);
88  const float slope_y = alpha.y * (cossin_phi.y * slope_11.x + cossin_phi.x * slope_11.y);
89 
90  kernel_assert(isfinite(slope_x));
91  return normalize(make_float3(-slope_x, -slope_y, 1.0f));
92 }
93 
94 /* === Phase functions: Glossy and Glass === */
95 
96 /* Phase function for reflective materials. */
98  ccl_private float3 *weight,
99  const float3 wm)
100 {
101  return -wi + 2.0f * wm * dot(wi, wm);
102 }
103 
105  const float lambda,
106  const float3 wo,
107  const float2 alpha)
108 {
109  if (w.z > 0.9999f)
110  return make_float3(0.0f, 0.0f, 0.0f);
111 
112  const float3 wh = normalize(wo - w);
113  if (wh.z < 0.0f)
114  return make_float3(0.0f, 0.0f, 0.0f);
115 
116  float pArea = (w.z < -0.9999f) ? 1.0f : lambda * w.z;
117 
118  const float dotW_WH = dot(-w, wh);
119  if (dotW_WH < 0.0f)
120  return make_float3(0.0f, 0.0f, 0.0f);
121 
122  float phase = max(0.0f, dotW_WH) * 0.25f / max(pArea * dotW_WH, 1e-7f);
123  if (alpha.x == alpha.y)
124  phase *= D_ggx(wh, alpha.x);
125  else
126  phase *= D_ggx_aniso(wh, alpha);
127 
128  return make_float3(phase, phase, phase);
129 }
130 
131 /* Phase function for dielectric transmissive materials, including both reflection and refraction
132  * according to the dielectric fresnel term. */
134  const float eta,
135  const float3 wm,
136  const float randV,
137  ccl_private bool *outside)
138 {
139  float cosI = dot(wi, wm);
140  float f = fresnel_dielectric_cos(cosI, eta);
141  if (randV < f) {
142  *outside = true;
143  return -wi + 2.0f * wm * cosI;
144  }
145  *outside = false;
146  float inv_eta = 1.0f / eta;
147  float cosT = -safe_sqrtf(1.0f - (1.0f - cosI * cosI) * inv_eta * inv_eta);
148  return normalize(wm * (cosI * inv_eta + cosT) - wi * inv_eta);
149 }
150 
152  const float lambda,
153  const float3 wo,
154  const bool wo_outside,
155  const float2 alpha,
156  const float eta)
157 {
158  if (w.z > 0.9999f)
159  return make_float3(0.0f, 0.0f, 0.0f);
160 
161  float pArea = (w.z < -0.9999f) ? 1.0f : lambda * w.z;
162  float v;
163  if (wo_outside) {
164  const float3 wh = normalize(wo - w);
165  if (wh.z < 0.0f)
166  return make_float3(0.0f, 0.0f, 0.0f);
167 
168  const float dotW_WH = dot(-w, wh);
169  v = fresnel_dielectric_cos(dotW_WH, eta) * max(0.0f, dotW_WH) * D_ggx(wh, alpha.x) * 0.25f /
170  (pArea * dotW_WH);
171  }
172  else {
173  float3 wh = normalize(wo * eta - w);
174  if (wh.z < 0.0f)
175  wh = -wh;
176  const float dotW_WH = dot(-w, wh), dotWO_WH = dot(wo, wh);
177  if (dotW_WH < 0.0f)
178  return make_float3(0.0f, 0.0f, 0.0f);
179 
180  float temp = dotW_WH + eta * dotWO_WH;
181  v = (1.0f - fresnel_dielectric_cos(dotW_WH, eta)) * max(0.0f, dotW_WH) * max(0.0f, -dotWO_WH) *
182  D_ggx(wh, alpha.x) / (pArea * temp * temp);
183  }
184 
185  return make_float3(v, v, v);
186 }
187 
188 /* === Utility functions for the random walks === */
189 
190 /* Smith Lambda function for GGX (based on page 12 of the supplemental implementation). */
191 ccl_device_forceinline float mf_lambda(const float3 w, const float2 alpha)
192 {
193  if (w.z > 0.9999f)
194  return 0.0f;
195  else if (w.z < -0.9999f)
196  return -0.9999f;
197 
198  const float inv_wz2 = 1.0f / max(w.z * w.z, 1e-7f);
199  const float2 wa = make_float2(w.x, w.y) * alpha;
200  float v = sqrtf(1.0f + dot(wa, wa) * inv_wz2);
201  if (w.z <= 0.0f)
202  v = -v;
203 
204  return 0.5f * (v - 1.0f);
205 }
206 
207 /* Height distribution CDF (based on page 4 of the supplemental implementation). */
208 ccl_device_forceinline float mf_invC1(const float h)
209 {
210  return 2.0f * saturatef(h) - 1.0f;
211 }
212 
213 ccl_device_forceinline float mf_C1(const float h)
214 {
215  return saturatef(0.5f * (h + 1.0f));
216 }
217 
218 /* Masking function (based on page 16 of the supplemental implementation). */
219 ccl_device_forceinline float mf_G1(const float3 w, const float C1, const float lambda)
220 {
221  if (w.z > 0.9999f)
222  return 1.0f;
223  if (w.z < 1e-5f)
224  return 0.0f;
225  return powf(C1, lambda);
226 }
227 
228 /* Sampling from the visible height distribution (based on page 17 of the supplemental
229  * implementation). */
231  ccl_private float *h,
232  ccl_private float *C1,
233  ccl_private float *G1,
234  ccl_private float *lambda,
235  const float U)
236 {
237  if (w.z > 0.9999f)
238  return false;
239  if (w.z < -0.9999f) {
240  *C1 *= U;
241  *h = mf_invC1(*C1);
242  *G1 = mf_G1(w, *C1, *lambda);
243  }
244  else if (fabsf(w.z) >= 0.0001f) {
245  if (U > 1.0f - *G1)
246  return false;
247  if (*lambda >= 0.0f) {
248  *C1 = 1.0f;
249  }
250  else {
251  *C1 *= powf(1.0f - U, -1.0f / *lambda);
252  }
253  *h = mf_invC1(*C1);
254  *G1 = mf_G1(w, *C1, *lambda);
255  }
256  return true;
257 }
258 
259 /* === PDF approximations for the different phase functions. ===
260  * As explained in bsdf_microfacet_multi_impl.h, using approximations with MIS still produces an
261  * unbiased result. */
262 
263 /* Approximation for the albedo of the single-scattering GGX distribution,
264  * the missing energy is then approximated as a diffuse reflection for the PDF. */
266 {
267  float albedo = 0.806495f * expf(-1.98712f * r * r) + 0.199531f;
268  albedo -= ((((((1.76741f * r - 8.43891f) * r + 15.784f) * r - 14.398f) * r + 6.45221f) * r -
269  1.19722f) *
270  r +
271  0.027803f) *
272  r +
273  0.00568739f;
274  return saturatef(albedo);
275 }
276 
278 {
279  if (ior < 1.0f) {
280  ior = 1.0f / ior;
281  }
282  a = saturatef(a);
283  ior = clamp(ior, 1.0f, 3.0f);
284  float I_1 = 0.0476898f * expf(-0.978352f * (ior - 0.65657f) * (ior - 0.65657f)) -
285  0.033756f * ior + 0.993261f;
286  float R_1 = (((0.116991f * a - 0.270369f) * a + 0.0501366f) * a - 0.00411511f) * a + 1.00008f;
287  float I_2 = (((-2.08704f * ior + 26.3298f) * ior - 127.906f) * ior + 292.958f) * ior - 287.946f +
288  199.803f / (ior * ior) - 101.668f / (ior * ior * ior);
289  float R_2 = ((((5.3725f * a - 24.9307f) * a + 22.7437f) * a - 3.40751f) * a + 0.0986325f) * a +
290  0.00493504f;
291 
292  return saturatef(1.0f + I_2 * R_2 * 0.0019127f - (1.0f - I_1) * (1.0f - R_1) * 9.3205f);
293 }
294 
295 ccl_device_forceinline float mf_ggx_pdf(const float3 wi, const float3 wo, const float alpha)
296 {
297  float D = D_ggx(normalize(wi + wo), alpha);
298  float lambda = mf_lambda(wi, make_float2(alpha, alpha));
299  float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
300 
301  float multiscatter = wo.z * M_1_PI_F;
302 
303  float albedo = mf_ggx_albedo(alpha);
304  return albedo * singlescatter + (1.0f - albedo) * multiscatter;
305 }
306 
307 ccl_device_forceinline float mf_ggx_aniso_pdf(const float3 wi, const float3 wo, const float2 alpha)
308 {
309  float D = D_ggx_aniso(normalize(wi + wo), alpha);
310  float lambda = mf_lambda(wi, alpha);
311  float singlescatter = 0.25f * D / max((1.0f + lambda) * wi.z, 1e-7f);
312 
313  float multiscatter = wo.z * M_1_PI_F;
314 
315  float albedo = mf_ggx_albedo(sqrtf(alpha.x * alpha.y));
316  return albedo * singlescatter + (1.0f - albedo) * multiscatter;
317 }
318 
320  const float3 wo,
321  const float alpha,
322  const float eta)
323 {
324  bool reflective = (wi.z * wo.z > 0.0f);
325 
326  float wh_len;
327  float3 wh = normalize_len(wi + (reflective ? wo : (wo * eta)), &wh_len);
328  if (wh.z < 0.0f)
329  wh = -wh;
330  float3 r_wi = (wi.z < 0.0f) ? -wi : wi;
331  float lambda = mf_lambda(r_wi, make_float2(alpha, alpha));
332  float D = D_ggx(wh, alpha);
333  float fresnel = fresnel_dielectric_cos(dot(r_wi, wh), eta);
334 
335  float multiscatter = fabsf(wo.z * M_1_PI_F);
336  if (reflective) {
337  float singlescatter = 0.25f * D / max((1.0f + lambda) * r_wi.z, 1e-7f);
338  float albedo = mf_ggx_albedo(alpha);
339  return fresnel * (albedo * singlescatter + (1.0f - albedo) * multiscatter);
340  }
341  else {
342  float singlescatter = fabsf(dot(r_wi, wh) * dot(wo, wh) * D * eta * eta /
343  max((1.0f + lambda) * r_wi.z * wh_len * wh_len, 1e-7f));
344  float albedo = mf_ggx_transmission_albedo(alpha, eta);
345  return (1.0f - fresnel) * (albedo * singlescatter + (1.0f - albedo) * multiscatter);
346  }
347 }
348 
349 /* === Actual random walk implementations === */
350 /* One version of mf_eval and mf_sample per phase function. */
351 
352 #define MF_NAME_JOIN(x, y) x##_##y
353 #define MF_NAME_EVAL(x, y) MF_NAME_JOIN(x, y)
354 #define MF_FUNCTION_FULL_NAME(prefix) MF_NAME_EVAL(prefix, MF_PHASE_FUNCTION)
355 
356 #define MF_PHASE_FUNCTION glass
357 #define MF_MULTI_GLASS
359 
360 #define MF_PHASE_FUNCTION glossy
361 #define MF_MULTI_GLOSSY
363 
365 {
367 
368  bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
369  bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
370 }
371 
372 /* === Closure implementations === */
373 
374 /* Multiscattering GGX Glossy closure */
375 
377 {
378  bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
379  bsdf->alpha_y = clamp(bsdf->alpha_y, 1e-4f, 1.0f);
380  bsdf->extra->color = saturate(bsdf->extra->color);
381  bsdf->extra->cspec0 = saturate(bsdf->extra->cspec0);
382 
384 }
385 
387 {
388  if (is_zero(bsdf->T))
389  bsdf->T = make_float3(1.0f, 0.0f, 0.0f);
390 
392 
394 }
395 
397  ccl_private const ShaderData *sd)
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  ccl_private float *pdf,
422  ccl_private 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  ccl_private float *pdf,
432  ccl_private uint *lcg_state)
433 {
434  ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
435 
436  if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
437  *pdf = 0.0f;
438  return make_float3(0.0f, 0.0f, 0.0f);
439  }
440 
441  float3 X, Y, Z;
442  Z = bsdf->N;
443 
444  /* Ensure that the both directions are on the outside w.r.t. the shading normal. */
445  if (dot(Z, I) <= 0.0f || dot(Z, omega_in) <= 0.0f) {
446  *pdf = 0.0f;
447  return make_float3(0.0f, 0.0f, 0.0f);
448  }
449 
450  bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
451 
452  bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
453  if (is_aniso)
454  make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
455  else
456  make_orthonormals(Z, &X, &Y);
457 
458  float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
459  float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
460 
461  if (is_aniso)
462  *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
463  else
464  *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
465  return mf_eval_glossy(localI,
466  localO,
467  true,
468  bsdf->extra->color,
469  bsdf->alpha_x,
470  bsdf->alpha_y,
471  lcg_state,
472  bsdf->ior,
473  use_fresnel,
474  bsdf->extra->cspec0);
475 }
476 
478  ccl_private const ShaderClosure *sc,
479  float3 Ng,
480  float3 I,
481  float3 dIdx,
482  float3 dIdy,
483  float randu,
484  float randv,
485  ccl_private float3 *eval,
486  ccl_private float3 *omega_in,
487  ccl_private float3 *domega_in_dx,
488  ccl_private float3 *domega_in_dy,
489  ccl_private float *pdf,
490  ccl_private uint *lcg_state)
491 {
492  ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
493 
494  float3 X, Y, Z;
495  Z = bsdf->N;
496 
497  /* Ensure that the view direction is on the outside w.r.t. the shading normal. */
498  if (dot(Z, I) <= 0.0f) {
499  *pdf = 0.0f;
500  return LABEL_NONE;
501  }
502 
503  /* Special case: Extremely low roughness.
504  * Don't bother with microfacets, just do specular reflection. */
505  if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
506  *omega_in = 2 * dot(Z, I) * Z - I;
507  if (dot(Ng, *omega_in) <= 0.0f) {
508  *pdf = 0.0f;
509  return LABEL_NONE;
510  }
511  *pdf = 1e6f;
512  *eval = make_float3(1e6f, 1e6f, 1e6f);
513 #ifdef __RAY_DIFFERENTIALS__
514  *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
515  *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
516 #endif
517  return LABEL_REFLECT | LABEL_SINGULAR;
518  }
519 
520  bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID);
521 
522  bool is_aniso = (bsdf->alpha_x != bsdf->alpha_y);
523  if (is_aniso)
524  make_orthonormals_tangent(Z, bsdf->T, &X, &Y);
525  else
526  make_orthonormals(Z, &X, &Y);
527 
528  float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
529  float3 localO;
530 
531  *eval = mf_sample_glossy(localI,
532  &localO,
533  bsdf->extra->color,
534  bsdf->alpha_x,
535  bsdf->alpha_y,
536  lcg_state,
537  bsdf->ior,
538  use_fresnel,
539  bsdf->extra->cspec0);
540  *omega_in = X * localO.x + Y * localO.y + Z * localO.z;
541 
542  /* Ensure that the light direction is on the outside w.r.t. the geometry normal. */
543  if (dot(Ng, *omega_in) <= 0.0f) {
544  *pdf = 0.0f;
545  return LABEL_NONE;
546  }
547 
548  if (is_aniso)
549  *pdf = mf_ggx_aniso_pdf(localI, localO, make_float2(bsdf->alpha_x, bsdf->alpha_y));
550  else
551  *pdf = mf_ggx_pdf(localI, localO, bsdf->alpha_x);
552  *eval *= *pdf;
553 
554 #ifdef __RAY_DIFFERENTIALS__
555  *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
556  *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
557 #endif
558  return LABEL_REFLECT | LABEL_GLOSSY;
559 }
560 
561 /* Multiscattering GGX Glass closure */
562 
564 {
565  bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
566  bsdf->alpha_y = bsdf->alpha_x;
567  bsdf->ior = max(0.0f, bsdf->ior);
568  bsdf->extra->color = saturate(bsdf->extra->color);
569 
571 
573 }
574 
576  ccl_private const ShaderData *sd)
577 {
578  bsdf->alpha_x = clamp(bsdf->alpha_x, 1e-4f, 1.0f);
579  bsdf->alpha_y = bsdf->alpha_x;
580  bsdf->ior = max(0.0f, bsdf->ior);
581  bsdf->extra->color = saturate(bsdf->extra->color);
582  bsdf->extra->cspec0 = saturate(bsdf->extra->cspec0);
583 
585 
587 
589 }
590 
593  const float3 I,
594  const float3 omega_in,
595  ccl_private float *pdf,
596  ccl_private uint *lcg_state)
597 {
598  ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
599 
600  if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
601  *pdf = 0.0f;
602  return make_float3(0.0f, 0.0f, 0.0f);
603  }
604 
605  float3 X, Y, Z;
606  Z = bsdf->N;
607  make_orthonormals(Z, &X, &Y);
608 
609  float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
610  float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
611 
612  *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
613  return mf_eval_glass(localI,
614  localO,
615  false,
616  bsdf->extra->color,
617  bsdf->alpha_x,
618  bsdf->alpha_y,
619  lcg_state,
620  bsdf->ior,
621  false,
622  bsdf->extra->color);
623 }
624 
626  const float3 I,
627  const float3 omega_in,
628  ccl_private float *pdf,
629  ccl_private uint *lcg_state)
630 {
631  ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
632 
633  if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
634  *pdf = 0.0f;
635  return make_float3(0.0f, 0.0f, 0.0f);
636  }
637 
638  bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
639 
640  float3 X, Y, Z;
641  Z = bsdf->N;
642  make_orthonormals(Z, &X, &Y);
643 
644  float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
645  float3 localO = make_float3(dot(omega_in, X), dot(omega_in, Y), dot(omega_in, Z));
646 
647  *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
648  return mf_eval_glass(localI,
649  localO,
650  true,
651  bsdf->extra->color,
652  bsdf->alpha_x,
653  bsdf->alpha_y,
654  lcg_state,
655  bsdf->ior,
656  use_fresnel,
657  bsdf->extra->cspec0);
658 }
659 
661  ccl_private const ShaderClosure *sc,
662  float3 Ng,
663  float3 I,
664  float3 dIdx,
665  float3 dIdy,
666  float randu,
667  float randv,
668  ccl_private float3 *eval,
669  ccl_private float3 *omega_in,
670  ccl_private float3 *domega_in_dx,
671  ccl_private float3 *domega_in_dy,
672  ccl_private float *pdf,
673  ccl_private uint *lcg_state)
674 {
675  ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
676 
677  float3 X, Y, Z;
678  Z = bsdf->N;
679 
680  if (bsdf->alpha_x * bsdf->alpha_y < 1e-7f) {
681  float3 R, T;
682 #ifdef __RAY_DIFFERENTIALS__
683  float3 dRdx, dRdy, dTdx, dTdy;
684 #endif
685  bool inside;
686  float fresnel = fresnel_dielectric(bsdf->ior,
687  Z,
688  I,
689  &R,
690  &T,
692  dIdx,
693  dIdy,
694  &dRdx,
695  &dRdy,
696  &dTdx,
697  &dTdy,
698 #endif
699  &inside);
700 
701  *pdf = 1e6f;
702  *eval = make_float3(1e6f, 1e6f, 1e6f);
703  if (randu < fresnel) {
704  *omega_in = R;
705 #ifdef __RAY_DIFFERENTIALS__
706  *domega_in_dx = dRdx;
707  *domega_in_dy = dRdy;
708 #endif
709  return LABEL_REFLECT | LABEL_SINGULAR;
710  }
711  else {
712  *omega_in = T;
713 #ifdef __RAY_DIFFERENTIALS__
714  *domega_in_dx = dTdx;
715  *domega_in_dy = dTdy;
716 #endif
718  }
719  }
720 
721  bool use_fresnel = (bsdf->type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID);
722 
723  make_orthonormals(Z, &X, &Y);
724 
725  float3 localI = make_float3(dot(I, X), dot(I, Y), dot(I, Z));
726  float3 localO;
727 
728  *eval = mf_sample_glass(localI,
729  &localO,
730  bsdf->extra->color,
731  bsdf->alpha_x,
732  bsdf->alpha_y,
733  lcg_state,
734  bsdf->ior,
735  use_fresnel,
736  bsdf->extra->cspec0);
737  *pdf = mf_glass_pdf(localI, localO, bsdf->alpha_x, bsdf->ior);
738  *eval *= *pdf;
739 
740  *omega_in = X * localO.x + Y * localO.y + Z * localO.z;
741  if (localO.z * localI.z > 0.0f) {
742 #ifdef __RAY_DIFFERENTIALS__
743  *domega_in_dx = (2 * dot(Z, dIdx)) * Z - dIdx;
744  *domega_in_dy = (2 * dot(Z, dIdy)) * Z - dIdy;
745 #endif
746  return LABEL_REFLECT | LABEL_GLOSSY;
747  }
748  else {
749 #ifdef __RAY_DIFFERENTIALS__
750  float cosI = dot(Z, I);
751  float dnp = max(sqrtf(1.0f - (bsdf->ior * bsdf->ior * (1.0f - cosI * cosI))), 1e-7f);
752  *domega_in_dx = -(bsdf->ior * dIdx) +
753  ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdx, Z)) * Z;
754  *domega_in_dy = -(bsdf->ior * dIdy) +
755  ((bsdf->ior - bsdf->ior * bsdf->ior * cosI / dnp) * dot(dIdy, Z)) * Z;
756 #endif
757 
758  return LABEL_TRANSMIT | LABEL_GLOSSY;
759  }
760 }
761 
MINLINE float safe_sqrtf(float a)
unsigned int uint
Definition: BLI_sys_types.h:67
_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 Z
Definition: GeomUtils.cpp:201
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color or the default fallback if none is specified Separate Split a vector into its X
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a or normal between and object coordinate space Combine Create a color from its and value channels Color Retrieve a color or the default fallback if none is specified Separate Split a vector into its Y
#define U
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define A
ccl_device_forceinline void bsdf_microfacet_fresnel_color(ccl_private const ShaderData *sd, ccl_private MicrofacetBsdf *bsdf)
ccl_device int bsdf_microfacet_multi_ggx_common_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_reflect(ccl_private const ShaderClosure *sc, const float3 I, const float3 omega_in, ccl_private float *pdf, ccl_private uint *lcg_state)
ccl_device void bsdf_microfacet_multi_ggx_blur(ccl_private ShaderClosure *sc, float roughness)
ccl_device_forceinline float3 mf_eval_phase_glossy(const float3 w, const float lambda, const float3 wo, const float2 alpha)
ccl_device_forceinline float D_ggx_aniso(const float3 wm, const float2 alpha)
ccl_device_forceinline float mf_C1(const float h)
ccl_device_forceinline float3 mf_sample_phase_glass(const float3 wi, const float eta, const float3 wm, const float randV, ccl_private bool *outside)
ccl_device float3 bsdf_microfacet_multi_ggx_eval_reflect(ccl_private const ShaderClosure *sc, const float3 I, const float3 omega_in, ccl_private float *pdf, ccl_private uint *lcg_state)
ccl_device_forceinline bool mf_sample_height(const float3 w, ccl_private float *h, ccl_private float *C1, ccl_private float *G1, ccl_private float *lambda, const float U)
ccl_device_forceinline float mf_lambda(const float3 w, const float2 alpha)
ccl_device_forceinline float mf_invC1(const float h)
ccl_device int bsdf_microfacet_multi_ggx_glass_fresnel_setup(ccl_private MicrofacetBsdf *bsdf, ccl_private const ShaderData *sd)
ccl_device int bsdf_microfacet_multi_ggx_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device float3 bsdf_microfacet_multi_ggx_eval_transmit(ccl_private const ShaderClosure *sc, const float3 I, const float3 omega_in, ccl_private float *pdf, ccl_private uint *lcg_state)
ccl_device float3 bsdf_microfacet_multi_ggx_glass_eval_transmit(ccl_private const ShaderClosure *sc, const float3 I, const float3 omega_in, ccl_private float *pdf, ccl_private uint *lcg_state)
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_glass_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device_forceinline float mf_ggx_aniso_pdf(const float3 wi, const float3 wo, const float2 alpha)
ccl_device int bsdf_microfacet_multi_ggx_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
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_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_inline float mf_ggx_transmission_albedo(float a, float ior)
ccl_device int bsdf_microfacet_multi_ggx_glass_sample(KernelGlobals kg, ccl_private const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, ccl_private float3 *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, ccl_private float *pdf, ccl_private uint *lcg_state)
ccl_device_forceinline float mf_G1(const float3 w, const float C1, const float lambda)
ccl_device int bsdf_microfacet_multi_ggx_fresnel_setup(ccl_private MicrofacetBsdf *bsdf, ccl_private const ShaderData *sd)
ccl_device int bsdf_microfacet_multi_ggx_sample(KernelGlobals kg, ccl_private const ShaderClosure *sc, float3 Ng, float3 I, float3 dIdx, float3 dIdy, float randu, float randv, ccl_private float3 *eval, ccl_private float3 *omega_in, ccl_private float3 *domega_in_dx, ccl_private float3 *domega_in_dy, ccl_private float *pdf, ccl_private uint *lcg_state)
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_forceinline float3 mf_sample_phase_glossy(const float3 wi, ccl_private float3 *weight, const float3 wm)
ccl_device float fresnel_dielectric_cos(float cosi, float eta)
Definition: bsdf_util.h:79
CCL_NAMESPACE_BEGIN ccl_device float fresnel_dielectric(float eta, const float3 N, const float3 I, ccl_private float3 *R, ccl_private float3 *T, ccl_private bool *is_inside)
Definition: bsdf_util.h:13
unsigned int U
Definition: btGjkEpa3.h:78
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition: btQuadWord.h:119
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#define ccl_device_forceinline
Definition: cuda/compat.h:35
#define sinf(x)
Definition: cuda/compat.h:102
#define cosf(x)
Definition: cuda/compat.h:101
#define ccl_device
Definition: cuda/compat.h:32
#define expf(x)
Definition: cuda/compat.h:106
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_inline
Definition: cuda/compat.h:34
#define powf(x, y)
Definition: cuda/compat.h:103
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
const KernelGlobalsCPU *ccl_restrict KernelGlobals
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_FRESNEL_ID
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID
@ SD_BSDF_HAS_EVAL
Definition: kernel/types.h:744
@ SD_BSDF_NEEDS_LCG
Definition: kernel/types.h:756
@ SD_BSDF
Definition: kernel/types.h:742
ShaderData
Definition: kernel/types.h:925
#define __RAY_DIFFERENTIALS__
Definition: kernel/types.h:62
@ LABEL_TRANSMIT
Definition: kernel/types.h:317
@ LABEL_NONE
Definition: kernel/types.h:316
@ LABEL_SINGULAR
Definition: kernel/types.h:321
@ LABEL_GLOSSY
Definition: kernel/types.h:320
@ LABEL_REFLECT
Definition: kernel/types.h:318
ShaderClosure
Definition: kernel/types.h:726
ccl_device_inline float2 safe_normalize(const float2 &a)
Definition: math_float2.h:201
ccl_device_inline float2 normalize_len(const float2 &a, float *t)
ccl_device_inline float3 saturate(float3 a)
Definition: math_float3.h:387
#define T
#define R
#define fmaxf(x, y)
Definition: metal/compat.h:228
#define make_float2(x, y)
Definition: metal/compat.h:203
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
#define make_float3(x, y, z)
Definition: metal/compat.h:204
bool isfinite(uchar)
Definition: scene/image.cpp:31
static unsigned a[3]
Definition: RandGen.cpp:78
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
T clamp(const T &a, const T &min, const T &max)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
bool is_zero(const T &a)
static const pxr::TfToken ior("ior", pxr::TfToken::Immortal)
static const pxr::TfToken roughness("roughness", pxr::TfToken::Immortal)
#define I
ccl_device void make_orthonormals_tangent(const float3 N, const float3 T, ccl_private float3 *a, ccl_private float3 *b)
float x
Definition: types_float2.h:15
float y
Definition: types_float2.h:15
float z
float y
float x
float max
#define M_2PI_F
Definition: util/math.h:60
ccl_device_inline float saturatef(float a)
Definition: util/math.h:404
#define M_1_PI_F
Definition: util/math.h:43
#define M_PI_F
Definition: util/math.h:34
ccl_device_inline void make_orthonormals(const float3 N, ccl_private float3 *a, ccl_private float3 *b)
Definition: util/math.h:566
BLI_INLINE float D(const float *data, const int res[3], int x, int y, int z)
Definition: voxel.c:13