Blender V5.0
closure.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#pragma once
6
13
14#include "kernel/geom/curve.h"
15#include "kernel/geom/object.h"
17
19#include "kernel/svm/util.h"
20
22
24
25/* Closure Nodes */
26
28{
29 if (type == CLOSURE_BSDF_PRINCIPLED_ID) {
30 /* Read all principled BSDF extra data to get the right offset. */
31 read_node(kg, &offset);
32 read_node(kg, &offset);
33 }
34
35 return offset;
36}
37
38template<uint node_feature_mask, ShaderType shader_type>
39#ifndef __KERNEL_ONEAPI__
41#else
43#endif
44 int
46 ccl_private ShaderData *sd,
47 ccl_private float *stack,
48 Spectrum closure_weight,
49 const uint4 node,
50 const uint32_t path_flag,
51 int offset)
52{
53 uint type;
54 uint param1_offset;
55 uint param2_offset;
56
57 uint mix_weight_offset;
58 svm_unpack_node_uchar4(node.y, &type, &param1_offset, &param2_offset, &mix_weight_offset);
59 const float mix_weight = (stack_valid(mix_weight_offset) ?
60 stack_load_float(stack, mix_weight_offset) :
61 1.0f);
62
63 /* note we read this extra node before weight check, so offset is added */
64 const uint4 data_node = read_node(kg, &offset);
65
66 /* Only compute BSDF for surfaces, transparent variable is shared with volume extinction. */
68 {
69 if ((shader_type != SHADER_TYPE_SURFACE) || mix_weight == 0.0f) {
70 return svm_node_closure_bsdf_skip(kg, offset, type);
71 }
72 }
73 else IF_KERNEL_NODES_FEATURE(EMISSION) {
74 if (type != CLOSURE_BSDF_PRINCIPLED_ID) {
75 /* Only principled BSDF can have emission. */
76 return svm_node_closure_bsdf_skip(kg, offset, type);
77 }
78 }
79 else {
80 return svm_node_closure_bsdf_skip(kg, offset, type);
81 }
82
83 float3 N = stack_valid(data_node.x) ? stack_load_float3(stack, data_node.x) : sd->N;
84 N = safe_normalize_fallback(N, sd->N);
85
86 const float param1 = (stack_valid(param1_offset)) ? stack_load_float(stack, param1_offset) :
87 __uint_as_float(node.z);
88 const float param2 = (stack_valid(param2_offset)) ? stack_load_float(stack, param2_offset) :
89 __uint_as_float(node.w);
90
91 switch (type) {
93 uint base_color_offset;
94 uint metallic_offset;
95 uint alpha_offset;
96 uint coat_normal_offset;
97 uint distribution_uint;
98 uint diffuse_roughness_offset;
99 uint specular_ior_level_offset;
100 uint specular_tint_offset;
101 uint emission_strength_offset;
102 uint emission_color_offset;
103 uint anisotropic_offset;
104 uint thin_film_thickness_offset;
105 uint subsurface_weight_offset;
106 uint coat_weight_offset;
107 uint sheen_weight_offset;
108 uint transmission_weight_offset;
109 uint coat_roughness_offset;
110 uint coat_ior_offset;
111 uint coat_tint_offset;
112 uint subsurface_method_uint;
113 uint subsurface_radius_offset;
114 uint subsurface_scale_offset;
115 uint subsurface_ior_offset;
116 uint subsurface_anisotropy_offset;
117 uint sheen_roughness_offset;
118 uint sheen_tint_offset;
119 uint anisotropic_rotation_offset;
120 uint tangent_offset;
121 uint thin_film_ior_offset;
122 ClosureType distribution;
123
124 const uint4 data_node2 = read_node(kg, &offset);
125 const uint4 data_node3 = read_node(kg, &offset);
126
128 data_node.y, &base_color_offset, &metallic_offset, &alpha_offset, &coat_normal_offset);
129 svm_unpack_node_uchar4(data_node.z,
130 &distribution_uint,
131 &diffuse_roughness_offset,
132 &specular_ior_level_offset,
133 &specular_tint_offset);
134 svm_unpack_node_uchar4(data_node.w,
135 &emission_strength_offset,
136 &emission_color_offset,
137 &anisotropic_offset,
138 &thin_film_thickness_offset);
139 svm_unpack_node_uchar4(data_node2.x,
140 &subsurface_weight_offset,
141 &coat_weight_offset,
142 &sheen_weight_offset,
143 &transmission_weight_offset);
144 svm_unpack_node_uchar4(data_node2.y,
145 &coat_roughness_offset,
146 &coat_ior_offset,
147 &coat_tint_offset,
148 &subsurface_method_uint);
149 svm_unpack_node_uchar4(data_node2.z,
150 &subsurface_radius_offset,
151 &subsurface_scale_offset,
152 &subsurface_ior_offset,
153 &subsurface_anisotropy_offset);
154 svm_unpack_node_uchar4(data_node2.w,
155 &sheen_roughness_offset,
156 &sheen_tint_offset,
157 &anisotropic_rotation_offset,
158 &tangent_offset);
159 thin_film_ior_offset = data_node3.x;
160
161 const float3 default_base_color = make_float3(__uint_as_float(data_node3.y),
162 __uint_as_float(data_node3.z),
163 __uint_as_float(data_node3.w));
164 const float3 base_color = max(
165 stack_load_float3_default(stack, base_color_offset, default_base_color), zero_float3());
166 const float3 clamped_base_color = min(base_color, one_float3());
167 const float ior = fmaxf(param1, 1e-5f);
168 const float roughness = saturatef(param2);
169 const float metallic = saturatef(stack_load_float_default(stack, metallic_offset, 0.0f));
170
171 const float alpha = saturatef(stack_load_float_default(stack, alpha_offset, 1.0f));
172 const float3 valid_reflection_N = maybe_ensure_valid_specular_reflection(sd, N);
173 const float3 coat_normal = safe_normalize_fallback(
174 stack_load_float3_default(stack, coat_normal_offset, N), sd->N);
175
176 distribution = (ClosureType)distribution_uint;
177
178 const float diffuse_roughness = saturatef(
179 stack_load_float_default(stack, diffuse_roughness_offset, 0.0f));
180 const float specular_ior_level = max(
181 stack_load_float_default(stack, specular_ior_level_offset, 0.5f), 0.0f);
182 const Spectrum specular_tint = rgb_to_spectrum(max(
183 stack_load_float3_default(stack, specular_tint_offset, one_float3()), zero_float3()));
184
186 stack, emission_color_offset, zero_float3())) *
187 stack_load_float_default(stack, emission_strength_offset, 0.0f);
188 const float anisotropic = saturatef(
189 stack_load_float_default(stack, anisotropic_offset, 0.0f));
191 stack, thin_film_thickness_offset, 0.0f);
192
193#ifdef __SUBSURFACE__
194 const float subsurface_weight = saturatef(
195 stack_load_float_default(stack, subsurface_weight_offset, 0.0f));
196#else
197 const float subsurface_weight = 0.0f;
198#endif
199 const float coat_weight = fmaxf(stack_load_float_default(stack, coat_weight_offset, 0.0f),
200 0.0f);
201 const float sheen_weight = fmaxf(stack_load_float_default(stack, sheen_weight_offset, 0.0f),
202 0.0f);
203 const float transmission_weight = saturatef(
204 stack_load_float_default(stack, transmission_weight_offset, 0.0f));
205
206 float thinfilm_ior = 0.0f;
208 thinfilm_ior = fmaxf(stack_load_float(stack, thin_film_ior_offset), 1e-5f);
209 }
210
211 /* We're ignoring closure_weight here since it's always 1 for the Principled BSDF, so there's
212 * no point in setting it. */
214
215 float alpha_x = sqr(roughness);
216 float alpha_y = sqr(roughness);
217 float3 T = zero_float3();
218 if (anisotropic > 0.0f && stack_valid(tangent_offset)) {
219 T = stack_load_float3(stack, tangent_offset);
220 const float aspect = sqrtf(1.0f - anisotropic * 0.9f);
221 alpha_x /= aspect;
222 alpha_y *= aspect;
223 const float anisotropic_rotation = stack_load_float_default(
224 stack, anisotropic_rotation_offset, 0.0f);
225 if (anisotropic_rotation != 0.0f) {
226 T = rotate_around_axis(T, N, anisotropic_rotation * M_2PI_F);
227 }
228 }
229
230#ifdef __CAUSTICS_TRICKS__
231 const bool reflective_caustics = (kernel_data.integrator.caustics_reflective ||
232 (path_flag & PATH_RAY_DIFFUSE) == 0);
233 const bool refractive_caustics = (kernel_data.integrator.caustics_refractive ||
234 (path_flag & PATH_RAY_DIFFUSE) == 0);
235#else
236 const bool reflective_caustics = true;
237 const bool refractive_caustics = true;
238#endif
239
240 /* Before any actual shader components, apply transparency. */
241 if (alpha < 1.0f) {
242 bsdf_transparent_setup(sd, weight * (1.0f - alpha), path_flag);
243 weight *= alpha;
244 }
245
246 /* First layer: Sheen */
247 if (sheen_weight > CLOSURE_WEIGHT_CUTOFF) {
248 const float3 sheen_tint = max(
249 stack_load_float3_default(stack, sheen_tint_offset, one_float3()), zero_float3());
250 const float sheen_roughness = saturatef(stack_load_float(stack, sheen_roughness_offset));
251
253 sd, sizeof(SheenBsdf), sheen_weight * rgb_to_spectrum(sheen_tint) * weight);
254
255 if (bsdf) {
256 bsdf->N = safe_normalize(mix(N, coat_normal, saturatef(coat_weight)));
257 bsdf->roughness = sheen_roughness;
258
259 /* setup bsdf */
260 const int sheen_flag = bsdf_sheen_setup(kg, sd, bsdf);
261
262 if (sheen_flag) {
263 sd->flag |= sheen_flag;
264
265 /* Attenuate lower layers */
266 const Spectrum albedo = bsdf_albedo(
267 kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
268 weight = closure_layering_weight(albedo, weight);
269 }
270 }
271 }
272
273 /* Second layer: Coat */
274 if (coat_weight > CLOSURE_WEIGHT_CUTOFF) {
275 const float coat_roughness = saturatef(stack_load_float(stack, coat_roughness_offset));
276 const float coat_ior = fmaxf(stack_load_float(stack, coat_ior_offset), 1.0f);
277 const float3 coat_tint = max(
278 stack_load_float3_default(stack, coat_tint_offset, one_float3()), zero_float3());
279
280 const float3 valid_coat_normal = maybe_ensure_valid_specular_reflection(sd, coat_normal);
281 if (reflective_caustics) {
283 sd, sizeof(MicrofacetBsdf), coat_weight * weight);
284
285 if (bsdf) {
286 bsdf->N = valid_coat_normal;
287 bsdf->T = zero_float3();
288 bsdf->ior = coat_ior;
289
290 bsdf->alpha_x = bsdf->alpha_y = sqr(coat_roughness);
291
292 /* setup bsdf */
293 sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
295
296 /* Attenuate lower layers */
297 const Spectrum albedo = bsdf_albedo(
298 kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
299 weight = closure_layering_weight(albedo, weight);
300 }
301 }
302
303 if (!isequal(coat_tint, one_float3())) {
304 /* Tint is normalized to perpendicular incidence.
305 * Therefore, if we define the coat thickness as length 1, the length along the ray is
306 * t = sqrt(1+tan^2(angle(N, I))) = sqrt(1+tan^2(acos(dotNI))) = 1 / dotNI.
307 * From Beer's law, we have T = exp(-sigma_e * t).
308 * Therefore, tint = exp(-sigma_e * 1) (per def.), so -sigma_e = log(tint).
309 * From this, T = exp(log(tint) * t) = exp(log(tint)) ^ t = tint ^ t;
310 *
311 * Note that this is only an approximation - it assumes that the outgoing ray
312 * follows the same angle, and that there aren't multiple internal bounces.
313 * In particular, things that could be improved:
314 * - For transmissive materials, there should not be an outgoing path at all if the path
315 * is transmitted.
316 * - For rough materials, we could blend towards a view-independent average path length
317 * (e.g. 2 for diffuse reflection) for the outgoing direction.
318 * However, there's also an argument to be made for keeping parameters independent of
319 * each other for more intuitive control, in particular main roughness not affecting the
320 * coat.
321 */
322 const float cosNI = dot(sd->wi, valid_coat_normal);
323 /* Refract incoming direction into coat material.
324 * TIR is no concern here since we're always coming from the outside. */
325 const float cosNT = sqrtf(1.0f - sqr(1.0f / coat_ior) * (1 - sqr(cosNI)));
326 const float optical_depth = 1.0f / cosNT;
327 weight *= mix(
328 one_spectrum(), power(rgb_to_spectrum(coat_tint), optical_depth), coat_weight);
329 }
330 }
331
332 /* Emission (attenuated by sheen and coat) */
333 if (!is_zero(emission)) {
334 emission_setup(sd, rgb_to_spectrum(emission) * weight);
335 }
336
337 /* Metallic component */
338 if (metallic > CLOSURE_WEIGHT_CUTOFF) {
339 if (reflective_caustics) {
341 sd, sizeof(MicrofacetBsdf), metallic * weight);
342 ccl_private FresnelF82Tint *fresnel =
343 (bsdf != nullptr) ?
345 nullptr;
346
347 if (bsdf && fresnel) {
348 bsdf->N = valid_reflection_N;
349 bsdf->ior = 1.0f;
350 bsdf->T = T;
351 bsdf->alpha_x = alpha_x;
352 bsdf->alpha_y = alpha_y;
353
354 fresnel->f0 = rgb_to_spectrum(clamped_base_color);
355 const Spectrum f82 = min(specular_tint, one_spectrum());
356
357 fresnel->thin_film.thickness = thinfilm_thickness;
358 fresnel->thin_film.ior = thinfilm_ior;
359
360 /* setup bsdf */
361 sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
362 const bool is_multiggx = (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
363 bsdf_microfacet_setup_fresnel_f82_tint(kg, bsdf, sd, fresnel, f82, is_multiggx);
364 }
365 }
366 /* Attenuate other components */
367 weight *= (1.0f - metallic);
368 }
369
370 /* Transmission component */
371 if (transmission_weight > CLOSURE_WEIGHT_CUTOFF) {
372 if (reflective_caustics || refractive_caustics) {
374 sd, sizeof(MicrofacetBsdf), transmission_weight * weight);
377 sd, sizeof(FresnelGeneralizedSchlick)) :
378 nullptr;
379
380 if (bsdf && fresnel) {
381 bsdf->N = valid_reflection_N;
382 bsdf->T = zero_float3();
383
384 bsdf->alpha_x = bsdf->alpha_y = sqr(roughness);
385 bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / ior : ior;
386
387 fresnel->f0 = make_float3(F0_from_ior(ior)) * specular_tint;
388 fresnel->f90 = one_spectrum();
389 fresnel->exponent = -ior;
390 fresnel->reflection_tint = reflective_caustics ? one_spectrum() : zero_spectrum();
391 fresnel->transmission_tint = refractive_caustics ?
392 sqrt(rgb_to_spectrum(clamped_base_color)) :
394 fresnel->thin_film.thickness = thinfilm_thickness;
395 fresnel->thin_film.ior = (sd->flag & SD_BACKFACING) ? thinfilm_ior / ior :
396 thinfilm_ior;
397
398 /* setup bsdf */
399 sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
400 const bool is_multiggx = (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
401 bsdf_microfacet_setup_fresnel_generalized_schlick(kg, bsdf, sd, fresnel, is_multiggx);
402 }
403 }
404 /* Attenuate other components */
405 weight *= (1.0f - transmission_weight);
406 }
407
408 /* Apply IOR adjustment */
409 float eta = ior;
410 float f0 = F0_from_ior(eta);
411 if (specular_ior_level != 0.5f) {
412 f0 *= 2.0f * specular_ior_level;
413 eta = ior_from_F0(f0);
414 if (ior < 1.0f) {
415 eta = 1.0f / eta;
416 }
417 }
418
419 /* Specular component */
420 if (reflective_caustics && (eta != 1.0f || thinfilm_thickness > 0.1f)) {
422 sd, sizeof(MicrofacetBsdf), weight);
425 sd, sizeof(FresnelGeneralizedSchlick)) :
426 nullptr;
427
428 if (bsdf && fresnel) {
429 bsdf->N = valid_reflection_N;
430 bsdf->ior = eta;
431 bsdf->T = T;
432 bsdf->alpha_x = alpha_x;
433 bsdf->alpha_y = alpha_y;
434
435 fresnel->f0 = f0 * specular_tint;
436 fresnel->f90 = one_spectrum();
437 fresnel->exponent = -eta;
438 fresnel->reflection_tint = one_spectrum();
439 fresnel->transmission_tint = zero_spectrum();
440 fresnel->thin_film.thickness = thinfilm_thickness;
441 fresnel->thin_film.ior = thinfilm_ior;
442
443 /* setup bsdf */
444 sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
445 const bool is_multiggx = (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
446 bsdf_microfacet_setup_fresnel_generalized_schlick(kg, bsdf, sd, fresnel, is_multiggx);
447
448 /* Attenuate lower layers */
449 const Spectrum albedo = bsdf_albedo(
450 kg, sd, (ccl_private ShaderClosure *)bsdf, true, false);
451 weight = closure_layering_weight(albedo, weight);
452 }
453 }
454
455 /* Diffuse/Subsurface component */
456#ifdef __SUBSURFACE__
457 if (subsurface_weight > CLOSURE_WEIGHT_CUTOFF) {
458 const ClosureType subsurface_method = (ClosureType)subsurface_method_uint;
460 sd, rgb_to_spectrum(clamped_base_color) * subsurface_weight * weight);
461 if (bssrdf) {
462 const float3 subsurface_radius = stack_load_float3(stack, subsurface_radius_offset);
463 const float subsurface_scale = stack_load_float(stack, subsurface_scale_offset);
464
465 bssrdf->radius = rgb_to_spectrum(
466 max(subsurface_radius * subsurface_scale, zero_float3()));
467 bssrdf->albedo = rgb_to_spectrum(clamped_base_color);
469 bssrdf->alpha = sqr(roughness);
470 /* IOR is clamped to [1.01..3.8] inside bssrdf_setup */
471 bssrdf->ior = eta;
472 /* Anisotropy is clamped to [0.0..0.9] inside bssrdf_setup */
473 bssrdf->anisotropy = stack_load_float_default(stack, subsurface_anisotropy_offset, 0.0f);
474 if (subsurface_method == CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID) {
475 bssrdf->ior = stack_load_float_default(stack, subsurface_ior_offset, 1.4f);
476 }
477
478 /* setup bsdf */
479 sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, subsurface_method);
480 }
481 }
482#else
483 (void)data_subsurf;
484#endif
485
487 sd,
488 sizeof(OrenNayarBsdf),
489 rgb_to_spectrum(base_color) * (1.0f - subsurface_weight) * weight);
490 if (bsdf) {
491 bsdf->N = N;
492
493 /* setup bsdf */
494 if (diffuse_roughness < CLOSURE_WEIGHT_CUTOFF) {
495 sd->flag |= bsdf_diffuse_setup((ccl_private DiffuseBsdf *)bsdf);
496 }
497 else {
498 bsdf->roughness = diffuse_roughness;
499 sd->flag |= bsdf_oren_nayar_setup(sd, bsdf, rgb_to_spectrum(base_color));
500 }
501 }
502
503 break;
504 }
506 const Spectrum weight = closure_weight * mix_weight;
508 sd, sizeof(OrenNayarBsdf), weight);
509
510 if (bsdf) {
511 bsdf->N = N;
512
513 const float roughness = param1;
514
515 if (roughness < 1e-5f) {
516 sd->flag |= bsdf_diffuse_setup((ccl_private DiffuseBsdf *)bsdf);
517 }
518 else {
519 bsdf->roughness = roughness;
520 const Spectrum color = saturate(rgb_to_spectrum(stack_load_float3(stack, data_node.y)));
521 sd->flag |= bsdf_oren_nayar_setup(sd, bsdf, color);
522 }
523 }
524 break;
525 }
527 const Spectrum weight = closure_weight * mix_weight;
529 sd, sizeof(DiffuseBsdf), weight);
530
531 if (bsdf) {
533 sd->flag |= bsdf_translucent_setup(bsdf);
534 }
535 break;
536 }
538 const Spectrum weight = closure_weight * mix_weight;
539 bsdf_transparent_setup(sd, weight, path_flag);
540 break;
541 }
544#ifdef __CAUSTICS_TRICKS__
545 if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE)) {
546 break;
547 }
548#endif
551
552 if (bsdf != nullptr) {
553 uint base_ior_offset;
554 uint edge_tint_k_offset;
555 uint rotation_offset;
556 uint tangent_offset;
558 data_node.y, &base_ior_offset, &edge_tint_k_offset, &rotation_offset, &tangent_offset);
559
560 const float3 valid_reflection_N = maybe_ensure_valid_specular_reflection(sd, N);
561 const float anisotropy = saturatef(param2);
562 const float roughness = saturatef(param1);
563 bsdf->alpha_x = sqr(roughness);
564 bsdf->alpha_y = sqr(roughness);
565 if (anisotropy > 0.0f && stack_valid(tangent_offset)) {
566 bsdf->T = stack_load_float3(stack, tangent_offset);
567 const float aspect = sqrtf(1.0f - anisotropy * 0.9f);
568 bsdf->alpha_x /= aspect;
569 bsdf->alpha_y *= aspect;
570 const float anisotropic_rotation = stack_load_float(stack, rotation_offset);
571 if (anisotropic_rotation != 0.0f) {
572 bsdf->T = rotate_around_axis(bsdf->T, N, anisotropic_rotation * M_2PI_F);
573 }
574 }
575 else {
576 bsdf->T = zero_float3();
577 }
578
579 bsdf->N = valid_reflection_N;
580 bsdf->ior = 1.0f;
581
582 uint distribution_int;
583 uint thin_film_thickness_offset;
584 uint thin_film_ior_offset;
585 uint unused;
586 svm_unpack_node_uchar4(data_node.z,
587 &distribution_int,
588 &thin_film_thickness_offset,
589 &thin_film_ior_offset,
590 &unused);
591
592 const float thin_film_thickness = fmaxf(
593 stack_load_float(stack, thin_film_thickness_offset), 1e-5f);
594 const float thin_film_ior = fmaxf(stack_load_float(stack, thin_film_ior_offset), 1e-5f);
595
596 const ClosureType distribution = (ClosureType)distribution_int;
597 /* Setup BSDF */
598 if (distribution == CLOSURE_BSDF_MICROFACET_BECKMANN_ID) {
599 sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
600 }
601 else {
602 sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
603 }
604
605 const bool is_multiggx = (distribution == CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID);
606
610
611 if (!fresnel) {
612 break;
613 }
614
615 fresnel->thin_film.thickness = thin_film_thickness;
616 fresnel->thin_film.ior = thin_film_ior;
617
618 const float3 n = max(stack_load_float3(stack, base_ior_offset), zero_float3());
619 const float3 k = max(stack_load_float3(stack, edge_tint_k_offset), zero_float3());
620
621 fresnel->ior = {rgb_to_spectrum(n), rgb_to_spectrum(k)};
622 bsdf_microfacet_setup_fresnel_conductor(kg, bsdf, sd, fresnel, is_multiggx);
623 }
624 else {
626 sd, sizeof(FresnelF82Tint));
627
628 if (!fresnel) {
629 break;
630 }
631
632 fresnel->thin_film.thickness = thin_film_thickness;
633 fresnel->thin_film.ior = thin_film_ior;
634
635 const float3 color = saturate(stack_load_float3(stack, base_ior_offset));
636 const float3 tint = saturate(stack_load_float3(stack, edge_tint_k_offset));
637
638 fresnel->f0 = rgb_to_spectrum(color);
639 const Spectrum f82 = rgb_to_spectrum(tint);
640 bsdf_microfacet_setup_fresnel_f82_tint(kg, bsdf, sd, fresnel, f82, is_multiggx);
641 }
642 }
643 break;
644 }
646 const Spectrum weight = closure_weight * mix_weight;
647 const float3 position = stack_load_float3(stack, data_node.y);
648 const float3 direction = stack_load_float3(stack, data_node.z);
649 bsdf_ray_portal_setup(sd, weight, position, direction);
650 break;
651 }
656#ifdef __CAUSTICS_TRICKS__
657 if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE)) {
658 break;
659 }
660#endif
661 const Spectrum weight = closure_weight * mix_weight;
663 sd, sizeof(MicrofacetBsdf), weight);
664
665 if (!bsdf) {
666 break;
667 }
668
669 const float roughness = sqr(saturatef(param1));
670
672 bsdf->ior = 1.0f;
673
674 /* compute roughness */
675 const float anisotropy = clamp(param2, -0.99f, 0.99f);
676 if (data_node.w == SVM_STACK_INVALID || fabsf(anisotropy) <= 1e-4f) {
677 /* Isotropic case. */
678 bsdf->T = zero_float3();
679 bsdf->alpha_x = roughness;
680 bsdf->alpha_y = roughness;
681 }
682 else {
683 bsdf->T = stack_load_float3(stack, data_node.w);
684
685 /* rotate tangent */
686 const float rotation = stack_load_float(stack, data_node.y);
687 if (rotation != 0.0f) {
688 bsdf->T = rotate_around_axis(bsdf->T, bsdf->N, rotation * M_2PI_F);
689 }
690
691 if (anisotropy < 0.0f) {
692 bsdf->alpha_x = roughness / (1.0f + anisotropy);
693 bsdf->alpha_y = roughness * (1.0f + anisotropy);
694 }
695 else {
696 bsdf->alpha_x = roughness * (1.0f - anisotropy);
697 bsdf->alpha_y = roughness / (1.0f - anisotropy);
698 }
699 }
700
701 /* setup bsdf */
703 sd->flag |= bsdf_microfacet_beckmann_setup(bsdf);
704 }
705 else if (type == CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID) {
706 sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf);
707 }
708 else {
709 sd->flag |= bsdf_microfacet_ggx_setup(bsdf);
711 kernel_assert(stack_valid(data_node.z));
712 const Spectrum color = max(rgb_to_spectrum(stack_load_float3(stack, data_node.z)),
713 zero_spectrum());
714 bsdf_microfacet_setup_fresnel_constant(kg, bsdf, sd, color);
715 }
716 }
717
718 break;
719 }
722#ifdef __CAUSTICS_TRICKS__
723 if (!kernel_data.integrator.caustics_refractive && (path_flag & PATH_RAY_DIFFUSE)) {
724 break;
725 }
726#endif
727 const Spectrum weight = closure_weight * mix_weight;
729 sd, sizeof(MicrofacetBsdf), weight);
730
731 if (bsdf) {
733 bsdf->T = zero_float3();
734
735 float eta = fmaxf(param2, 1e-5f);
736 eta = (sd->flag & SD_BACKFACING) ? 1.0f / eta : eta;
737
738 /* setup bsdf */
739 const float roughness = sqr(param1);
740 bsdf->alpha_x = roughness;
741 bsdf->alpha_y = roughness;
742 bsdf->ior = eta;
743
746 }
747 else {
748 sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf);
749 }
750 }
751
752 break;
753 }
757#ifdef __CAUSTICS_TRICKS__
758 const bool reflective_caustics = (kernel_data.integrator.caustics_reflective ||
759 (path_flag & PATH_RAY_DIFFUSE) == 0);
760 const bool refractive_caustics = (kernel_data.integrator.caustics_refractive ||
761 (path_flag & PATH_RAY_DIFFUSE) == 0);
762 if (!(reflective_caustics || refractive_caustics)) {
763 break;
764 }
765#else
766 const bool reflective_caustics = true;
767 const bool refractive_caustics = true;
768#endif
769
770 const float thinfilm_thickness = stack_load_float(stack, data_node.z);
771 const float thinfilm_ior = fmaxf(stack_load_float(stack, data_node.w), 1e-5f);
772
777 sd, sizeof(FresnelGeneralizedSchlick)) :
778 nullptr;
779
780 if (bsdf && fresnel) {
782 bsdf->T = zero_float3();
783
784 const float ior = fmaxf(param2, 1e-5f);
785 bsdf->ior = (sd->flag & SD_BACKFACING) ? 1.0f / ior : ior;
786 bsdf->alpha_x = bsdf->alpha_y = sqr(saturatef(param1));
787
788 fresnel->f0 = make_float3(F0_from_ior(ior));
789 fresnel->f90 = one_spectrum();
790 fresnel->exponent = -ior;
791 const float3 color = max(stack_load_float3(stack, data_node.y), zero_float3());
792 fresnel->reflection_tint = reflective_caustics ? rgb_to_spectrum(color) : zero_spectrum();
793 fresnel->transmission_tint = refractive_caustics ? rgb_to_spectrum(color) :
795 fresnel->thin_film.thickness = thinfilm_thickness;
796 fresnel->thin_film.ior = (sd->flag & SD_BACKFACING) ? thinfilm_ior / ior : thinfilm_ior;
797 /* setup bsdf */
799 sd->flag |= bsdf_microfacet_beckmann_glass_setup(bsdf);
800 }
801 else {
802 sd->flag |= bsdf_microfacet_ggx_glass_setup(bsdf);
803 }
804 const bool is_multiggx = (type == CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID);
805 bsdf_microfacet_setup_fresnel_generalized_schlick(kg, bsdf, sd, fresnel, is_multiggx);
806 }
807 break;
808 }
810 const Spectrum weight = closure_weight * mix_weight;
812 sd, sizeof(VelvetBsdf), weight);
813
814 if (bsdf) {
815 bsdf->N = N;
816
817 bsdf->sigma = saturatef(param1);
818 sd->flag |= bsdf_ashikhmin_velvet_setup(bsdf);
819 }
820 break;
821 }
823 const Spectrum weight = closure_weight * mix_weight;
825 sd, sizeof(SheenBsdf), weight);
826
827 if (bsdf) {
828 bsdf->N = N;
829 bsdf->roughness = saturatef(param1);
830
831 sd->flag |= bsdf_sheen_setup(kg, sd, bsdf);
832 }
833 break;
834 }
836#ifdef __CAUSTICS_TRICKS__
837 if (!kernel_data.integrator.caustics_reflective && (path_flag & PATH_RAY_DIFFUSE)) {
838 break;
839 }
841#endif
843 const Spectrum weight = closure_weight * mix_weight;
845 sd, sizeof(ToonBsdf), weight);
846
847 if (bsdf) {
848 bsdf->N = N;
849 bsdf->size = param1;
850 bsdf->smooth = param2;
851
852 if (type == CLOSURE_BSDF_DIFFUSE_TOON_ID) {
853 sd->flag |= bsdf_diffuse_toon_setup(bsdf);
854 }
855 else {
856 sd->flag |= bsdf_glossy_toon_setup(bsdf);
857 }
858 }
859 break;
860 }
861#ifdef __HAIR__
862# ifdef __PRINCIPLED_HAIR__
865 const uint4 data_node2 = read_node(kg, &offset);
866 const uint4 data_node3 = read_node(kg, &offset);
867 const uint4 data_node4 = read_node(kg, &offset);
868
869 const Spectrum weight = closure_weight * mix_weight;
870
871 uint offset_ofs;
872 uint ior_ofs;
873 uint color_ofs;
874 uint parametrization;
875 svm_unpack_node_uchar4(data_node.y, &offset_ofs, &ior_ofs, &color_ofs, &parametrization);
876 const float alpha = stack_load_float_default(stack, offset_ofs, data_node.z);
877 const float ior = stack_load_float_default(stack, ior_ofs, data_node.w);
878
879 uint tint_ofs;
880 uint melanin_ofs;
881 uint melanin_redness_ofs;
882 uint absorption_coefficient_ofs;
883 svm_unpack_node_uchar4(data_node2.x,
884 &tint_ofs,
885 &melanin_ofs,
886 &melanin_redness_ofs,
887 &absorption_coefficient_ofs);
888
889 uint shared_ofs1;
890 uint random_ofs;
891 uint random_color_ofs;
892 uint shared_ofs2;
894 data_node3.x, &shared_ofs1, &random_ofs, &random_color_ofs, &shared_ofs2);
895
896 const AttributeDescriptor attr_descr_random = find_attribute(kg, sd, data_node2.y);
897 float random = 0.0f;
898 if (attr_descr_random.offset != ATTR_STD_NOT_FOUND) {
899 random = primitive_surface_attribute<float>(kg, sd, attr_descr_random).val;
900 }
901 else {
902 random = stack_load_float_default(stack, random_ofs, data_node3.y);
903 }
904
905 /* Random factors range: [-randomization/2, +randomization/2]. */
906 const float random_roughness = param2;
907 const float factor_random_roughness = 1.0f + 2.0f * (random - 0.5f) * random_roughness;
908 const float roughness = param1 * factor_random_roughness;
909 const float radial_roughness = (type == CLOSURE_BSDF_HAIR_CHIANG_ID) ?
911 stack, shared_ofs2, data_node4.y) *
912 factor_random_roughness :
913 roughness;
914
915 Spectrum sigma;
916 switch (parametrization) {
918 const float3 absorption_coefficient = stack_load_float3(stack,
919 absorption_coefficient_ofs);
920 sigma = rgb_to_spectrum(absorption_coefficient);
921 break;
922 }
924 float melanin = stack_load_float_default(stack, melanin_ofs, data_node2.z);
925 const float melanin_redness = stack_load_float_default(
926 stack, melanin_redness_ofs, data_node2.w);
927
928 /* Randomize melanin. */
929 float random_color = stack_load_float_default(stack, random_color_ofs, data_node3.z);
930 random_color = clamp(random_color, 0.0f, 1.0f);
931 const float factor_random_color = 1.0f + 2.0f * (random - 0.5f) * random_color;
932 melanin *= factor_random_color;
933
934 /* Map melanin 0..inf from more perceptually linear 0..1. */
935 melanin = -logf(fmaxf(1.0f - melanin, 0.0001f));
936
937 /* Benedikt Bitterli's melanin ratio remapping. */
938 const float eumelanin = melanin * (1.0f - melanin_redness);
939 const float pheomelanin = melanin * melanin_redness;
941 eumelanin, pheomelanin);
942
943 /* Optional tint. */
944 const float3 tint = stack_load_float3(stack, tint_ofs);
946 rgb_to_spectrum(tint), radial_roughness);
947
948 sigma = melanin_sigma + tint_sigma;
949 break;
950 }
952 const float3 color = stack_load_float3(stack, color_ofs);
954 radial_roughness);
955 break;
956 }
957 default: {
958 /* Fallback to brownish hair, same as defaults for melanin. */
959 kernel_assert(!"Invalid Hair parametrization!");
960 sigma = bsdf_principled_hair_sigma_from_concentration(0.0f, 0.8054375f);
961 break;
962 }
963 }
964
965 if (type == CLOSURE_BSDF_HAIR_CHIANG_ID) {
967 sd, sizeof(ChiangHairBSDF), weight);
968 if (bsdf) {
969 /* Remap Coat value to [0, 100]% of Roughness. */
970 const float coat = stack_load_float_default(stack, shared_ofs1, data_node3.w);
971 const float m0_roughness = 1.0f - clamp(coat, 0.0f, 1.0f);
972
973 bsdf->v = roughness;
974 bsdf->s = radial_roughness;
975 bsdf->m0_roughness = m0_roughness;
976 bsdf->alpha = alpha;
977 bsdf->eta = ior;
978 bsdf->sigma = sigma;
979
980 sd->flag |= bsdf_hair_chiang_setup(sd, bsdf);
981 }
982 }
983 else {
985 uint R_ofs;
986 uint TT_ofs;
987 uint TRT_ofs;
988 uint unused;
989 svm_unpack_node_uchar4(data_node4.x, &R_ofs, &TT_ofs, &TRT_ofs, &unused);
990 const float R = stack_load_float_default(stack, R_ofs, data_node4.y);
991 const float TT = stack_load_float_default(stack, TT_ofs, data_node4.z);
992 const float TRT = stack_load_float_default(stack, TRT_ofs, data_node4.w);
993 if (R <= 0.0f && TT <= 0.0f && TRT <= 0.0f) {
994 break;
995 }
996
998 sd, sizeof(HuangHairBSDF), weight);
999 if (bsdf) {
1001 sd, sizeof(HuangHairExtra));
1002
1003 if (!extra) {
1004 break;
1005 }
1006
1007 bsdf->extra = extra;
1008 bsdf->extra->R = fmaxf(0.0f, R);
1009 bsdf->extra->TT = fmaxf(0.0f, TT);
1010 bsdf->extra->TRT = fmaxf(0.0f, TRT);
1011
1012 bsdf->extra->pixel_coverage = 1.0f;
1013
1014 /* For camera ray, check if the hair covers more than one pixel, in which case a
1015 * nearfield model is needed to prevent ribbon-like appearance. */
1016 if ((path_flag & PATH_RAY_CAMERA) && (sd->type & PRIMITIVE_CURVE)) {
1017 /* Interpolate radius between curve keys. */
1018 const KernelCurve kcurve = kernel_data_fetch(curves, sd->prim);
1019 const int k0 = kcurve.first_key + PRIMITIVE_UNPACK_SEGMENT(sd->type);
1020 const int k1 = k0 + 1;
1021 const float radius = mix(
1022 kernel_data_fetch(curve_keys, k0).w, kernel_data_fetch(curve_keys, k1).w, sd->u);
1023
1024 bsdf->extra->pixel_coverage = 0.5f * sd->dP / radius;
1025 }
1026
1027 bsdf->aspect_ratio = stack_load_float_default(stack, shared_ofs1, data_node3.w);
1028 if (bsdf->aspect_ratio != 1.0f) {
1029 /* Align ellipse major axis with the curve normal direction. */
1030 const AttributeDescriptor attr_descr_normal = find_attribute(kg, sd, shared_ofs2);
1031 bsdf->N = curve_attribute<float3>(kg, sd, attr_descr_normal).val;
1032 }
1033
1034 bsdf->roughness = roughness;
1035 bsdf->tilt = alpha;
1036 bsdf->eta = ior;
1037 bsdf->sigma = sigma;
1038
1039 sd->flag |= bsdf_hair_huang_setup(sd, bsdf, path_flag);
1040 }
1041 }
1042 break;
1043 }
1044# endif /* __PRINCIPLED_HAIR__ */
1047 const Spectrum weight = closure_weight * mix_weight;
1048
1050 sd, sizeof(HairBsdf), weight);
1051
1052 if (bsdf) {
1054 bsdf->roughness1 = param1;
1055 bsdf->roughness2 = param2;
1056 bsdf->offset = -stack_load_float(stack, data_node.y);
1057
1058 if (stack_valid(data_node.w)) {
1059 bsdf->T = normalize(stack_load_float3(stack, data_node.w));
1060 }
1061 else if (!(sd->type & PRIMITIVE_CURVE)) {
1062 bsdf->T = normalize(sd->dPdv);
1063 bsdf->offset = 0.0f;
1064 }
1065 else {
1066 bsdf->T = normalize(sd->dPdu);
1067 }
1068
1069 if (type == CLOSURE_BSDF_HAIR_REFLECTION_ID) {
1070 sd->flag |= bsdf_hair_reflection_setup(bsdf);
1071 }
1072 else {
1073 sd->flag |= bsdf_hair_transmission_setup(bsdf);
1074 }
1075 }
1076
1077 break;
1078 }
1079#endif /* __HAIR__ */
1080
1081#ifdef __SUBSURFACE__
1085 const Spectrum weight = closure_weight * mix_weight;
1086 ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, weight);
1087
1088 if (bssrdf) {
1089 bssrdf->radius = max(rgb_to_spectrum(stack_load_float3(stack, data_node.y) * param1),
1090 zero_spectrum());
1091 bssrdf->albedo = closure_weight;
1093 bssrdf->ior = param2;
1094 bssrdf->alpha = saturatef(stack_load_float(stack, data_node.w));
1095 bssrdf->anisotropy = stack_load_float(stack, data_node.z);
1096
1097 sd->flag |= bssrdf_setup(sd, bssrdf, path_flag, (ClosureType)type);
1098 }
1099
1100 break;
1101 }
1102#endif
1103 default:
1104 break;
1105 }
1106
1107 return offset;
1108}
1109
1111 ccl_private float *stack,
1112 Spectrum weight,
1113 const uint type,
1114 const uint param1_offset,
1115 const uint param_extra)
1116{
1117 switch (type) {
1120 bsdf_alloc(sd, sizeof(HenyeyGreensteinVolume), weight);
1121 if (volume) {
1122 volume->g = stack_valid(param1_offset) ? stack_load_float(stack, param1_offset) :
1123 __uint_as_float(param_extra);
1124 sd->flag |= volume_henyey_greenstein_setup(volume);
1125 }
1126 } break;
1129 sd, sizeof(FournierForandVolume), weight);
1130 if (volume) {
1131 const float IOR = stack_load_float(stack, param1_offset);
1132 const float B = stack_load_float(stack, param_extra);
1133 sd->flag |= volume_fournier_forand_setup(volume, B, IOR);
1134 }
1135 } break;
1138 sd, sizeof(RayleighVolume), weight);
1139 if (volume) {
1140 sd->flag |= volume_rayleigh_setup(volume);
1141 }
1142 break;
1143 }
1146 sd, sizeof(DraineVolume), weight);
1147 if (volume) {
1148 volume->g = stack_load_float(stack, param1_offset);
1149 volume->alpha = stack_load_float(stack, param_extra);
1150 sd->flag |= volume_draine_setup(volume);
1151 }
1152 } break;
1153 case CLOSURE_VOLUME_MIE_ID: {
1154 const float d = stack_valid(param1_offset) ? stack_load_float(stack, param1_offset) :
1155 __uint_as_float(param_extra);
1156 float g_HG;
1157 float g_D;
1158 float alpha;
1159 float mixture;
1160 phase_mie_fitted_parameters(d, &g_HG, &g_D, &alpha, &mixture);
1162 sd, sizeof(HenyeyGreensteinVolume), weight * (1.0f - mixture));
1163 if (hg) {
1164 hg->g = g_HG;
1165 sd->flag |= volume_henyey_greenstein_setup(hg);
1166 }
1168 sd, sizeof(DraineVolume), weight * mixture);
1169 if (draine) {
1170 draine->g = g_D;
1171 draine->alpha = alpha;
1172 sd->flag |= volume_draine_setup(draine);
1173 }
1174 } break;
1175 default: {
1176 kernel_assert(0);
1177 break;
1178 }
1179 }
1180}
1181
1182template<ShaderType shader_type>
1184 ccl_private ShaderData *sd,
1185 ccl_private float *stack,
1186 Spectrum closure_weight,
1187 const uint4 node)
1188{
1189#ifdef __VOLUME__
1190 /* Only sum extinction for volumes, variable is shared with surface transparency. */
1191 if (shader_type != SHADER_TYPE_VOLUME) {
1192 return;
1193 }
1194
1195 uint type;
1196 uint density_offset;
1197 uint param1_offset;
1198 uint mix_weight_offset;
1199 svm_unpack_node_uchar4(node.y, &type, &density_offset, &param1_offset, &mix_weight_offset);
1200 const float mix_weight = (stack_valid(mix_weight_offset) ?
1201 stack_load_float(stack, mix_weight_offset) :
1202 1.0f);
1203 if (mix_weight == 0.0f) {
1204 return;
1205 }
1206
1207 float density = (stack_valid(density_offset)) ? stack_load_float(stack, density_offset) :
1208 __uint_as_float(node.z);
1209 density = mix_weight * fmaxf(density, 0.0f) * object_volume_density(kg, sd->object);
1210
1211 /* Compute scattering coefficient. */
1212 Spectrum weight = closure_weight;
1213
1214 if (type == CLOSURE_VOLUME_ABSORPTION_ID) {
1215 weight = one_spectrum() - weight;
1216 }
1217
1218 weight *= density;
1219
1220 /* Add closure for volume scattering. */
1221 if (CLOSURE_IS_VOLUME_SCATTER(type)) {
1222 svm_alloc_closure_volume_scatter(sd, stack, weight, type, param1_offset, node.w);
1223 }
1224
1225 /* Sum total extinction weight. */
1226 volume_extinction_setup(sd, weight);
1227#endif
1228}
1229
1230template<ShaderType shader_type>
1232 ccl_private ShaderData *sd,
1233 ccl_private float *stack,
1234 Spectrum scatter_coeffs,
1235 const uint4 node,
1236 const uint32_t path_flag)
1237{
1238#ifdef __VOLUME__
1239 /* Only sum extinction for volumes, variable is shared with surface transparency. */
1240 if (shader_type != SHADER_TYPE_VOLUME) {
1241 return;
1242 }
1243
1244 uint type;
1245 uint empty_offset;
1246 uint param1_offset;
1247 uint mix_weight_offset;
1248 svm_unpack_node_uchar4(node.y, &type, &empty_offset, &param1_offset, &mix_weight_offset);
1249 const float mix_weight = (stack_valid(mix_weight_offset) ?
1250 stack_load_float(stack, mix_weight_offset) :
1251 1.0f);
1252 if (mix_weight == 0.0f) {
1253 return;
1254 }
1255
1256 /* Compute scattering coefficient. */
1257 const float weight = mix_weight * object_volume_density(kg, sd->object);
1258
1259 /* Add closure for volume scattering. */
1260 if (!is_zero(scatter_coeffs) && CLOSURE_IS_VOLUME_SCATTER(type)) {
1262 sd, stack, weight * scatter_coeffs, type, param1_offset, node.z);
1263 }
1264 uint absorption_coeffs_offset;
1265 uint emission_coeffs_offset;
1267 node.w, &absorption_coeffs_offset, &emission_coeffs_offset, &empty_offset, &empty_offset);
1268 const float3 absorption_coeffs = stack_load_float3(stack, absorption_coeffs_offset);
1269 volume_extinction_setup(sd, weight * (scatter_coeffs + absorption_coeffs));
1270
1271 const float3 emission_coeffs = stack_load_float3(stack, emission_coeffs_offset);
1272 /* Compute emission. */
1273 if (path_flag & PATH_RAY_SHADOW) {
1274 /* Don't need emission for shadows. */
1275 return;
1276 }
1277
1278 if (is_zero(emission_coeffs)) {
1279 return;
1280 }
1281 emission_setup(sd, weight * emission_coeffs);
1282
1283#endif
1284}
1285
1286template<ShaderType shader_type>
1288 ccl_private ShaderData *sd,
1289 ccl_private float *stack,
1290 const Spectrum closure_weight,
1291 const uint4 node,
1292 const uint32_t path_flag,
1293 int offset)
1294{
1295#ifdef __VOLUME__
1296 const uint4 value_node = read_node(kg, &offset);
1297 const uint4 attr_node = read_node(kg, &offset);
1298
1299 /* Only sum extinction for volumes, variable is shared with surface transparency. */
1300 if (shader_type != SHADER_TYPE_VOLUME) {
1301 return offset;
1302 }
1303
1304 uint density_offset;
1305 uint anisotropy_offset;
1306 uint absorption_color_offset;
1307 uint mix_weight_offset;
1309 node.y, &density_offset, &anisotropy_offset, &absorption_color_offset, &mix_weight_offset);
1310 const float mix_weight = (stack_valid(mix_weight_offset) ?
1311 stack_load_float(stack, mix_weight_offset) :
1312 1.0f);
1313
1314 if (mix_weight == 0.0f) {
1315 return offset;
1316 }
1317
1318 /* Compute density. */
1319 const float weight = mix_weight * object_volume_density(kg, sd->object);
1320 float primitive_density = 1.0f;
1321 float density = (stack_valid(density_offset)) ? stack_load_float(stack, density_offset) :
1322 __uint_as_float(value_node.x);
1323 density = weight * fmaxf(density, 0.0f);
1324
1325 if (density > 0.0f) {
1326 /* Density and color attribute lookup if available. */
1327 const AttributeDescriptor attr_density = find_attribute(kg, sd, attr_node.x);
1328 if (attr_density.offset != ATTR_STD_NOT_FOUND) {
1329 primitive_density = primitive_volume_attribute<float>(kg, sd, attr_density, true);
1330 density = fmaxf(density * primitive_density, 0.0f);
1331 }
1332 }
1333
1334 if (density > 0.0f) {
1335 /* Compute scattering color. */
1336 Spectrum color = closure_weight;
1337
1338 const AttributeDescriptor attr_color = find_attribute(kg, sd, attr_node.y);
1339 if (attr_color.offset != ATTR_STD_NOT_FOUND) {
1340 color *= rgb_to_spectrum(primitive_volume_attribute<float3>(kg, sd, attr_color, true));
1341 }
1342
1343 /* Add closure for volume scattering. */
1345 sd, sizeof(HenyeyGreensteinVolume), color * density);
1346 if (volume) {
1347 const float anisotropy = (stack_valid(anisotropy_offset)) ?
1348 stack_load_float(stack, anisotropy_offset) :
1349 __uint_as_float(value_node.y);
1350 volume->g = anisotropy;
1351 sd->flag |= volume_henyey_greenstein_setup(volume);
1352 }
1353
1354 /* Add extinction weight. */
1355 const float3 absorption_color = max(sqrt(stack_load_float3(stack, absorption_color_offset)),
1356 zero_float3());
1357
1358 const Spectrum zero = zero_spectrum();
1359 const Spectrum one = one_spectrum();
1360 const Spectrum absorption = max(one - color, zero) *
1361 max(one - rgb_to_spectrum(absorption_color), zero);
1362 volume_extinction_setup(sd, (color + absorption) * density);
1363 }
1364
1365 /* Compute emission. */
1366 if (path_flag & PATH_RAY_SHADOW) {
1367 /* Don't need emission for shadows. */
1368 return offset;
1369 }
1370
1371 uint emission_offset;
1372 uint emission_color_offset;
1373 uint blackbody_offset;
1374 uint temperature_offset;
1376 node.z, &emission_offset, &emission_color_offset, &blackbody_offset, &temperature_offset);
1377 const float emission = (stack_valid(emission_offset)) ?
1378 stack_load_float(stack, emission_offset) :
1379 __uint_as_float(value_node.z);
1380 const float blackbody = (stack_valid(blackbody_offset)) ?
1381 stack_load_float(stack, blackbody_offset) :
1382 __uint_as_float(value_node.w);
1383
1384 if (emission > 0.0f) {
1385 const float3 emission_color = stack_load_float3(stack, emission_color_offset);
1386 emission_setup(sd, rgb_to_spectrum(emission * emission_color * weight));
1387 }
1388
1389 if (blackbody > 0.0f) {
1390 float T = stack_load_float(stack, temperature_offset);
1391
1392 /* Add flame temperature from attribute if available. */
1393 const AttributeDescriptor attr_temperature = find_attribute(kg, sd, attr_node.z);
1394 if (attr_temperature.offset != ATTR_STD_NOT_FOUND) {
1395 const float temperature = primitive_volume_attribute<float>(kg, sd, attr_temperature, true);
1396 T *= fmaxf(temperature, 0.0f);
1397 }
1398
1399 T = fmaxf(T, 0.0f);
1400
1401 /* Stefan-Boltzmann law. */
1402 const float T4 = sqr(sqr(T));
1403 const float sigma = 5.670373e-8f * 1e-6f / M_PI_F;
1404 const float intensity = sigma * mix(1.0f, T4, blackbody);
1405
1406 if (intensity > 0.0f) {
1407 const float3 blackbody_tint = stack_load_float3(stack, node.w);
1408 const float3 bb = blackbody_tint * intensity *
1410 emission_setup(sd, rgb_to_spectrum(bb * weight));
1411 }
1412 }
1413#endif
1414 return offset;
1415}
1416
1418 ccl_private ShaderData *sd,
1419 ccl_private float *stack,
1420 Spectrum closure_weight,
1421 const uint4 node)
1422{
1423 const uint mix_weight_offset = node.y;
1424 Spectrum weight = closure_weight;
1425
1426 if (stack_valid(mix_weight_offset)) {
1427 const float mix_weight = stack_load_float(stack, mix_weight_offset);
1428
1429 if (mix_weight == 0.0f) {
1430 return;
1431 }
1432
1433 weight *= mix_weight;
1434 }
1435
1436 if (sd->flag & SD_IS_VOLUME_SHADER_EVAL) {
1437 weight *= object_volume_density(kg, sd->object);
1438 }
1439
1440 emission_setup(sd, weight);
1441}
1442
1444 ccl_private float *stack,
1445 Spectrum closure_weight,
1446 const uint4 node)
1447{
1448 const uint mix_weight_offset = node.y;
1449 Spectrum weight = closure_weight;
1450
1451 if (stack_valid(mix_weight_offset)) {
1452 const float mix_weight = stack_load_float(stack, mix_weight_offset);
1453
1454 if (mix_weight == 0.0f) {
1455 return;
1456 }
1457
1458 weight *= mix_weight;
1459 }
1460
1461 background_setup(sd, weight);
1462}
1463
1465 ccl_private float *stack,
1466 Spectrum closure_weight,
1467 const uint4 node)
1468{
1469 const uint mix_weight_offset = node.y;
1470
1471 if (stack_valid(mix_weight_offset)) {
1472 const float mix_weight = stack_load_float(stack, mix_weight_offset);
1473
1474 if (mix_weight == 0.0f) {
1475 return;
1476 }
1477
1478 closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, closure_weight * mix_weight);
1479 }
1480 else {
1481 closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, closure_weight);
1482 }
1483
1484 sd->flag |= SD_HOLDOUT;
1485}
1486
1487/* Closure Nodes */
1488
1490 const uint r,
1491 uint g,
1492 const uint b)
1493{
1494 *closure_weight = rgb_to_spectrum(
1496}
1497
1499 ccl_private Spectrum *closure_weight,
1500 const uint weight_offset)
1501{
1502 *closure_weight = rgb_to_spectrum(stack_load_float3(stack, weight_offset));
1503}
1504
1506 ccl_private Spectrum *closure_weight,
1507 const uint4 node)
1508{
1509 const uint color_offset = node.y;
1510 const uint strength_offset = node.z;
1511
1512 const float strength = (stack_valid(strength_offset)) ?
1513 stack_load_float(stack, strength_offset) :
1514 __uint_as_float(node.w);
1515 *closure_weight = rgb_to_spectrum(stack_load_float3(stack, color_offset)) * strength;
1516}
1517
1519{
1520 /* fetch weight from blend input, previous mix closures,
1521 * and write to stack to be used by closure nodes later */
1522 uint weight_offset;
1523 uint in_weight_offset;
1524 uint weight1_offset;
1525 uint weight2_offset;
1527 node.y, &weight_offset, &in_weight_offset, &weight1_offset, &weight2_offset);
1528
1529 float weight = stack_load_float(stack, weight_offset);
1530 weight = saturatef(weight);
1531
1532 const float in_weight = (stack_valid(in_weight_offset)) ?
1533 stack_load_float(stack, in_weight_offset) :
1534 1.0f;
1535
1536 if (stack_valid(weight1_offset)) {
1537 stack_store_float(stack, weight1_offset, in_weight * (1.0f - weight));
1538 }
1539 if (stack_valid(weight2_offset)) {
1540 stack_store_float(stack, weight2_offset, in_weight * weight);
1541 }
1542}
1543
1544/* (Bump) normal */
1545
1547 ccl_private float *stack,
1548 const uint in_direction,
1549 const uint out_normal)
1550{
1551 const float3 normal = stack_load_float3(stack, in_direction);
1552 sd->N = normal;
1553 stack_store_float3(stack, out_normal, normal);
1554}
1555
#define ATTR_FALLTHROUGH
unsigned int uint
static float mix_weight(float weight, float weight2, char mix_mode)
CCL_NAMESPACE_BEGIN ccl_device ccl_private ShaderClosure * closure_alloc(ccl_private ShaderData *sd, const uint size, ClosureType type, Spectrum weight)
Definition alloc.h:11
ccl_device_inline ccl_private ShaderClosure * bsdf_alloc(ccl_private ShaderData *sd, const int size, Spectrum weight)
Definition alloc.h:55
ccl_device ccl_private void * closure_alloc_extra(ccl_private ShaderData *sd, const int size)
Definition alloc.h:34
ccl_device_inline Spectrum bsdf_albedo(KernelGlobals kg, const ccl_private ShaderData *sd, const ccl_private ShaderClosure *sc, const bool reflection, const bool transmission)
Definition bsdf.h:648
CCL_NAMESPACE_BEGIN ccl_device int bsdf_ashikhmin_shirley_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device int bsdf_ashikhmin_velvet_setup(ccl_private VelvetBsdf *bsdf)
ccl_device int bsdf_translucent_setup(ccl_private DiffuseBsdf *bsdf)
ccl_device int bsdf_diffuse_setup(ccl_private DiffuseBsdf *bsdf)
ccl_device int bsdf_hair_reflection_setup(ccl_private HairBsdf *bsdf)
Definition bsdf_hair.h:27
ccl_device int bsdf_hair_transmission_setup(ccl_private HairBsdf *bsdf)
Definition bsdf_hair.h:35
ccl_device void bsdf_microfacet_setup_fresnel_f82_tint(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, const ccl_private ShaderData *sd, ccl_private FresnelF82Tint *fresnel, const Spectrum f82_tint, const bool preserve_energy)
ccl_device int bsdf_microfacet_beckmann_glass_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device int bsdf_microfacet_beckmann_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device void bsdf_microfacet_setup_fresnel_constant(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, const ccl_private ShaderData *sd, const Spectrum color)
ccl_device void bsdf_microfacet_setup_fresnel_generalized_schlick(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, const ccl_private ShaderData *sd, ccl_private FresnelGeneralizedSchlick *fresnel, const bool preserve_energy)
ccl_device void bsdf_microfacet_setup_fresnel_dielectric(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, const ccl_private ShaderData *sd)
ccl_device void bsdf_microfacet_setup_fresnel_conductor(KernelGlobals kg, ccl_private MicrofacetBsdf *bsdf, const ccl_private ShaderData *sd, ccl_private FresnelConductor *fresnel, const bool preserve_energy)
ccl_device int bsdf_microfacet_beckmann_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
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 int bsdf_microfacet_ggx_refraction_setup(ccl_private MicrofacetBsdf *bsdf)
ccl_device int bsdf_oren_nayar_setup(const ccl_private ShaderData *sd, ccl_private OrenNayarBsdf *bsdf, const Spectrum color)
ccl_device void bsdf_ray_portal_setup(ccl_private ShaderData *sd, const Spectrum weight, const float3 position, float3 direction)
ccl_device int bsdf_sheen_setup(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private SheenBsdf *bsdf)
Definition bsdf_sheen.h:27
ccl_device int bsdf_diffuse_toon_setup(ccl_private ToonBsdf *bsdf)
Definition bsdf_toon.h:35
ccl_device int bsdf_glossy_toon_setup(ccl_private ToonBsdf *bsdf)
Definition bsdf_toon.h:119
CCL_NAMESPACE_BEGIN ccl_device void bsdf_transparent_setup(ccl_private ShaderData *sd, const Spectrum weight, const uint32_t path_flag)
ccl_device float3 maybe_ensure_valid_specular_reflection(ccl_private ShaderData *sd, const float3 N)
Definition bsdf_util.h:365
ccl_device float ior_from_F0(const float f0)
Definition bsdf_util.h:250
ccl_device float F0_from_ior(const float ior)
Definition bsdf_util.h:256
ccl_device_inline Spectrum bsdf_principled_hair_sigma_from_reflectance(const Spectrum color, const float azimuthal_roughness)
Definition bsdf_util.h:386
ccl_device_inline Spectrum bsdf_principled_hair_sigma_from_concentration(const float eumelanin, const float pheomelanin)
Definition bsdf_util.h:393
ccl_device_inline Spectrum closure_layering_weight(const Spectrum layer_albedo, const Spectrum weight)
Definition bsdf_util.h:406
ccl_device_inline ccl_private Bssrdf * bssrdf_alloc(ccl_private ShaderData *sd, Spectrum weight)
Definition bssrdf.h:270
ccl_device int bssrdf_setup(ccl_private ShaderData *sd, ccl_private Bssrdf *bssrdf, const int path_flag, ClosureType type)
Definition bssrdf.h:288
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
ccl_device_noinline int svm_node_principled_volume(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, const Spectrum closure_weight, const uint4 node, const uint32_t path_flag, int offset)
Definition closure.h:1287
ccl_device_noinline void svm_node_closure_holdout(ccl_private ShaderData *sd, ccl_private float *stack, Spectrum closure_weight, const uint4 node)
Definition closure.h:1464
ccl_device_noinline void svm_node_closure_background(ccl_private ShaderData *sd, ccl_private float *stack, Spectrum closure_weight, const uint4 node)
Definition closure.h:1443
ccl_device_noinline void svm_node_volume_coefficients(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, Spectrum scatter_coeffs, const uint4 node, const uint32_t path_flag)
Definition closure.h:1231
ccl_device_inline void svm_alloc_closure_volume_scatter(ccl_private ShaderData *sd, ccl_private float *stack, Spectrum weight, const uint type, const uint param1_offset, const uint param_extra)
Definition closure.h:1110
ccl_device_noinline void svm_node_closure_emission(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, Spectrum closure_weight, const uint4 node)
Definition closure.h:1417
ccl_device void svm_node_emission_weight(ccl_private float *stack, ccl_private Spectrum *closure_weight, const uint4 node)
Definition closure.h:1505
ccl_device void svm_node_closure_set_weight(ccl_private Spectrum *closure_weight, const uint r, uint g, const uint b)
Definition closure.h:1489
ccl_device_noinline void svm_node_closure_volume(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, Spectrum closure_weight, const uint4 node)
Definition closure.h:1183
CCL_NAMESPACE_BEGIN ccl_device_inline int svm_node_closure_bsdf_skip(KernelGlobals kg, int offset, const uint type)
Definition closure.h:27
ccl_device_noinline void svm_node_mix_closure(ccl_private float *stack, const uint4 node)
Definition closure.h:1518
ccl_device void svm_node_closure_weight(ccl_private float *stack, ccl_private Spectrum *closure_weight, const uint weight_offset)
Definition closure.h:1498
ccl_device void svm_node_set_normal(ccl_private ShaderData *sd, ccl_private float *stack, const uint in_direction, const uint out_normal)
Definition closure.h:1546
ccl_device_noinline int svm_node_closure_bsdf(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private float *stack, Spectrum closure_weight, const uint4 node, const uint32_t path_flag, int offset)
Definition closure.h:45
nullptr thinfilm_thickness
dot(value.rgb, luminance_coefficients)") DEFINE_VALUE("REDUCE(lhs
ccl_device_inline float stack_load_float(const ccl_private float *stack, const uint a)
ccl_device_inline float3 stack_load_float3_default(const ccl_private float *stack, const uint a, const float3 value)
ccl_device_inline void stack_store_float(ccl_private float *stack, const uint a, const float f)
ccl_device_inline uint4 read_node(KernelGlobals kg, ccl_private int *const offset)
ccl_device_inline void stack_store_float3(ccl_private float *stack, const uint a, const float3 f)
ccl_device_inline float stack_load_float_default(const ccl_private float *stack, const uint a, const uint value)
ccl_device_forceinline void svm_unpack_node_uchar4(const uint i, ccl_private uint *x, ccl_private uint *y, ccl_private uint *z, ccl_private uint *w)
ccl_device_inline bool stack_valid(const uint a)
CCL_NAMESPACE_BEGIN ccl_device_inline float3 stack_load_float3(const ccl_private float *stack, const uint a)
#define kernel_assert(cond)
#define CLOSURE_IS_VOLUME_SCATTER(type)
#define kernel_data
#define THINFILM_THICKNESS_CUTOFF
#define IF_KERNEL_NODES_FEATURE(feature)
#define kernel_data_fetch(name, index)
#define one_spectrum
#define PRIMITIVE_UNPACK_SEGMENT(type)
#define zero_spectrum
#define make_spectrum(f)
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define SVM_STACK_INVALID
#define ccl_device_noinline
#define logf(x)
#define CCL_NAMESPACE_END
#define saturatef(x)
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define __uint_as_float(x)
#define CLOSURE_WEIGHT_CUTOFF
ccl_device void emission_setup(ccl_private ShaderData *sd, const Spectrum weight)
Definition emissive.h:29
CCL_NAMESPACE_BEGIN ccl_device void background_setup(ccl_private ShaderData *sd, const Spectrum weight)
Definition emissive.h:16
IMETHOD void random(Vector &a)
addDelta operator for displacement rotational velocity.
Definition frames.inl:1282
VecBase< float, D > normalize(VecOp< float, D >) RET
#define sqrt
constexpr T clamp(T, U, U) RET
CCL_NAMESPACE_BEGIN ccl_device void volume_extinction_setup(ccl_private ShaderData *sd, Spectrum weight)
ccl_device_inline float object_volume_density(KernelGlobals kg, const int object)
@ NODE_PRINCIPLED_HAIR_REFLECTANCE
@ NODE_PRINCIPLED_HAIR_DIRECT_ABSORPTION
@ NODE_PRINCIPLED_HAIR_PIGMENT_CONCENTRATION
@ SHADER_TYPE_SURFACE
@ SHADER_TYPE_VOLUME
ClosureType
@ CLOSURE_VOLUME_RAYLEIGH_ID
@ CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID
@ CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID
@ CLOSURE_VOLUME_MIE_ID
@ CLOSURE_BSDF_ASHIKHMIN_SHIRLEY_ID
@ CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID
@ CLOSURE_BSDF_DIFFUSE_ID
@ CLOSURE_BSSRDF_BURLEY_ID
@ CLOSURE_BSDF_PRINCIPLED_ID
@ CLOSURE_BSDF_SHEEN_ID
@ CLOSURE_BSDF_TRANSPARENT_ID
@ CLOSURE_BSDF_DIFFUSE_TOON_ID
@ CLOSURE_VOLUME_DRAINE_ID
@ CLOSURE_BSDF_MICROFACET_GGX_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID
@ CLOSURE_BSDF_HAIR_TRANSMISSION_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_GLASS_ID
@ CLOSURE_VOLUME_FOURNIER_FORAND_ID
@ CLOSURE_BSSRDF_RANDOM_WALK_ID
@ CLOSURE_BSDF_PHYSICAL_CONDUCTOR
@ CLOSURE_BSDF_HAIR_HUANG_ID
@ CLOSURE_BSDF_MICROFACET_BECKMANN_ID
@ CLOSURE_BSDF_MICROFACET_MULTI_GGX_GLASS_ID
@ CLOSURE_BSDF_F82_CONDUCTOR
@ CLOSURE_BSDF_RAY_PORTAL_ID
@ CLOSURE_HOLDOUT_ID
@ CLOSURE_BSDF_GLOSSY_TOON_ID
@ CLOSURE_BSDF_HAIR_CHIANG_ID
@ CLOSURE_VOLUME_ABSORPTION_ID
@ CLOSURE_BSDF_HAIR_REFLECTION_ID
@ CLOSURE_BSSRDF_RANDOM_WALK_SKIN_ID
@ CLOSURE_BSDF_TRANSLUCENT_ID
@ CLOSURE_BSDF_ASHIKHMIN_VELVET_ID
@ SD_IS_VOLUME_SHADER_EVAL
@ SD_BACKFACING
@ SD_HOLDOUT
@ PRIMITIVE_CURVE
@ ATTR_STD_NOT_FOUND
@ PATH_RAY_SHADOW
@ PATH_RAY_DIFFUSE
@ PATH_RAY_CAMERA
ccl_device float3 rec709_to_rgb(KernelGlobals kg, const float3 rec709)
ccl_device_inline Spectrum rgb_to_spectrum(const float3 rgb)
ccl_device_inline float2 power(const float2 v, const float e)
ccl_device_inline bool is_zero(const float2 a)
ccl_device_inline float2 safe_normalize(const float2 a)
ccl_device_inline bool isequal(const float2 a, const float2 b)
ccl_device_inline float3 safe_normalize_fallback(const float3 a, const float3 fallback)
ccl_device_inline float3 one_float3()
Definition math_float3.h:26
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
ccl_device_inline float3 rotate_around_axis(const float3 p, const float3 axis, const float angle)
ccl_device float3 svm_math_blackbody_color_rec709(const float t)
Definition math_util.h:207
#define N
#define T
#define B
#define R
#define T4
Definition md5.cpp:23
CCL_NAMESPACE_BEGIN ccl_device_forceinline dual< T > primitive_surface_attribute(KernelGlobals kg, const ccl_private ShaderData *sd, const AttributeDescriptor desc, const bool dx=false, const bool dy=false)
Definition primitive.h:32
#define mix
#define sqr
#define fabsf
#define sqrtf
#define ccl_device
#define M_2PI_F
#define fmaxf
#define M_PI_F
#define saturate(a)
Definition smaa.cc:315
#define min(a, b)
Definition sort.cc:36
closure color absorption() BUILTIN
closure color bssrdf(string method, normal N, vector radius, color albedo) BUILTIN
closure color draine(float g, float alpha) BUILTIN
static bool find_attribute(const std::string &attributes, const char *search_attribute)
FresnelThinFilm thin_film
FresnelThinFilm thin_film
uint x
Definition types_uint4.h:13
uint y
Definition types_uint4.h:13
uint z
Definition types_uint4.h:13
uint w
Definition types_uint4.h:13
max
Definition text_draw.cc:251
float3 Spectrum
ccl_device int volume_draine_setup(ccl_private DraineVolume *volume)
ccl_device int volume_fournier_forand_setup(ccl_private FournierForandVolume *volume, float B, float IOR)
ccl_device int volume_henyey_greenstein_setup(ccl_private HenyeyGreensteinVolume *volume)
ccl_device int volume_rayleigh_setup(ccl_private RayleighVolume *volume)
ccl_device void phase_mie_fitted_parameters(float d, ccl_private float *g_HG, ccl_private float *g_D, ccl_private float *alpha, ccl_private float *w)