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());
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
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
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp a value between a minimum and a maximum Vector Perform vector math operation Invert Invert a color
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)
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)
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)
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)
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)"
#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
@ NONE
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
float max
#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