Blender V4.3
bsdf_microfacet.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
2 * SPDX-FileCopyrightText: 2011-2022 Blender Foundation
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Adapted code from Open Shading Language. */
7
8#pragma once
9
11
13
15
17
22
24 NONE = 0,
26 DIELECTRIC_TINT, /* used by the OSL MaterialX closures */
30};
31
32typedef struct FresnelThinFilm {
33 float thickness;
34 float ior;
36
43
47
50
53 /* Reflectivity at perpendicular (F0) and glancing (F90) angles. */
55 /* Negative exponent signals a special case where the real Fresnel is remapped to F0...F90. */
56 float exponent;
58
59typedef struct FresnelF82Tint {
60 /* Perpendicular reflectivity. */
62 /* Precomputed (1-cos)^6 factor for edge tint. */
65
66typedef struct MicrofacetBsdf {
68
70
71 /* Used to account for missing energy due to the single-scattering microfacet model.
72 * This could be included in bsdf->weight as well, but there it would mess up the color
73 * channels.
74 * Note that this is currently only used by GGX. */
76
77 /* Fresnel model to apply, as well as the extra data for it.
78 * For NONE and DIELECTRIC, no extra storage is needed, so the pointer is NULL for them. */
81
84
85static_assert(sizeof(ShaderClosure) >= sizeof(MicrofacetBsdf), "MicrofacetBsdf is too large!");
86
87/* Beckmann VNDF importance sampling algorithm from:
88 * Importance Sampling Microfacet-Based BSDFs using the Distribution of Visible Normals.
89 * Eric Heitz and Eugene d'Eon, EGSR 2014.
90 * https://hal.inria.fr/hal-00996995v2/document */
91
93 const float alpha_x,
94 const float alpha_y,
95 const float2 rand)
96{
97 /* 1. stretch wi */
98 float3 wi_ = make_float3(alpha_x * wi.x, alpha_y * wi.y, wi.z);
99 wi_ = normalize(wi_);
100
101 /* 2. sample P22_{wi}(x_slope, y_slope, 1, 1) */
102 float slope_x, slope_y;
103 float cos_phi_i = 1.0f;
104 float sin_phi_i = 0.0f;
105
106 if (wi_.z >= 0.99999f) {
107 /* Special case (normal incidence). */
108 const float r = sqrtf(-logf(rand.x));
109 const float phi = M_2PI_F * rand.y;
110 slope_x = r * cosf(phi);
111 slope_y = r * sinf(phi);
112 }
113 else {
114 /* Precomputations. */
115 const float cos_theta_i = wi_.z;
116 const float sin_theta_i = sin_from_cos(cos_theta_i);
117 const float tan_theta_i = sin_theta_i / cos_theta_i;
118 const float cot_theta_i = 1.0f / tan_theta_i;
119 const float erf_a = fast_erff(cot_theta_i);
120 const float exp_a2 = expf(-cot_theta_i * cot_theta_i);
121 const float SQRT_PI_INV = 0.56418958354f;
122
123 float invlen = 1.0f / sin_theta_i;
124 cos_phi_i = wi_.x * invlen;
125 sin_phi_i = wi_.y * invlen;
126
127 /* Based on paper from Wenzel Jakob
128 * An Improved Visible Normal Sampling Routine for the Beckmann Distribution
129 *
130 * http://www.mitsuba-renderer.org/~wenzel/files/visnormal.pdf
131 *
132 * Reformulation from OpenShadingLanguage which avoids using inverse
133 * trigonometric functions.
134 */
135
136 /* Sample slope X.
137 *
138 * Compute a coarse approximation using the approximation:
139 * `exp(-ierf(x)^2) ~= 1 - x * x`
140 * `solve y = 1 + b + K * (1 - b * b)`
141 */
142 const float K = tan_theta_i * SQRT_PI_INV;
143 const float y_approx = rand.x * (1.0f + erf_a + K * (1 - erf_a * erf_a));
144 const float y_exact = rand.x * (1.0f + erf_a + K * exp_a2);
145 float b = K > 0 ? (0.5f - sqrtf(K * (K - y_approx + 1.0f) + 0.25f)) / K : y_approx - 1.0f;
146
147 float inv_erf = fast_ierff(b);
148 float2 begin = make_float2(-1.0f, -y_exact);
149 float2 end = make_float2(erf_a, 1.0f + erf_a + K * exp_a2 - y_exact);
150 float2 current = make_float2(b, 1.0f + b + K * expf(-sqr(inv_erf)) - y_exact);
151
152 /* Find root in a monotonic interval using newton method, under given precision and maximal
153 * iterations. Falls back to bisection if newton step produces results outside of the valid
154 * interval. */
155 const float precision = 1e-6f;
156 const int max_iter = 3;
157 int iter = 0;
158 while (fabsf(current.y) > precision && iter++ < max_iter) {
159 if (signf(begin.y) == signf(current.y)) {
160 begin.x = current.x;
161 begin.y = current.y;
162 }
163 else {
164 end.x = current.x;
165 }
166 const float newton_x = current.x - current.y / (1.0f - inv_erf * tan_theta_i);
167 current.x = (newton_x >= begin.x && newton_x <= end.x) ? newton_x : 0.5f * (begin.x + end.x);
168 inv_erf = fast_ierff(current.x);
169 current.y = 1.0f + current.x + K * expf(-sqr(inv_erf)) - y_exact;
170 }
171
172 slope_x = inv_erf;
173 slope_y = fast_ierff(2.0f * rand.y - 1.0f);
174 }
175
176 /* 3. rotate */
177 float tmp = cos_phi_i * slope_x - sin_phi_i * slope_y;
178 slope_y = sin_phi_i * slope_x + cos_phi_i * slope_y;
179 slope_x = tmp;
180
181 /* 4. unstretch */
182 slope_x = alpha_x * slope_x;
183 slope_y = alpha_y * slope_y;
184
185 /* 5. compute normal */
186 return normalize(make_float3(-slope_x, -slope_y, 1.0f));
187}
188
189/* GGX VNDF importance sampling algorithm from:
190 * Sampling the GGX Distribution of Visible Normals.
191 * Eric Heitz, JCGT Vol. 7, No. 4, 2018.
192 * https://jcgt.org/published/0007/04/01/ */
194 const float alpha_x,
195 const float alpha_y,
196 const float2 rand)
197{
198 /* Section 3.2: Transforming the view direction to the hemisphere configuration. */
199 float3 wi_ = normalize(make_float3(alpha_x * wi.x, alpha_y * wi.y, wi.z));
200
201 /* Section 4.1: Orthonormal basis. */
202 float lensq = sqr(wi_.x) + sqr(wi_.y);
203 float3 T1, T2;
204 if (lensq > 1e-7f) {
205 T1 = make_float3(-wi_.y, wi_.x, 0.0f) * inversesqrtf(lensq);
206 T2 = cross(wi_, T1);
207 }
208 else {
209 /* Normal incidence, any basis is fine. */
210 T1 = make_float3(1.0f, 0.0f, 0.0f);
211 T2 = make_float3(0.0f, 1.0f, 0.0f);
212 }
213
214 /* Section 4.2: Parameterization of the projected area. */
215 float2 t = sample_uniform_disk(rand);
216 t.y = mix(safe_sqrtf(1.0f - sqr(t.x)), t.y, 0.5f * (1.0f + wi_.z));
217
218 /* Section 4.3: Reprojection onto hemisphere. */
219 float3 H_ = t.x * T1 + t.y * T2 + safe_sqrtf(1.0f - len_squared(t)) * wi_;
220
221 /* Section 3.4: Transforming the normal back to the ellipsoid configuration. */
222 return normalize(make_float3(alpha_x * H_.x, alpha_y * H_.y, max(0.0f, H_.z)));
223}
224
225/* Computes the Fresnel reflectance and transmittance given the Microfacet BSDF and the cosine of
226 * the incoming angle `cos_theta_i`.
227 * Also returns the cosine of the angle between the normal and the refracted ray as `r_cos_theta_t`
228 * if provided. */
230 ccl_private const MicrofacetBsdf *bsdf,
231 const float cos_theta_i,
232 ccl_private float *r_cos_theta_t,
233 ccl_private Spectrum *r_reflectance,
234 ccl_private Spectrum *r_transmittance)
235{
236 /* Whether the closure has reflective or transmissive lobes. */
237 const bool has_reflection = !CLOSURE_IS_REFRACTION(bsdf->type);
238 const bool has_transmission = CLOSURE_IS_GLASS(bsdf->type) || !has_reflection;
239
240 if (bsdf->fresnel_type == MicrofacetFresnel::DIELECTRIC) {
241 const Spectrum F = make_spectrum(fresnel_dielectric(cos_theta_i, bsdf->ior, r_cos_theta_t));
242 *r_reflectance = F;
243 *r_transmittance = one_spectrum() - F;
244 }
245 else if (bsdf->fresnel_type == MicrofacetFresnel::DIELECTRIC_TINT) {
247 bsdf->fresnel;
248 const float F = fresnel_dielectric(cos_theta_i, bsdf->ior, r_cos_theta_t);
249 *r_reflectance = F * fresnel->reflection_tint;
250 *r_transmittance = (1.0f - F) * fresnel->transmission_tint;
251 }
252 else if (bsdf->fresnel_type == MicrofacetFresnel::CONDUCTOR) {
253 ccl_private FresnelConductor *fresnel = (ccl_private FresnelConductor *)bsdf->fresnel;
254 *r_reflectance = fresnel_conductor(cos_theta_i, fresnel->n, fresnel->k);
255 *r_transmittance = zero_spectrum();
256 }
257 else if (bsdf->fresnel_type == MicrofacetFresnel::F82_TINT) {
258 /* F82-Tint model, described in "Novel aspects of the Adobe Standard Material" by Kutz et al.
259 * Essentially, this is the usual Schlick Fresnel with an additional cosI*(1-cosI)^6
260 * term which modulates the reflectivity around acos(1/7) degrees (ca. 82°). */
261 ccl_private FresnelF82Tint *fresnel = (ccl_private FresnelF82Tint *)bsdf->fresnel;
262 const float mu = saturatef(1.0f - cos_theta_i);
263 const float mu5 = sqr(sqr(mu)) * mu;
264 const Spectrum F_schlick = mix(fresnel->f0, one_spectrum(), mu5);
265 *r_reflectance = saturate(F_schlick - fresnel->b * cos_theta_i * mu5 * mu);
266 *r_transmittance = zero_spectrum();
267 }
268 else if (bsdf->fresnel_type == MicrofacetFresnel::GENERALIZED_SCHLICK) {
270 bsdf->fresnel;
271 Spectrum F;
272 if (fresnel->thin_film.thickness > 0.1f) {
273 /* Iridescence doesn't combine well with the general case. We only expose it through the
274 * Principled BSDF for now, so it's fine to not support custom exponents and F90. */
275 kernel_assert(fresnel->exponent < 0.0f);
276 kernel_assert(fresnel->f90 == one_spectrum());
277 F = fresnel_iridescence(kg,
278 1.0f,
279 fresnel->thin_film.ior,
280 bsdf->ior,
281 cos_theta_i,
282 fresnel->thin_film.thickness,
283 r_cos_theta_t);
284 /* Apply F0 scaling (here per-channel, since iridescence produces colored output).
285 * Note that the usual approach (as used below) cannot be used here, since F may be below
286 * F0_real. Therefore, use a different approach: Scale the result by (F0 / F0_real), with
287 * the strength of the scaling depending on how close F is to F0_real.
288 * There isn't one single "correct" way to do this, it's just for artistic control anyways.
289 */
290 const float F0_real = F0_from_ior(bsdf->ior);
291 if (F0_real > 1e-5f && !isequal(F, one_spectrum())) {
293 const float s = saturatef(inverse_lerp(1.0f, F0_real, GET_SPECTRUM_CHANNEL(F, i)));
294 const float factor = GET_SPECTRUM_CHANNEL(fresnel->f0, i) / F0_real;
295 GET_SPECTRUM_CHANNEL(F, i) *= mix(1.0f, factor, s);
296 }
297 }
298 }
299 else if (fresnel->exponent < 0.0f) {
300 /* Special case: Use real Fresnel curve to determine the interpolation between F0 and F90.
301 * Used by Principled BSDF. */
302 const float F_real = fresnel_dielectric(cos_theta_i, bsdf->ior, r_cos_theta_t);
303 const float F0_real = F0_from_ior(bsdf->ior);
304 const float s = saturatef(inverse_lerp(F0_real, 1.0f, F_real));
305 F = mix(fresnel->f0, fresnel->f90, s);
306 }
307 else {
308 /* Regular case: Generalized Schlick term. */
309 const float cos_theta_t_sq = 1.0f - (1.0f - sqr(cos_theta_i)) / sqr(bsdf->ior);
310 if (cos_theta_t_sq <= 0.0f) {
311 /* Total internal reflection */
312 *r_reflectance = fresnel->reflection_tint * (float)has_reflection;
313 *r_transmittance = zero_spectrum();
314 return;
315 }
316 const float cos_theta_t = sqrtf(cos_theta_t_sq);
317 if (r_cos_theta_t) {
318 *r_cos_theta_t = cos_theta_t;
319 }
320
321 /* TODO(lukas): Is a special case for exponent==5 worth it? */
322 /* When going from a higher to a lower IOR, we must use the transmitted angle. */
323 const float fresnel_angle = ((bsdf->ior < 1.0f) ? cos_theta_t : cos_theta_i);
324 const float s = powf(1.0f - fresnel_angle, fresnel->exponent);
325 F = mix(fresnel->f0, fresnel->f90, s);
326 }
327 *r_reflectance = F * fresnel->reflection_tint;
328 *r_transmittance = (one_spectrum() - F) * fresnel->transmission_tint;
329 }
330 else {
331 kernel_assert(bsdf->fresnel_type == MicrofacetFresnel::NONE);
332 /* No Fresnel used, this is either purely reflective or purely refractive closure. */
333 *r_reflectance = *r_transmittance = one_spectrum();
334
335 /* Exclude total internal reflection. */
336 if (has_transmission && fresnel_dielectric(cos_theta_i, bsdf->ior, r_cos_theta_t) == 1.0f) {
337 *r_transmittance = zero_spectrum();
338 }
339 }
340
341 *r_reflectance *= (float)has_reflection;
342 *r_transmittance *= (float)has_transmission;
343}
344
347 ccl_private const ShaderData *sd,
348 const Spectrum Fss)
349{
350 const float mu = dot(sd->wi, bsdf->N);
351 const float rough = sqrtf(sqrtf(bsdf->alpha_x * bsdf->alpha_y));
352
353 float E, E_avg;
354 if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_ID) {
355 E = lookup_table_read_2D(kg, rough, mu, kernel_data.tables.ggx_E, 32, 32);
356 E_avg = lookup_table_read(kg, rough, kernel_data.tables.ggx_Eavg, 32);
357 }
358 else if (bsdf->type == CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID) {
359 int ofs = kernel_data.tables.ggx_glass_E;
360 int avg_ofs = kernel_data.tables.ggx_glass_Eavg;
361 float ior = bsdf->ior;
362 if (ior < 1.0f) {
363 ior = 1.0f / ior;
364 ofs = kernel_data.tables.ggx_glass_inv_E;
365 avg_ofs = kernel_data.tables.ggx_glass_inv_Eavg;
366 }
367 /* TODO: Bias mu towards more precision for low values. */
368 float z = sqrtf(fabsf((ior - 1.0f) / (ior + 1.0f)));
369 E = lookup_table_read_3D(kg, rough, mu, z, ofs, 16, 16, 16);
370 E_avg = lookup_table_read_2D(kg, rough, z, avg_ofs, 16, 16);
371 }
372 else {
373 kernel_assert(false);
374 E = 1.0f;
375 E_avg = 1.0f;
376 }
377
378 const float missing_factor = ((1.0f - E) / E);
379 bsdf->energy_scale = 1.0f + missing_factor;
380
381 /* Check if we need to account for extra darkening/saturation due to multi-bounce Fresnel. */
382 if (!isequal(Fss, one_spectrum())) {
383 /* Fms here is based on the appendix of "Revisiting Physically Based Shading at Imageworks"
384 * by Christopher Kulla and Alejandro Conty,
385 * with one Fss cancelled out since this is just a multiplier on top of
386 * the single-scattering BSDF, which already contains one bounce of Fresnel. */
387 const Spectrum Fms = Fss * E_avg / (one_spectrum() - Fss * (1.0f - E_avg));
388 /* Since we already include the energy compensation in bsdf->energy_scale,
389 * this term is what's needed to make the full BSDF * weight * energy_scale
390 * computation work out to the correct value. */
391 const Spectrum darkening = (one_spectrum() + Fms * missing_factor) / bsdf->energy_scale;
392 bsdf->weight *= darkening;
393 bsdf->sample_weight *= average(darkening);
394 }
395}
396
397/* This function estimates the albedo of the BSDF (NOT including the bsdf->weight) as caused by
398 * the applied Fresnel model for the given view direction.
399 * The base microfacet model is assumed to have an albedo of 1 (we have the energy preservation
400 * code for that), but e.g. a reflection-only closure with Fresnel applied can end up having
401 * a very low overall albedo.
402 * This is used to adjust the sample weight, as well as for the Diff/Gloss/Trans Color pass
403 * and the Denoising Albedo pass.
404 *
405 * TODO: The Schlick LUT seems to assume energy preservation, which is not true for GGX. if
406 * energy-preserving then transmission should just be `1 - reflection`. For dielectric we could
407 * probably split the LUT for multiGGX if smooth assumption is not good enough. */
409 ccl_private const ShaderData *sd,
410 ccl_private const MicrofacetBsdf *bsdf,
411 const bool eval_reflection,
412 const bool eval_transmission)
413{
414 const float cos_NI = dot(sd->wi, bsdf->N);
415 Spectrum reflectance, transmittance;
416 microfacet_fresnel(kg, bsdf, cos_NI, nullptr, &reflectance, &transmittance);
417
418 reflectance *= (float)eval_reflection;
419 transmittance *= (float)eval_transmission;
420
421 /* Use lookup tables for generalized Schlick reflection, otherwise assume smooth surface. */
422 if (!is_zero(reflectance) && bsdf->fresnel_type == MicrofacetFresnel::GENERALIZED_SCHLICK) {
424 bsdf->fresnel;
425
426 if (fresnel->thin_film.thickness > 0.1f) {
427 /* Precomputing LUTs for thin-film iridescence isn't viable, so fall back to the specular
428 * reflection approximation from the microfacet_fresnel call above in that case. */
429 }
430 else {
431 float rough = sqrtf(sqrtf(bsdf->alpha_x * bsdf->alpha_y));
432 float s;
433 if (fresnel->exponent < 0.0f) {
434 float z = sqrtf(fabsf((bsdf->ior - 1.0f) / (bsdf->ior + 1.0f)));
436 kg, rough, cos_NI, z, kernel_data.tables.ggx_gen_schlick_ior_s, 16, 16, 16);
437 }
438 else {
439 float z = 1.0f / (0.2f * fresnel->exponent + 1.0f);
441 kg, rough, cos_NI, z, kernel_data.tables.ggx_gen_schlick_s, 16, 16, 16);
442 }
443 reflectance = mix(fresnel->f0, fresnel->f90, s) * fresnel->reflection_tint;
444 }
445 }
446 else if (bsdf->fresnel_type == MicrofacetFresnel::F82_TINT) {
447 ccl_private FresnelF82Tint *fresnel = (ccl_private FresnelF82Tint *)bsdf->fresnel;
448 float rough = sqrtf(sqrtf(bsdf->alpha_x * bsdf->alpha_y));
449 const float s = lookup_table_read_3D(
450 kg, rough, cos_NI, 0.5f, kernel_data.tables.ggx_gen_schlick_s, 16, 16, 16);
451 /* TODO: Precompute B factor term and account for it here. */
452 reflectance = mix(fresnel->f0, one_spectrum(), s);
453 }
454
455 return reflectance + transmittance;
456}
457
458/* Smith shadowing-masking term, here in the non-separable form.
459 * For details, see:
460 * Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs.
461 * Eric Heitz, JCGT Vol. 3, No. 2, 2014.
462 * https://jcgt.org/published/0003/02/03/ */
463template<MicrofacetType m_type>
465{
467 /* Equation 72. */
468 return 0.5f * (sqrtf(1.0f + sqr_alpha_tan_n) - 1.0f);
469 }
470 else {
472 /* Approximation from below Equation 69. */
473 if (sqr_alpha_tan_n < 0.39f) {
474 /* Equivalent to a >= 1.6f, but also handles sqr_alpha_tan_n == 0.0f cleanly. */
475 return 0.0f;
476 }
477
478 const float a = inversesqrtf(sqr_alpha_tan_n);
479 return ((0.396f * a - 1.259f) * a + 1.0f) / ((2.181f * a + 3.535f) * a);
480 }
481}
482
483template<MicrofacetType m_type> ccl_device_inline float bsdf_lambda(float alpha2, float cos_N)
484{
485 return bsdf_lambda_from_sqr_alpha_tan_n<m_type>(alpha2 * fmaxf(1.0f / sqr(cos_N) - 1.0f, 0.0f));
486}
487
488template<MicrofacetType m_type>
489ccl_device_inline float bsdf_aniso_lambda(float alpha_x, float alpha_y, float3 V)
490{
491 const float sqr_alpha_tan_n = (sqr(alpha_x * V.x) + sqr(alpha_y * V.y)) / sqr(V.z);
492 return bsdf_lambda_from_sqr_alpha_tan_n<m_type>(sqr_alpha_tan_n);
493}
494
495/* Mono-directional shadowing-masking term. */
496template<MicrofacetType m_type> ccl_device_inline float bsdf_G(float alpha2, float cos_N)
497{
498 return 1.0f / (1.0f + bsdf_lambda<m_type>(alpha2, cos_N));
499}
500
501/* Combined shadowing-masking term. */
502template<MicrofacetType m_type>
503ccl_device_inline float bsdf_G(float alpha2, float cos_NI, float cos_NO)
504{
505 return 1.0f / (1.0f + bsdf_lambda<m_type>(alpha2, cos_NI) + bsdf_lambda<m_type>(alpha2, cos_NO));
506}
507
508/* Normal distribution function. */
509template<MicrofacetType m_type> ccl_device_inline float bsdf_D(float alpha2, float cos_NH)
510{
511 const float cos_NH2 = min(sqr(cos_NH), 1.0f);
512 const float one_minus_cos_NH2 = 1.0f - cos_NH2;
513
515 return 1.0f / (expf(one_minus_cos_NH2 / (cos_NH2 * alpha2)) * M_PI_F * alpha2 * sqr(cos_NH2));
516 }
517 else {
519 return alpha2 / (M_PI_F * sqr(one_minus_cos_NH2 + alpha2 * cos_NH2));
520 }
521}
522
523template<MicrofacetType m_type>
524ccl_device_inline float bsdf_aniso_D(float alpha_x, float alpha_y, float3 H)
525{
526 H /= make_float3(alpha_x, alpha_y, 1.0f);
527
528 const float cos_NH2 = sqr(H.z);
529 const float alpha2 = alpha_x * alpha_y;
530
532 return expf(-(sqr(H.x) + sqr(H.y)) / cos_NH2) / (M_PI_F * alpha2 * sqr(cos_NH2));
533 }
534 else {
536 return M_1_PI_F / (alpha2 * sqr(len_squared(H)));
537 }
538}
539
540/* Do not set `SD_BSDF_HAS_EVAL` flag if the squared roughness is below a certain threshold. */
542{
543 return (bsdf->alpha_x * bsdf->alpha_y > BSDF_ROUGHNESS_SQ_THRESH) ? SD_BSDF_HAS_EVAL : 0;
544}
545
546template<MicrofacetType m_type>
548 ccl_private const ShaderClosure *sc,
549 const float3 Ng,
550 const float3 wi,
551 const float3 wo,
552 ccl_private float *pdf)
553{
554 ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
555
556 /* Whether the closure has reflective or transmissive lobes. */
557 const bool has_reflection = !CLOSURE_IS_REFRACTION(bsdf->type);
558 const bool has_transmission = CLOSURE_IS_GLASS(bsdf->type) || !has_reflection;
559
560 const float3 N = bsdf->N;
561 const float cos_NI = dot(N, wi);
562 const float cos_NO = dot(N, wo);
563 const float cos_NgO = dot(Ng, wo);
564
565 const float alpha_x = bsdf->alpha_x;
566 const float alpha_y = bsdf->alpha_y;
567
568 const bool is_transmission = (cos_NO < 0.0f);
569
570 /* Check whether the pair of directions is valid for evaluation:
571 * - Incoming direction has to be in the upper hemisphere (Cycles convention)
572 * - Specular cases can't be evaluated, only sampled.
573 * - The outgoing direction has to be the in the same hemisphere w.r.t. both normals.
574 * - Purely reflective closures can't have refraction.
575 * - Purely refractive closures can't have reflection.
576 */
577 if ((cos_NI <= 0) || !bsdf_microfacet_eval_flag(bsdf) || ((cos_NgO < 0.0f) != is_transmission) ||
578 (is_transmission && !has_transmission) || (!is_transmission && !has_reflection))
579 {
580 return zero_spectrum();
581 }
582
583 /* Compute half vector. */
584 /* TODO: deal with the case when `bsdf->ior` is close to one. */
585 /* TODO: check if the refraction configuration is valid. See `btdf_ggx()` in
586 * `eevee_bxdf_lib.glsl`. */
587 float3 H = is_transmission ? -(bsdf->ior * wo + wi) : (wi + wo);
588 const float inv_len_H = safe_divide(1.0f, len(H));
589 H *= inv_len_H;
590
591 /* Compute Fresnel coefficients. */
592 const float cos_HI = dot(H, wi);
593 Spectrum reflectance, transmittance;
594 microfacet_fresnel(kg, bsdf, cos_HI, nullptr, &reflectance, &transmittance);
595
596 if (is_zero(reflectance) && is_zero(transmittance)) {
597 return zero_spectrum();
598 }
599
600 const float cos_NH = dot(N, H);
601 float D, lambdaI, lambdaO;
602
603 /* NOTE: we could add support for anisotropic transmission, although it will make dispersion
604 * harder to compute. */
605 if (alpha_x == alpha_y || is_transmission) { /* Isotropic. */
606 float alpha2 = alpha_x * alpha_y;
607 D = bsdf_D<m_type>(alpha2, cos_NH);
608 lambdaI = bsdf_lambda<m_type>(alpha2, cos_NI);
609 lambdaO = bsdf_lambda<m_type>(alpha2, cos_NO);
610 }
611 else { /* Anisotropic. */
612 float3 X, Y;
613 make_orthonormals_tangent(N, bsdf->T, &X, &Y);
614
615 const float3 local_H = make_float3(dot(X, H), dot(Y, H), cos_NH);
616 const float3 local_I = make_float3(dot(X, wi), dot(Y, wi), cos_NI);
617 const float3 local_O = make_float3(dot(X, wo), dot(Y, wo), cos_NO);
618
619 D = bsdf_aniso_D<m_type>(alpha_x, alpha_y, local_H);
620
621 lambdaI = bsdf_aniso_lambda<m_type>(alpha_x, alpha_y, local_I);
622 lambdaO = bsdf_aniso_lambda<m_type>(alpha_x, alpha_y, local_O);
623 }
624
625 float common = D / cos_NI *
626 (is_transmission ? sqr(bsdf->ior * inv_len_H) * fabsf(cos_HI * dot(H, wo)) :
627 0.25f);
628
629 const float pdf_reflect = average(reflectance) / average(reflectance + transmittance);
630 const float lobe_pdf = is_transmission ? 1.0f - pdf_reflect : pdf_reflect;
631
632 *pdf = common * lobe_pdf / (1.0f + lambdaI);
633 return (is_transmission ? transmittance : reflectance) * common / (1.0f + lambdaO + lambdaI);
634}
635
636template<MicrofacetType m_type>
638 ccl_private const ShaderClosure *sc,
639 float3 Ng,
640 float3 wi,
641 const float3 rand,
642 ccl_private Spectrum *eval,
644 ccl_private float *pdf,
645 ccl_private float2 *sampled_roughness,
646 ccl_private float *eta)
647{
648 ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
649
650 const float3 N = bsdf->N;
651 const float cos_NI = dot(N, wi);
652 if (cos_NI <= 0) {
653 /* Incident angle from the lower hemisphere is invalid. */
654 return LABEL_NONE;
655 }
656
657 const float m_eta = bsdf->ior;
658 const float m_inv_eta = 1.0f / bsdf->ior;
659 const float alpha_x = bsdf->alpha_x;
660 const float alpha_y = bsdf->alpha_y;
661 bool m_singular = !bsdf_microfacet_eval_flag(bsdf);
662
663 /* Half vector. */
664 float3 H;
665 /* Needed for anisotropic microfacets later. */
666 float3 local_H, local_I;
667 if (m_singular) {
668 H = N;
669 }
670 else {
671 float3 X, Y;
672 if (alpha_x == alpha_y) {
673 make_orthonormals(N, &X, &Y);
674 }
675 else {
676 make_orthonormals_tangent(N, bsdf->T, &X, &Y);
677 }
678
679 /* Importance sampling with distribution of visible normals. Vectors are transformed to local
680 * space before and after sampling. */
681 local_I = make_float3(dot(X, wi), dot(Y, wi), cos_NI);
683 local_H = microfacet_ggx_sample_vndf(local_I, alpha_x, alpha_y, float3_to_float2(rand));
684 }
685 else {
686 /* m_type == MicrofacetType::BECKMANN */
687 local_H = microfacet_beckmann_sample_vndf(local_I, alpha_x, alpha_y, float3_to_float2(rand));
688 }
689
690 H = X * local_H.x + Y * local_H.y + N * local_H.z;
691 }
692 const float cos_HI = dot(H, wi);
693
694 /* The angle between the half vector and the refracted ray. Not used when sampling reflection. */
695 float cos_HO;
696 /* Compute Fresnel coefficients. */
697 Spectrum reflectance, transmittance;
698 microfacet_fresnel(kg, bsdf, cos_HI, &cos_HO, &reflectance, &transmittance);
699
700 if (is_zero(reflectance) && is_zero(transmittance)) {
701 return LABEL_NONE;
702 }
703
704 /* Decide between refraction and reflection based on the energy. */
705 const float pdf_reflect = average(reflectance) / average(reflectance + transmittance);
706 const bool do_refract = (rand.z >= pdf_reflect);
707
708 /* Compute actual reflected or refracted direction. */
709 *wo = do_refract ? refract_angle(wi, H, cos_HO, m_inv_eta) : 2.0f * cos_HI * H - wi;
710 if ((dot(Ng, *wo) < 0) != do_refract) {
711 return LABEL_NONE;
712 }
713
714 if (do_refract) {
715 *eval = transmittance;
716 *pdf = 1.0f - pdf_reflect;
717 /* If the IOR is close enough to 1.0, just treat the interaction as specular. */
718 m_singular = m_singular || (fabsf(m_eta - 1.0f) < 1e-4f);
719 }
720 else {
721 *eval = reflectance;
722 *pdf = pdf_reflect;
723 }
724
725 if (m_singular) {
726 /* Some high number for MIS. */
727 *pdf *= 1e6f;
728 *eval *= 1e6f;
729 }
730 else {
731 float D, lambdaI, lambdaO;
732
733 /* TODO: add support for anisotropic transmission. */
734 if (alpha_x == alpha_y || do_refract) { /* Isotropic. */
735 float alpha2 = alpha_x * alpha_y;
736 const float cos_NH = local_H.z;
737 const float cos_NO = dot(N, *wo);
738
739 D = bsdf_D<m_type>(alpha2, cos_NH);
740 lambdaO = bsdf_lambda<m_type>(alpha2, cos_NO);
741 lambdaI = bsdf_lambda<m_type>(alpha2, cos_NI);
742 }
743 else { /* Anisotropic. */
744 const float3 local_O = 2.0f * cos_HI * local_H - local_I;
745
746 D = bsdf_aniso_D<m_type>(alpha_x, alpha_y, local_H);
747
748 lambdaO = bsdf_aniso_lambda<m_type>(alpha_x, alpha_y, local_O);
749 lambdaI = bsdf_aniso_lambda<m_type>(alpha_x, alpha_y, local_I);
750 }
751
752 const float common = D / cos_NI *
753 (do_refract ? fabsf(cos_HI * cos_HO) / sqr(cos_HO + cos_HI * m_inv_eta) :
754 0.25f);
755
756 *pdf *= common / (1.0f + lambdaI);
757 *eval *= common / (1.0f + lambdaI + lambdaO);
758 }
759
760 *sampled_roughness = make_float2(alpha_x, alpha_y);
761 *eta = do_refract ? m_eta : 1.0f;
762
763 return (do_refract ? LABEL_TRANSMIT : LABEL_REFLECT) |
764 (m_singular ? LABEL_SINGULAR : LABEL_GLOSSY);
765}
766
767/* Fresnel term setup functions. These get called after the distribution-specific setup functions
768 * like bsdf_microfacet_ggx_setup. */
769
772 ccl_private const ShaderData *sd,
774 const bool preserve_energy)
775{
776 bsdf->fresnel_type = MicrofacetFresnel::CONDUCTOR;
777 bsdf->fresnel = fresnel;
778 bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
779
780 if (preserve_energy) {
781 /* In order to estimate Fss of the conductor, we fit the F82-tint model to it based on the
782 * value at 0° and ~82° and then use the analytic expression for its Fss. */
783 Spectrum F0 = fresnel_conductor(1.0f, fresnel->n, fresnel->k);
784 Spectrum F82 = fresnel_conductor(1.0f / 7.0f, fresnel->n, fresnel->k);
785 /* 0.46266436f is (1 - 1/7)^5, 17.651384f is 1/(1/7 * (1 - 1/7)^6) */
786 Spectrum B = (mix(F0, one_spectrum(), 0.46266436f) - F82) * 17.651384f;
787 Spectrum Fss = saturate(mix(F0, one_spectrum(), 1.0f / 21.0f) - B * (1.0f / 126.0f));
788 microfacet_ggx_preserve_energy(kg, bsdf, sd, Fss);
789 }
790}
791
793 KernelGlobals kg,
795 ccl_private const ShaderData *sd,
797 const bool preserve_energy)
798{
799 bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC_TINT;
800 bsdf->fresnel = fresnel;
801 bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
802
803 if (preserve_energy) {
804 /* Assume that the transmissive tint makes up most of the overall color. */
805 microfacet_ggx_preserve_energy(kg, bsdf, sd, fresnel->transmission_tint);
806 }
807}
808
810 KernelGlobals kg,
812 ccl_private const ShaderData *sd,
814 const bool preserve_energy)
815{
816 fresnel->f0 = saturate(fresnel->f0);
817 bsdf->fresnel_type = MicrofacetFresnel::GENERALIZED_SCHLICK;
818 bsdf->fresnel = fresnel;
819 bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
820
821 if (preserve_energy) {
822 Spectrum Fss = one_spectrum();
823 /* Multi-bounce Fresnel is only supported for reflective lobes here. */
824 if (is_zero(fresnel->transmission_tint)) {
825 float s;
826 if (fresnel->exponent < 0.0f) {
827 const float eta = bsdf->ior;
828 const float real_F0 = F0_from_ior(bsdf->ior);
829
830 /* Numerical fit for the integral of 2*cosI * F(cosI, eta) over 0...1 with F being
831 * the real dielectric Fresnel. From "Revisiting Physically Based Shading at Imageworks"
832 * by Christopher Kulla and Alejandro Conty. */
833 float real_Fss;
834 if (eta < 1.0f) {
835 real_Fss = 0.997118f + eta * (0.1014f - eta * (0.965241f + eta * 0.130607f));
836 }
837 else {
838 real_Fss = (eta - 1.0f) / (4.08567f + 1.00071f * eta);
839 }
840 s = saturatef(inverse_lerp(real_F0, 1.0f, real_Fss));
841 }
842 else {
843 /* Integral of 2*cosI * (1 - cosI)^exponent over 0...1. */
844 s = 2.0f / ((fresnel->exponent + 3.0f) * fresnel->exponent + 2.0f);
845 }
846 /* Due to the linearity of the generalized model, this ends up working. */
847 Fss = fresnel->reflection_tint * mix(fresnel->f0, fresnel->f90, s);
848 }
849 else {
850 /* For transmissive BSDFs, assume that the transmissive tint makes up most of the overall
851 * color. */
852 Fss = fresnel->transmission_tint;
853 }
854
855 microfacet_ggx_preserve_energy(kg, bsdf, sd, Fss);
856 }
857}
858
861 ccl_private const ShaderData *sd,
863 const Spectrum f82_tint,
864 const bool preserve_energy)
865{
866 if (isequal(f82_tint, one_spectrum())) {
867 fresnel->b = zero_spectrum();
868 }
869 else {
870 /* Precompute the F82 term factor for the Fresnel model.
871 * In the classic F82 model, the F82 input directly determines the value of the Fresnel
872 * model at ~82°, similar to F0 and F90.
873 * With F82-Tint, on the other hand, the value at 82° is the value of the classic Schlick
874 * model multiplied by the tint input.
875 * Therefore, the factor follows by setting F82Tint(cosI) = FSchlick(cosI) - b*cosI*(1-cosI)^6
876 * and F82Tint(acos(1/7)) = FSchlick(acos(1/7)) * f82_tint and solving for b. */
877 const float f = 6.0f / 7.0f;
878 const float f5 = sqr(sqr(f)) * f;
879 const Spectrum F_schlick = mix(fresnel->f0, one_spectrum(), f5);
880 fresnel->b = F_schlick * (7.0f / (f5 * f)) * (one_spectrum() - f82_tint);
881 }
882
883 bsdf->fresnel_type = MicrofacetFresnel::F82_TINT;
884 bsdf->fresnel = fresnel;
885 bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
886
887 if (preserve_energy) {
888 Spectrum Fss = mix(fresnel->f0, one_spectrum(), 1.0f / 21.0f) - fresnel->b * (1.0f / 126.0f);
889 microfacet_ggx_preserve_energy(kg, bsdf, sd, Fss);
890 }
891}
892
895 ccl_private const ShaderData *sd,
896 const Spectrum color)
897{
898 /* Constant Fresnel is a special case - the color is already baked into the closure's
899 * weight, so we just need to perform the energy preservation. */
900 kernel_assert(bsdf->fresnel_type == MicrofacetFresnel::NONE ||
901 bsdf->fresnel_type == MicrofacetFresnel::DIELECTRIC);
902
903 microfacet_ggx_preserve_energy(kg, bsdf, sd, color);
904}
905
908 ccl_private const ShaderData *sd)
909{
910 bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC;
911 bsdf->sample_weight *= average(bsdf_microfacet_estimate_albedo(kg, sd, bsdf, true, true));
912}
913
914/* GGX microfacet with Smith shadow-masking from:
915 *
916 * Microfacet Models for Refraction through Rough Surfaces
917 * B. Walter, S. R. Marschner, H. Li, K. E. Torrance, EGSR 2007
918 *
919 * Anisotropic from:
920 *
921 * Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs
922 * E. Heitz, Research Report 2014
923 *
924 * Anisotropy is only supported for reflection currently, but adding it for
925 * transmission is just a matter of copying code from reflection if needed. */
926
928{
929 bsdf->alpha_x = saturatef(bsdf->alpha_x);
930 bsdf->alpha_y = saturatef(bsdf->alpha_y);
931
932 bsdf->fresnel_type = MicrofacetFresnel::NONE;
933 bsdf->energy_scale = 1.0f;
935
936 return SD_BSDF | bsdf_microfacet_eval_flag(bsdf);
937}
938
940{
941 bsdf->alpha_x = saturatef(bsdf->alpha_x);
942 bsdf->alpha_y = bsdf->alpha_x;
943
944 bsdf->fresnel_type = MicrofacetFresnel::NONE;
945 bsdf->energy_scale = 1.0f;
947
949}
950
952{
953 bsdf->alpha_x = saturatef(bsdf->alpha_x);
954 bsdf->alpha_y = bsdf->alpha_x;
955
956 bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC;
957 bsdf->energy_scale = 1.0f;
959
961}
962
964{
966
967 bsdf->alpha_x = fmaxf(roughness, bsdf->alpha_x);
968 bsdf->alpha_y = fmaxf(roughness, bsdf->alpha_y);
969}
970
972 ccl_private const ShaderClosure *sc,
973 const float3 Ng,
974 const float3 wi,
975 const float3 wo,
976 ccl_private float *pdf)
977{
978 ccl_private const MicrofacetBsdf *bsdf = (ccl_private const MicrofacetBsdf *)sc;
979 return bsdf->energy_scale * bsdf_microfacet_eval<MicrofacetType::GGX>(kg, sc, Ng, wi, wo, pdf);
980}
981
983 ccl_private const ShaderClosure *sc,
984 float3 Ng,
985 float3 wi,
986 const float3 rand,
987 ccl_private Spectrum *eval,
989 ccl_private float *pdf,
990 ccl_private float2 *sampled_roughness,
991 ccl_private float *eta)
992{
993
995 kg, sc, Ng, wi, rand, eval, wo, pdf, sampled_roughness, eta);
996 *eval *= ((ccl_private const MicrofacetBsdf *)sc)->energy_scale;
997 return label;
998}
999
1000/* Beckmann microfacet with Smith shadow-masking from:
1001 *
1002 * Microfacet Models for Refraction through Rough Surfaces
1003 * B. Walter, S. R. Marschner, H. Li, K. E. Torrance, EGSR 2007 */
1004
1006{
1007 bsdf->alpha_x = saturatef(bsdf->alpha_x);
1008 bsdf->alpha_y = saturatef(bsdf->alpha_y);
1009
1010 bsdf->fresnel_type = MicrofacetFresnel::NONE;
1012
1013 return SD_BSDF | bsdf_microfacet_eval_flag(bsdf);
1014}
1015
1017{
1018 bsdf->alpha_x = saturatef(bsdf->alpha_x);
1019 bsdf->alpha_y = bsdf->alpha_x;
1020
1021 bsdf->fresnel_type = MicrofacetFresnel::NONE;
1023
1025}
1026
1028{
1029 bsdf->alpha_x = saturatef(bsdf->alpha_x);
1030 bsdf->alpha_y = bsdf->alpha_x;
1031
1032 bsdf->fresnel_type = MicrofacetFresnel::DIELECTRIC;
1034
1036}
1037
1039 ccl_private const ShaderClosure *sc,
1040 const float3 Ng,
1041 const float3 wi,
1042 const float3 wo,
1043 ccl_private float *pdf)
1044{
1045 return bsdf_microfacet_eval<MicrofacetType::BECKMANN>(kg, sc, Ng, wi, wo, pdf);
1046}
1047
1049 ccl_private const ShaderClosure *sc,
1050 float3 Ng,
1051 float3 wi,
1052 const float3 rand,
1053 ccl_private Spectrum *eval,
1054 ccl_private float3 *wo,
1055 ccl_private float *pdf,
1056 ccl_private float2 *sampled_roughness,
1057 ccl_private float *eta)
1058{
1060 kg, sc, Ng, wi, rand, eval, wo, pdf, sampled_roughness, eta);
1061}
1062
#define D
MINLINE float signf(float f)
MINLINE float safe_sqrtf(float a)
MINLINE float safe_divide(float a, float b)
#define saturate(a)
#define K(key)
#define X
#define Y
ccl_device int bsdf_microfacet_sample(KernelGlobals kg, ccl_private const ShaderClosure *sc, float3 Ng, float3 wi, const float3 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf, ccl_private float2 *sampled_roughness, ccl_private float *eta)
ccl_device_forceinline float3 microfacet_beckmann_sample_vndf(const float3 wi, const float alpha_x, const float alpha_y, const float2 rand)
ccl_device_inline float bsdf_lambda(float alpha2, float cos_N)
struct FresnelConductor FresnelConductor
ccl_device Spectrum bsdf_microfacet_ggx_eval(KernelGlobals kg, ccl_private const ShaderClosure *sc, const float3 Ng, const float3 wi, const float3 wo, ccl_private float *pdf)
ccl_device_forceinline float3 microfacet_ggx_sample_vndf(const float3 wi, const float alpha_x, const float alpha_y, const float2 rand)
ccl_device void bsdf_microfacet_setup_fresnel_dielectric_tint(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, ccl_private const ShaderData *sd, ccl_private FresnelDielectricTint *fresnel, const bool preserve_energy)
ccl_device int bsdf_microfacet_beckmann_glass_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device void bsdf_microfacet_setup_fresnel_conductor(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, ccl_private const ShaderData *sd, ccl_private FresnelConductor *fresnel, const bool preserve_energy)
ccl_device int bsdf_microfacet_beckmann_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device_inline float bsdf_D(float alpha2, float cos_NH)
ccl_device_inline float bsdf_aniso_D(float alpha_x, float alpha_y, float3 H)
struct MicrofacetBsdf MicrofacetBsdf
struct FresnelDielectricTint FresnelDielectricTint
ccl_device_forceinline int bsdf_microfacet_eval_flag(const ccl_private MicrofacetBsdf *bsdf)
ccl_device int bsdf_microfacet_beckmann_sample(KernelGlobals kg, ccl_private const ShaderClosure *sc, float3 Ng, float3 wi, const float3 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf, ccl_private float2 *sampled_roughness, ccl_private float *eta)
MicrofacetType
@ GGX
@ BECKMANN
ccl_device void bsdf_microfacet_setup_fresnel_dielectric(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, ccl_private const ShaderData *sd)
ccl_device_inline float bsdf_aniso_lambda(float alpha_x, float alpha_y, float3 V)
ccl_device void bsdf_microfacet_setup_fresnel_generalized_schlick(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, ccl_private const ShaderData *sd, ccl_private FresnelGeneralizedSchlick *fresnel, const bool preserve_energy)
ccl_device Spectrum bsdf_microfacet_estimate_albedo(KernelGlobals kg, ccl_private const ShaderData *sd, ccl_private const MicrofacetBsdf *bsdf, const bool eval_reflection, const bool eval_transmission)
ccl_device_inline float bsdf_G(float alpha2, float cos_N)
ccl_device_inline float bsdf_lambda_from_sqr_alpha_tan_n(float sqr_alpha_tan_n)
struct FresnelGeneralizedSchlick FresnelGeneralizedSchlick
ccl_device int bsdf_microfacet_beckmann_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device int bsdf_microfacet_ggx_sample(KernelGlobals kg, ccl_private const ShaderClosure *sc, float3 Ng, float3 wi, const float3 rand, ccl_private Spectrum *eval, ccl_private float3 *wo, ccl_private float *pdf, ccl_private float2 *sampled_roughness, ccl_private float *eta)
struct FresnelThinFilm FresnelThinFilm
struct FresnelF82Tint FresnelF82Tint
MicrofacetFresnel
@ CONDUCTOR
@ DIELECTRIC_TINT
@ GENERALIZED_SCHLICK
@ DIELECTRIC
@ NONE
@ F82_TINT
ccl_device int bsdf_microfacet_ggx_glass_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device int bsdf_microfacet_ggx_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device void bsdf_microfacet_setup_fresnel_constant(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, ccl_private const ShaderData *sd, const Spectrum color)
ccl_device void bsdf_microfacet_blur(ccl_private ShaderClosure *sc, float roughness)
ccl_device_forceinline void microfacet_fresnel(KernelGlobals kg, ccl_private const MicrofacetBsdf *bsdf, const float cos_theta_i, ccl_private float *r_cos_theta_t, ccl_private Spectrum *r_reflectance, ccl_private Spectrum *r_transmittance)
ccl_device Spectrum bsdf_microfacet_beckmann_eval(KernelGlobals kg, ccl_private const ShaderClosure *sc, const float3 Ng, const float3 wi, const float3 wo, ccl_private float *pdf)
ccl_device void bsdf_microfacet_setup_fresnel_f82_tint(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, ccl_private const ShaderData *sd, ccl_private FresnelF82Tint *fresnel, const Spectrum f82_tint, const bool preserve_energy)
ccl_device int bsdf_microfacet_ggx_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device Spectrum bsdf_microfacet_eval(KernelGlobals kg, ccl_private const ShaderClosure *sc, const float3 Ng, const float3 wi, const float3 wo, ccl_private float *pdf)
ccl_device_inline void microfacet_ggx_preserve_energy(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, ccl_private const ShaderData *sd, const Spectrum Fss)
ccl_device float F0_from_ior(float ior)
Definition bsdf_util.h:112
ccl_device Spectrum fresnel_conductor(float cosi, const Spectrum eta, const Spectrum k)
Definition bsdf_util.h:95
ccl_device Spectrum fresnel_iridescence(KernelGlobals kg, float eta1, float eta2, float eta3, float cos_theta_1, float thickness, ccl_private float *r_cos_theta_3)
Definition bsdf_util.h:319
ccl_device_forceinline float fresnel_dielectric(float cos_theta_i, float eta, ccl_private float *r_cos_theta_t)
Definition bsdf_util.h:63
ccl_device_inline float3 refract_angle(const float3 incident, const float3 normal, const float cos_theta_t, const float inv_eta)
Definition bsdf_util.h:72
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
SIMD_FORCE_INLINE btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition btVector3.h:303
local_group_size(16, 16) .push_constant(Type b
additional_info("compositor_sum_squared_difference_float_shared") .push_constant(Type output_img float dot(value.rgb, luminance_coefficients)") .define("LOAD(value)"
const char * label
#define kernel_assert(cond)
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define ccl_device_forceinline
#define logf(x)
#define sinf(x)
#define cosf(x)
#define ccl_device
#define expf(x)
#define ccl_private
#define ccl_device_inline
#define powf(x, y)
#define CCL_NAMESPACE_END
#define saturatef(x)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define fmaxf(x, y)
ccl_device_forceinline float2 make_float2(const float x, const float y)
#define fabsf(x)
#define sqrtf(x)
int len
draw_view in_light_buf[] float
#define mix(a, b, c)
Definition hash.h:36
#define CLOSURE_IS_GLASS(type)
#define CLOSURE_IS_REFRACTION(type)
@ CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID
@ CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID
@ CLOSURE_BSDF_MICROFACET_GGX_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_ID
#define BSDF_ROUGHNESS_SQ_THRESH
@ SD_BSDF_HAS_EVAL
@ SD_BSDF
@ SD_BSDF_HAS_TRANSMISSION
ShaderData
@ LABEL_TRANSMIT
@ LABEL_NONE
@ LABEL_SINGULAR
@ LABEL_GLOSSY
@ LABEL_REFLECT
ShaderClosure
CCL_NAMESPACE_BEGIN ccl_device float lookup_table_read(KernelGlobals kg, float x, int offset, int size)
ccl_device float lookup_table_read_2D(KernelGlobals kg, float x, float y, int offset, int xsize, int ysize)
ccl_device float lookup_table_read_3D(KernelGlobals kg, float x, float y, float z, int offset, int xsize, int ysize, int zsize)
ccl_device_inline float fast_erff(float x)
Definition math_fast.h:566
ccl_device_inline float fast_ierff(float x)
Definition math_fast.h:601
ccl_device_inline float len_squared(const float2 a)
ccl_device_inline bool is_zero(const float2 a)
ccl_device_inline float average(const float2 a)
ccl_device_inline float cross(const float2 a, const float2 b)
ccl_device_inline bool isequal(const float2 a, const float2 b)
#define N
#define B
#define F
#define T2
Definition md5.cpp:19
#define T1
Definition md5.cpp:18
#define H(x, y, z)
#define M_PI_F
Definition mikk_util.hh:15
CCL_NAMESPACE_BEGIN ccl_device float2 sample_uniform_disk(const float2 rand)
ccl_device void make_orthonormals_tangent(const float3 N, const float3 T, ccl_private float3 *a, ccl_private float3 *b)
#define M_2PI_F
Definition sky_float3.h:23
#define min(a, b)
Definition sort.c:32
FresnelThinFilm thin_film
ccl_private void * fresnel
float x
float y
float z
Definition sky_float3.h:27
float y
Definition sky_float3.h:27
float x
Definition sky_float3.h:27
#define one_spectrum
#define zero_spectrum
#define make_spectrum(f)
#define FOREACH_SPECTRUM_CHANNEL(counter)
#define GET_SPECTRUM_CHANNEL(v, i)
SPECTRUM_DATA_TYPE Spectrum
ccl_device_inline float inverse_lerp(float a, float b, float x)
Definition util/math.h:550
ccl_device_inline float sqr(float a)
Definition util/math.h:782
ccl_device_inline float sin_from_cos(const float c)
Definition util/math.h:787
ccl_device_inline float inversesqrtf(float f)
Definition util/math.h:711
ccl_device_inline void make_orthonormals(const float3 N, ccl_private float3 *a, ccl_private float3 *b)
Definition util/math.h:593
ccl_device_inline float2 float3_to_float2(const float3 a)
Definition util/math.h:530
CCL_NAMESPACE_BEGIN struct Window V