Blender  V3.3
kernel/integrator/shader_eval.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 /* Functions to evaluate shaders and use the resulting shader closures. */
5 
6 #pragma once
7 
8 #include "kernel/closure/alloc.h"
9 #include "kernel/closure/bsdf.h"
12 
13 #include "kernel/film/accumulate.h"
14 
15 #include "kernel/svm/svm.h"
16 
17 #ifdef __OSL__
18 # include "kernel/osl/shader.h"
19 #endif
20 
22 
23 /* Merging */
24 
25 #if defined(__VOLUME__)
26 ccl_device_inline void shader_merge_volume_closures(ccl_private ShaderData *sd)
27 {
28  /* Merge identical closures to save closure space with stacked volumes. */
29  for (int i = 0; i < sd->num_closure; i++) {
30  ccl_private ShaderClosure *sci = &sd->closure[i];
31 
32  if (sci->type != CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) {
33  continue;
34  }
35 
36  for (int j = i + 1; j < sd->num_closure; j++) {
37  ccl_private ShaderClosure *scj = &sd->closure[j];
38  if (sci->type != scj->type) {
39  continue;
40  }
41 
43  sci;
45  scj;
46  if (!(hgi->g == hgj->g)) {
47  continue;
48  }
49 
50  sci->weight += scj->weight;
51  sci->sample_weight += scj->sample_weight;
52 
53  int size = sd->num_closure - (j + 1);
54  if (size > 0) {
55  for (int k = 0; k < size; k++) {
56  scj[k] = scj[k + 1];
57  }
58  }
59 
60  sd->num_closure--;
61  kernel_assert(sd->num_closure >= 0);
62  j--;
63  }
64  }
65 }
66 
67 ccl_device_inline void shader_copy_volume_phases(ccl_private ShaderVolumePhases *ccl_restrict
68  phases,
70 {
71  phases->num_closure = 0;
72 
73  for (int i = 0; i < sd->num_closure; i++) {
74  ccl_private const ShaderClosure *from_sc = &sd->closure[i];
75  ccl_private const HenyeyGreensteinVolume *from_hg =
76  (ccl_private const HenyeyGreensteinVolume *)from_sc;
77 
78  if (from_sc->type == CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID) {
79  ccl_private ShaderVolumeClosure *to_sc = &phases->closure[phases->num_closure];
80 
81  to_sc->weight = from_sc->weight;
82  to_sc->sample_weight = from_sc->sample_weight;
83  to_sc->g = from_hg->g;
84  phases->num_closure++;
85  if (phases->num_closure >= MAX_VOLUME_CLOSURE) {
86  break;
87  }
88  }
89  }
90 }
91 #endif /* __VOLUME__ */
92 
96  const uint32_t path_flag)
97 {
98  /* Filter out closures. */
99  if (kernel_data.integrator.filter_closures) {
100  if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_EMISSION) {
101  sd->closure_emission_background = zero_float3();
102  }
103 
104  if (kernel_data.integrator.filter_closures & FILTER_CLOSURE_DIRECT_LIGHT) {
105  sd->flag &= ~SD_BSDF_HAS_EVAL;
106  }
107 
108  if (path_flag & PATH_RAY_CAMERA) {
109  for (int i = 0; i < sd->num_closure; i++) {
110  ccl_private ShaderClosure *sc = &sd->closure[i];
111 
112  if ((CLOSURE_IS_BSDF_DIFFUSE(sc->type) &&
113  (kernel_data.integrator.filter_closures & FILTER_CLOSURE_DIFFUSE)) ||
114  (CLOSURE_IS_BSDF_GLOSSY(sc->type) &&
115  (kernel_data.integrator.filter_closures & FILTER_CLOSURE_GLOSSY)) ||
116  (CLOSURE_IS_BSDF_TRANSMISSION(sc->type) &&
117  (kernel_data.integrator.filter_closures & FILTER_CLOSURE_TRANSMISSION))) {
118  sc->type = CLOSURE_NONE_ID;
119  sc->sample_weight = 0.0f;
120  }
121  else if ((CLOSURE_IS_BSDF_TRANSPARENT(sc->type) &&
122  (kernel_data.integrator.filter_closures & FILTER_CLOSURE_TRANSPARENT))) {
123  sc->type = CLOSURE_HOLDOUT_ID;
124  sc->sample_weight = 0.0f;
125  sd->flag |= SD_HOLDOUT;
126  }
127  }
128  }
129  }
130 
131  /* Defensive sampling.
132  *
133  * We can likely also do defensive sampling at deeper bounces, particularly
134  * for cases like a perfect mirror but possibly also others. This will need
135  * a good heuristic. */
136  if (INTEGRATOR_STATE(state, path, bounce) + INTEGRATOR_STATE(state, path, transparent_bounce) ==
137  0 &&
138  sd->num_closure > 1) {
139  float sum = 0.0f;
140 
141  for (int i = 0; i < sd->num_closure; i++) {
142  ccl_private ShaderClosure *sc = &sd->closure[i];
143  if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
144  sum += sc->sample_weight;
145  }
146  }
147 
148  for (int i = 0; i < sd->num_closure; i++) {
149  ccl_private ShaderClosure *sc = &sd->closure[i];
150  if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
151  sc->sample_weight = max(sc->sample_weight, 0.125f * sum);
152  }
153  }
154  }
155 
156  /* Filter glossy.
157  *
158  * Blurring of bsdf after bounces, for rays that have a small likelihood
159  * of following this particular path (diffuse, rough glossy) */
160  if (kernel_data.integrator.filter_glossy != FLT_MAX
161 #ifdef __MNEE__
162  && !(INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_VALID)
163 #endif
164  ) {
165  float blur_pdf = kernel_data.integrator.filter_glossy *
166  INTEGRATOR_STATE(state, path, min_ray_pdf);
167 
168  if (blur_pdf < 1.0f) {
169  float blur_roughness = sqrtf(1.0f - blur_pdf) * 0.5f;
170 
171  for (int i = 0; i < sd->num_closure; i++) {
172  ccl_private ShaderClosure *sc = &sd->closure[i];
173  if (CLOSURE_IS_BSDF(sc->type)) {
174  bsdf_blur(kg, sc, blur_roughness);
175  }
176  }
177  }
178  }
179 }
180 
181 /* BSDF */
182 
184  const float3 omega_in)
185 {
186  return dot(sd->N, omega_in) < 0.0f;
187 }
188 
190 {
191  if (!(light_shader_flags & SHADER_EXCLUDE_ANY)) {
192  return false;
193  }
194  if (light_shader_flags & SHADER_EXCLUDE_DIFFUSE) {
196  return true;
197  }
198  }
199  if (light_shader_flags & SHADER_EXCLUDE_GLOSSY) {
201  return true;
202  }
203  }
204  if (light_shader_flags & SHADER_EXCLUDE_TRANSMIT) {
206  return true;
207  }
208  }
209  return false;
210 }
211 
214  const float3 omega_in,
215  const bool is_transmission,
216  ccl_private const ShaderClosure *skip_sc,
217  ccl_private BsdfEval *result_eval,
218  float sum_pdf,
219  float sum_sample_weight,
220  const uint light_shader_flags)
221 {
222  /* This is the veach one-sample model with balance heuristic,
223  * some PDF factors drop out when using balance heuristic weighting. */
224  for (int i = 0; i < sd->num_closure; i++) {
225  ccl_private const ShaderClosure *sc = &sd->closure[i];
226 
227  if (sc == skip_sc) {
228  continue;
229  }
230 
231  if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
232  if (CLOSURE_IS_BSDF(sc->type) && !_shader_bsdf_exclude(sc->type, light_shader_flags)) {
233  float bsdf_pdf = 0.0f;
234  float3 eval = bsdf_eval(kg, sd, sc, omega_in, is_transmission, &bsdf_pdf);
235 
236  if (bsdf_pdf != 0.0f) {
237  bsdf_eval_accum(result_eval, sc->type, eval * sc->weight);
238  sum_pdf += bsdf_pdf * sc->sample_weight;
239  }
240  }
241 
242  sum_sample_weight += sc->sample_weight;
243  }
244  }
245 
246  return (sum_sample_weight > 0.0f) ? sum_pdf / sum_sample_weight : 0.0f;
247 }
248 
249 #ifndef __KERNEL_CUDA__
251 #else
253 #endif
254  float
257  const float3 omega_in,
258  const bool is_transmission,
260  const uint light_shader_flags)
261 {
263 
265  kg, sd, omega_in, is_transmission, NULL, bsdf_eval, 0.0f, 0.0f, light_shader_flags);
266 }
267 
268 /* Randomly sample a BSSRDF or BSDF proportional to ShaderClosure.sample_weight. */
270  ccl_private const ShaderData *ccl_restrict sd, ccl_private float *randu)
271 {
272  int sampled = 0;
273 
274  if (sd->num_closure > 1) {
275  /* Pick a BSDF or based on sample weights. */
276  float sum = 0.0f;
277 
278  for (int i = 0; i < sd->num_closure; i++) {
279  ccl_private const ShaderClosure *sc = &sd->closure[i];
280 
281  if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
282  sum += sc->sample_weight;
283  }
284  }
285 
286  float r = (*randu) * sum;
287  float partial_sum = 0.0f;
288 
289  for (int i = 0; i < sd->num_closure; i++) {
290  ccl_private const ShaderClosure *sc = &sd->closure[i];
291 
292  if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
293  float next_sum = partial_sum + sc->sample_weight;
294 
295  if (r < next_sum) {
296  sampled = i;
297 
298  /* Rescale to reuse for direction sample, to better preserve stratification. */
299  *randu = (r - partial_sum) / sc->sample_weight;
300  break;
301  }
302 
303  partial_sum = next_sum;
304  }
305  }
306  }
307 
308  return &sd->closure[sampled];
309 }
310 
311 /* Return weight for picked BSSRDF. */
314  ccl_private const ShaderClosure *ccl_restrict bssrdf_sc)
315 {
316  float3 weight = bssrdf_sc->weight;
317 
318  if (sd->num_closure > 1) {
319  float sum = 0.0f;
320  for (int i = 0; i < sd->num_closure; i++) {
321  ccl_private const ShaderClosure *sc = &sd->closure[i];
322 
323  if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type)) {
324  sum += sc->sample_weight;
325  }
326  }
327  weight *= sum / bssrdf_sc->sample_weight;
328  }
329 
330  return weight;
331 }
332 
333 /* Sample direction for picked BSDF, and return evaluation and pdf for all
334  * BSDFs combined using MIS. */
337  ccl_private const ShaderClosure *sc,
338  float randu,
339  float randv,
341  ccl_private float3 *omega_in,
342  ccl_private differential3 *domega_in,
343  ccl_private float *pdf)
344 {
345  /* BSSRDF should already have been handled elsewhere. */
346  kernel_assert(CLOSURE_IS_BSDF(sc->type));
347 
348  int label;
349  float3 eval = zero_float3();
350 
351  *pdf = 0.0f;
352  label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
353 
354  if (*pdf != 0.0f) {
355  bsdf_eval_init(bsdf_eval, sc->type, eval * sc->weight);
356 
357  if (sd->num_closure > 1) {
358  const bool is_transmission = shader_bsdf_is_transmission(sd, *omega_in);
359  float sweight = sc->sample_weight;
361  kg, sd, *omega_in, is_transmission, sc, bsdf_eval, *pdf * sweight, sweight, 0);
362  }
363  }
364 
365  return label;
366 }
367 
369 {
370  float roughness = 0.0f;
371  float sum_weight = 0.0f;
372 
373  for (int i = 0; i < sd->num_closure; i++) {
374  ccl_private const ShaderClosure *sc = &sd->closure[i];
375 
376  if (CLOSURE_IS_BSDF(sc->type)) {
377  /* sqrt once to undo the squaring from multiplying roughness on the
378  * two axes, and once for the squared roughness convention. */
379  float weight = fabsf(average(sc->weight));
381  sum_weight += weight;
382  }
383  }
384 
385  return (sum_weight > 0.0f) ? roughness / sum_weight : 0.0f;
386 }
387 
389 {
390  if (sd->flag & SD_HAS_ONLY_VOLUME) {
391  return one_float3();
392  }
393  else if (sd->flag & SD_TRANSPARENT) {
394  return sd->closure_transparent_extinction;
395  }
396  else {
397  return zero_float3();
398  }
399 }
400 
402 {
403  if (sd->flag & SD_TRANSPARENT) {
404  for (int i = 0; i < sd->num_closure; i++) {
405  ccl_private ShaderClosure *sc = &sd->closure[i];
406 
407  if (sc->type == CLOSURE_BSDF_TRANSPARENT_ID) {
408  sc->sample_weight = 0.0f;
409  sc->weight = zero_float3();
410  }
411  }
412 
413  sd->flag &= ~SD_TRANSPARENT;
414  }
415 }
416 
418 {
419  float3 alpha = one_float3() - shader_bsdf_transparency(kg, sd);
420 
421  alpha = max(alpha, zero_float3());
422  alpha = min(alpha, one_float3());
423 
424  return alpha;
425 }
426 
428 {
429  float3 eval = zero_float3();
430 
431  for (int i = 0; i < sd->num_closure; i++) {
432  ccl_private const ShaderClosure *sc = &sd->closure[i];
433 
434  if (CLOSURE_IS_BSDF_DIFFUSE(sc->type) || CLOSURE_IS_BSSRDF(sc->type))
435  eval += sc->weight;
436  }
437 
438  return eval;
439 }
440 
442 {
443  float3 eval = zero_float3();
444 
445  for (int i = 0; i < sd->num_closure; i++) {
446  ccl_private const ShaderClosure *sc = &sd->closure[i];
447 
448  if (CLOSURE_IS_BSDF_GLOSSY(sc->type))
449  eval += sc->weight;
450  }
451 
452  return eval;
453 }
454 
456 {
457  float3 eval = zero_float3();
458 
459  for (int i = 0; i < sd->num_closure; i++) {
460  ccl_private const ShaderClosure *sc = &sd->closure[i];
461 
462  if (CLOSURE_IS_BSDF_TRANSMISSION(sc->type))
463  eval += sc->weight;
464  }
465 
466  return eval;
467 }
468 
470 {
471  float3 N = zero_float3();
472 
473  for (int i = 0; i < sd->num_closure; i++) {
474  ccl_private const ShaderClosure *sc = &sd->closure[i];
475  if (CLOSURE_IS_BSDF_OR_BSSRDF(sc->type))
476  N += sc->N * fabsf(average(sc->weight));
477  }
478 
479  return (is_zero(N)) ? sd->N : normalize(N);
480 }
481 
483  ccl_private const ShaderData *sd,
484  const float ao_factor,
486 {
487  float3 eval = zero_float3();
488  float3 N = zero_float3();
489 
490  for (int i = 0; i < sd->num_closure; i++) {
491  ccl_private const ShaderClosure *sc = &sd->closure[i];
492 
493  if (CLOSURE_IS_BSDF_DIFFUSE(sc->type)) {
494  ccl_private const DiffuseBsdf *bsdf = (ccl_private const DiffuseBsdf *)sc;
495  eval += sc->weight * ao_factor;
496  N += bsdf->N * fabsf(average(sc->weight));
497  }
498  }
499 
500  *N_ = (is_zero(N)) ? sd->N : normalize(N);
501  return eval;
502 }
503 
504 #ifdef __SUBSURFACE__
505 ccl_device float3 shader_bssrdf_normal(ccl_private const ShaderData *sd)
506 {
507  float3 N = zero_float3();
508 
509  for (int i = 0; i < sd->num_closure; i++) {
510  ccl_private const ShaderClosure *sc = &sd->closure[i];
511 
512  if (CLOSURE_IS_BSSRDF(sc->type)) {
513  ccl_private const Bssrdf *bssrdf = (ccl_private const Bssrdf *)sc;
514  float avg_weight = fabsf(average(sc->weight));
515 
516  N += bssrdf->N * avg_weight;
517  }
518  }
519 
520  return (is_zero(N)) ? sd->N : normalize(N);
521 }
522 #endif /* __SUBSURFACE__ */
523 
524 /* Constant emission optimization */
525 
527  int shader,
528  ccl_private float3 *eval)
529 {
530  int shader_index = shader & SHADER_MASK;
531  int shader_flag = kernel_data_fetch(shaders, shader_index).flags;
532 
533  if (shader_flag & SD_HAS_CONSTANT_EMISSION) {
534  *eval = make_float3(kernel_data_fetch(shaders, shader_index).constant_emission[0],
535  kernel_data_fetch(shaders, shader_index).constant_emission[1],
536  kernel_data_fetch(shaders, shader_index).constant_emission[2]);
537 
538  return true;
539  }
540 
541  return false;
542 }
543 
544 /* Background */
545 
547 {
548  if (sd->flag & SD_EMISSION) {
549  return sd->closure_emission_background;
550  }
551  else {
552  return zero_float3();
553  }
554 }
555 
556 /* Emission */
557 
559 {
560  if (sd->flag & SD_EMISSION) {
561  return emissive_simple_eval(sd->Ng, sd->I) * sd->closure_emission_background;
562  }
563  else {
564  return zero_float3();
565  }
566 }
567 
568 /* Holdout */
569 
571 {
572  float3 weight = zero_float3();
573 
574  /* For objects marked as holdout, preserve transparency and remove all other
575  * closures, replacing them with a holdout weight. */
576  if (sd->object_flag & SD_OBJECT_HOLDOUT_MASK) {
577  if ((sd->flag & SD_TRANSPARENT) && !(sd->flag & SD_HAS_ONLY_VOLUME)) {
578  weight = one_float3() - sd->closure_transparent_extinction;
579 
580  for (int i = 0; i < sd->num_closure; i++) {
581  ccl_private ShaderClosure *sc = &sd->closure[i];
582  if (!CLOSURE_IS_BSDF_TRANSPARENT(sc->type)) {
583  sc->type = NBUILTIN_CLOSURES;
584  }
585  }
586 
587  sd->flag &= ~(SD_CLOSURE_FLAGS - (SD_TRANSPARENT | SD_BSDF));
588  }
589  else {
590  weight = one_float3();
591  }
592  }
593  else {
594  for (int i = 0; i < sd->num_closure; i++) {
595  ccl_private const ShaderClosure *sc = &sd->closure[i];
596  if (CLOSURE_IS_HOLDOUT(sc->type)) {
597  weight += sc->weight;
598  }
599  }
600  }
601 
602  return weight;
603 }
604 
605 /* Surface Evaluation */
606 
607 template<uint node_feature_mask, typename ConstIntegratorGenericState>
609  ConstIntegratorGenericState state,
612  uint32_t path_flag,
613  bool use_caustics_storage = false)
614 {
615  /* If path is being terminated, we are tracing a shadow ray or evaluating
616  * emission, then we don't need to store closures. The emission and shadow
617  * shader data also do not have a closure array to save GPU memory. */
618  int max_closures;
619  if (path_flag & (PATH_RAY_TERMINATE | PATH_RAY_SHADOW | PATH_RAY_EMISSION)) {
620  max_closures = 0;
621  }
622  else {
623  max_closures = use_caustics_storage ? CAUSTICS_MAX_CLOSURE : kernel_data.max_closures;
624  }
625 
626  sd->num_closure = 0;
627  sd->num_closure_left = max_closures;
628 
629 #ifdef __OSL__
630  if (kg->osl) {
631  if (sd->object == OBJECT_NONE && sd->lamp == LAMP_NONE) {
632  OSLShader::eval_background(kg, state, sd, path_flag);
633  }
634  else {
635  OSLShader::eval_surface(kg, state, sd, path_flag);
636  }
637  }
638  else
639 #endif
640  {
641 #ifdef __SVM__
642  svm_eval_nodes<node_feature_mask, SHADER_TYPE_SURFACE>(kg, state, sd, buffer, path_flag);
643 #else
644  if (sd->object == OBJECT_NONE) {
645  sd->closure_emission_background = make_float3(0.8f, 0.8f, 0.8f);
646  sd->flag |= SD_EMISSION;
647  }
648  else {
650  sd, sizeof(DiffuseBsdf), make_float3(0.8f, 0.8f, 0.8f));
651  if (bsdf != NULL) {
652  bsdf->N = sd->N;
653  sd->flag |= bsdf_diffuse_setup(bsdf);
654  }
655  }
656 #endif
657  }
658 }
659 
660 /* Volume */
661 
662 #ifdef __VOLUME__
663 
664 ccl_device_inline float _shader_volume_phase_multi_eval(
665  ccl_private const ShaderData *sd,
666  ccl_private const ShaderVolumePhases *phases,
667  const float3 omega_in,
668  int skip_phase,
669  ccl_private BsdfEval *result_eval,
670  float sum_pdf,
671  float sum_sample_weight)
672 {
673  for (int i = 0; i < phases->num_closure; i++) {
674  if (i == skip_phase)
675  continue;
676 
677  ccl_private const ShaderVolumeClosure *svc = &phases->closure[i];
678  float phase_pdf = 0.0f;
679  float3 eval = volume_phase_eval(sd, svc, omega_in, &phase_pdf);
680 
681  if (phase_pdf != 0.0f) {
683  sum_pdf += phase_pdf * svc->sample_weight;
684  }
685 
686  sum_sample_weight += svc->sample_weight;
687  }
688 
689  return (sum_sample_weight > 0.0f) ? sum_pdf / sum_sample_weight : 0.0f;
690 }
691 
692 ccl_device float shader_volume_phase_eval(KernelGlobals kg,
693  ccl_private const ShaderData *sd,
694  ccl_private const ShaderVolumePhases *phases,
695  const float3 omega_in,
696  ccl_private BsdfEval *phase_eval)
697 {
699 
700  return _shader_volume_phase_multi_eval(sd, phases, omega_in, -1, phase_eval, 0.0f, 0.0f);
701 }
702 
703 ccl_device int shader_volume_phase_sample(KernelGlobals kg,
704  ccl_private const ShaderData *sd,
705  ccl_private const ShaderVolumePhases *phases,
706  float randu,
707  float randv,
708  ccl_private BsdfEval *phase_eval,
709  ccl_private float3 *omega_in,
710  ccl_private differential3 *domega_in,
711  ccl_private float *pdf)
712 {
713  int sampled = 0;
714 
715  if (phases->num_closure > 1) {
716  /* pick a phase closure based on sample weights */
717  float sum = 0.0f;
718 
719  for (sampled = 0; sampled < phases->num_closure; sampled++) {
720  ccl_private const ShaderVolumeClosure *svc = &phases->closure[sampled];
721  sum += svc->sample_weight;
722  }
723 
724  float r = randu * sum;
725  float partial_sum = 0.0f;
726 
727  for (sampled = 0; sampled < phases->num_closure; sampled++) {
728  ccl_private const ShaderVolumeClosure *svc = &phases->closure[sampled];
729  float next_sum = partial_sum + svc->sample_weight;
730 
731  if (r <= next_sum) {
732  /* Rescale to reuse for BSDF direction sample. */
733  randu = (r - partial_sum) / svc->sample_weight;
734  break;
735  }
736 
737  partial_sum = next_sum;
738  }
739 
740  if (sampled == phases->num_closure) {
741  *pdf = 0.0f;
742  return LABEL_NONE;
743  }
744  }
745 
746  /* todo: this isn't quite correct, we don't weight anisotropy properly
747  * depending on color channels, even if this is perhaps not a common case */
748  ccl_private const ShaderVolumeClosure *svc = &phases->closure[sampled];
749  int label;
750  float3 eval = zero_float3();
751 
752  *pdf = 0.0f;
753  label = volume_phase_sample(sd, svc, randu, randv, &eval, omega_in, domega_in, pdf);
754 
755  if (*pdf != 0.0f) {
757  }
758 
759  return label;
760 }
761 
762 ccl_device int shader_phase_sample_closure(KernelGlobals kg,
763  ccl_private const ShaderData *sd,
765  float randu,
766  float randv,
767  ccl_private BsdfEval *phase_eval,
768  ccl_private float3 *omega_in,
769  ccl_private differential3 *domega_in,
770  ccl_private float *pdf)
771 {
772  int label;
773  float3 eval = zero_float3();
774 
775  *pdf = 0.0f;
776  label = volume_phase_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf);
777 
778  if (*pdf != 0.0f)
780 
781  return label;
782 }
783 
784 /* Volume Evaluation */
785 
786 template<const bool shadow, typename StackReadOp, typename ConstIntegratorGenericState>
787 ccl_device_inline void shader_eval_volume(KernelGlobals kg,
788  ConstIntegratorGenericState state,
790  const uint32_t path_flag,
791  StackReadOp stack_read)
792 {
793  /* If path is being terminated, we are tracing a shadow ray or evaluating
794  * emission, then we don't need to store closures. The emission and shadow
795  * shader data also do not have a closure array to save GPU memory. */
796  int max_closures;
797  if (path_flag & (PATH_RAY_TERMINATE | PATH_RAY_SHADOW | PATH_RAY_EMISSION)) {
798  max_closures = 0;
799  }
800  else {
801  max_closures = kernel_data.max_closures;
802  }
803 
804  /* reset closures once at the start, we will be accumulating the closures
805  * for all volumes in the stack into a single array of closures */
806  sd->num_closure = 0;
807  sd->num_closure_left = max_closures;
808  sd->flag = 0;
809  sd->object_flag = 0;
810 
811  for (int i = 0;; i++) {
812  const VolumeStack entry = stack_read(i);
813  if (entry.shader == SHADER_NONE) {
814  break;
815  }
816 
817  /* Setup shader-data from stack. it's mostly setup already in
818  * shader_setup_from_volume, this switching should be quick. */
819  sd->object = entry.object;
820  sd->lamp = LAMP_NONE;
821  sd->shader = entry.shader;
822 
823  sd->flag &= ~SD_SHADER_FLAGS;
824  sd->flag |= kernel_data_fetch(shaders, (sd->shader & SHADER_MASK)).flags;
825  sd->object_flag &= ~SD_OBJECT_FLAGS;
826 
827  if (sd->object != OBJECT_NONE) {
828  sd->object_flag |= kernel_data_fetch(object_flag, sd->object);
829 
830 # ifdef __OBJECT_MOTION__
831  /* todo: this is inefficient for motion blur, we should be
832  * caching matrices instead of recomputing them each step */
833  shader_setup_object_transforms(kg, sd, sd->time);
834 
835  if ((sd->object_flag & SD_OBJECT_HAS_VOLUME_MOTION) != 0) {
838 
839  const float3 P = sd->P;
840  const float velocity_scale = kernel_data_fetch(objects, sd->object).velocity_scale;
841  const float time_offset = kernel_data.cam.motion_position == MOTION_POSITION_CENTER ?
842  0.5f :
843  0.0f;
844  const float time = kernel_data.cam.motion_position == MOTION_POSITION_END ?
845  (1.0f - kernel_data.cam.shuttertime) + sd->time :
846  sd->time;
847 
848  /* Use a 1st order semi-lagrangian advection scheme to estimate what volume quantity
849  * existed, or will exist, at the given time:
850  *
851  * `phi(x, T) = phi(x - (T - t) * u(x, T), t)`
852  *
853  * where
854  *
855  * x : position
856  * T : super-sampled time (or ray time)
857  * t : current time of the simulation (in rendering we assume this is center frame with
858  * relative time = 0)
859  * phi : the volume quantity
860  * u : the velocity field
861  *
862  * But first we need to determine the velocity field `u(x, T)`, which we can estimate also
863  * using semi-lagrangian advection.
864  *
865  * `u(x, T) = u(x - (T - t) * u(x, T), t)`
866  *
867  * This is the typical way to model self-advection in fluid dynamics, however, we do not
868  * account for other forces affecting the velocity during simulation (pressure, buoyancy,
869  * etc.): this gives a linear interpolation when fluid are mostly "curvy". For better
870  * results, a higher order interpolation scheme can be used (at the cost of more lookups),
871  * or an interpolation of the velocity fields for the previous and next frames could also
872  * be used to estimate `u(x, T)` (which will cost more memory and lookups).
873  *
874  * References:
875  * "Eulerian Motion Blur", Kim and Ko, 2007
876  * "Production Volume Rendering", Wreninge et al., 2012
877  */
878 
879  /* Find velocity. */
880  float3 velocity = primitive_volume_attribute_float3(kg, sd, v_desc);
881  object_dir_transform(kg, sd, &velocity);
882 
883  /* Find advected P. */
884  sd->P = P - (time - time_offset) * velocity_scale * velocity;
885 
886  /* Find advected velocity. */
887  velocity = primitive_volume_attribute_float3(kg, sd, v_desc);
888  object_dir_transform(kg, sd, &velocity);
889 
890  /* Find advected P. */
891  sd->P = P - (time - time_offset) * velocity_scale * velocity;
892  }
893 # endif
894  }
895 
896  /* evaluate shader */
897 # ifdef __SVM__
898 # ifdef __OSL__
899  if (kg->osl) {
900  OSLShader::eval_volume(kg, state, sd, path_flag);
901  }
902  else
903 # endif
904  {
905  svm_eval_nodes<KERNEL_FEATURE_NODE_MASK_VOLUME, SHADER_TYPE_VOLUME>(
906  kg, state, sd, NULL, path_flag);
907  }
908 # endif
909 
910  /* Merge closures to avoid exceeding number of closures limit. */
911  if (!shadow) {
912  if (i > 0) {
913  shader_merge_volume_closures(sd);
914  }
915  }
916  }
917 }
918 
919 #endif /* __VOLUME__ */
920 
921 /* Displacement Evaluation */
922 
923 template<typename ConstIntegratorGenericState>
925  ConstIntegratorGenericState state,
927 {
928  sd->num_closure = 0;
929  sd->num_closure_left = 0;
930 
931  /* this will modify sd->P */
932 #ifdef __SVM__
933 # ifdef __OSL__
934  if (kg->osl)
936  else
937 # endif
938  {
939  svm_eval_nodes<KERNEL_FEATURE_NODE_MASK_DISPLACEMENT, SHADER_TYPE_DISPLACEMENT>(
940  kg, state, sd, NULL, 0);
941  }
942 #endif
943 }
944 
945 /* Cryptomatte */
946 
948 {
949  return kernel_data_fetch(shaders, (shader & SHADER_MASK)).cryptomatte_id;
950 }
951 
MINLINE float safe_sqrtf(float a)
unsigned int uint
Definition: BLI_sys_types.h:67
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble GLdouble r _GL_VOID_RET _GL_VOID GLfloat GLfloat r _GL_VOID_RET _GL_VOID GLint GLint r _GL_VOID_RET _GL_VOID GLshort GLshort r _GL_VOID_RET _GL_VOID GLdouble GLdouble r
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
ccl_device_inline void bsdf_eval_accum(ccl_private BsdfEval *eval, const ClosureType closure_type, float3 value)
Definition: accumulate.h:39
CCL_NAMESPACE_BEGIN ccl_device_inline void bsdf_eval_init(ccl_private BsdfEval *eval, const ClosureType closure_type, float3 value)
Definition: accumulate.h:22
ccl_device_inline ccl_private ShaderClosure * bsdf_alloc(ccl_private ShaderData *sd, int size, float3 weight)
Definition: alloc.h:50
ccl_device_inline int bsdf_sample(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private const ShaderClosure *sc, float randu, float randv, ccl_private float3 *eval, ccl_private float3 *omega_in, ccl_private differential3 *domega_in, ccl_private float *pdf)
Definition: bsdf.h:101
ccl_device_inline float bsdf_get_roughness_squared(ccl_private const ShaderClosure *sc)
Definition: bsdf.h:45
ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float roughness)
Definition: bsdf.h:650
ccl_device float3 bsdf_eval(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private const ShaderClosure *sc, const float3 omega_in, const bool is_transmission, ccl_private float *pdf)
Definition: bsdf.h:462
ccl_device int bsdf_diffuse_setup(ccl_private DiffuseBsdf *bsdf)
Definition: bsdf_diffuse.h:23
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
static T sum(const btAlignedObjectArray< T > &items)
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#define ccl_restrict
Definition: cuda/compat.h:50
#define ccl_device_forceinline
Definition: cuda/compat.h:35
#define ccl_device
Definition: cuda/compat.h:32
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_device_inline
Definition: cuda/compat.h:34
#define ccl_global
Definition: cuda/compat.h:43
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
double time
const char * label
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
ccl_device float3 emissive_simple_eval(const float3 Ng, const float3 I)
Definition: emissive.h:57
ccl_device int volume_phase_sample(ccl_private const ShaderData *sd, ccl_private const ShaderVolumeClosure *svc, float randu, float randv, ccl_private float3 *eval, ccl_private float3 *omega_in, ccl_private differential3 *domega_in, ccl_private float *pdf)
ccl_device float3 volume_phase_eval(ccl_private const ShaderData *sd, ccl_private const ShaderVolumeClosure *svc, float3 omega_in, ccl_private float *pdf)
ccl_global float * buffer
const int state
ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals kg, ccl_private const ShaderData *sd, uint id)
ccl_device_inline void object_dir_transform(KernelGlobals kg, ccl_private const ShaderData *sd, ccl_private float3 *D)
ccl_device float3 shader_bsdf_average_normal(KernelGlobals kg, ccl_private const ShaderData *sd)
ccl_device void shader_bsdf_disable_transparency(KernelGlobals kg, ccl_private ShaderData *sd)
ccl_device_inline float3 shader_bssrdf_sample_weight(ccl_private const ShaderData *ccl_restrict sd, ccl_private const ShaderClosure *ccl_restrict bssrdf_sc)
ccl_device float shader_bsdf_average_roughness(ccl_private const ShaderData *sd)
ccl_device float shader_cryptomatte_id(KernelGlobals kg, int shader)
ccl_device void shader_eval_displacement(KernelGlobals kg, ConstIntegratorGenericState state, ccl_private ShaderData *sd)
ccl_device float3 shader_emissive_eval(ccl_private const ShaderData *sd)
ccl_device void shader_eval_surface(KernelGlobals kg, ConstIntegratorGenericState state, ccl_private ShaderData *ccl_restrict sd, ccl_global float *ccl_restrict buffer, uint32_t path_flag, bool use_caustics_storage=false)
ccl_device float3 shader_bsdf_transparency(KernelGlobals kg, ccl_private const ShaderData *sd)
ccl_device float3 shader_background_eval(ccl_private const ShaderData *sd)
ccl_device_inline ccl_private const ShaderClosure * shader_bsdf_bssrdf_pick(ccl_private const ShaderData *ccl_restrict sd, ccl_private float *randu)
ccl_device_inline float _shader_bsdf_multi_eval(KernelGlobals kg, ccl_private ShaderData *sd, const float3 omega_in, const bool is_transmission, ccl_private const ShaderClosure *skip_sc, ccl_private BsdfEval *result_eval, float sum_pdf, float sum_sample_weight, const uint light_shader_flags)
ccl_device float3 shader_bsdf_transmission(KernelGlobals kg, ccl_private const ShaderData *sd)
ccl_device_inline bool shader_bsdf_is_transmission(ccl_private const ShaderData *sd, const float3 omega_in)
ccl_device float3 shader_bsdf_ao(KernelGlobals kg, ccl_private const ShaderData *sd, const float ao_factor, ccl_private float3 *N_)
ccl_device float3 shader_bsdf_diffuse(KernelGlobals kg, ccl_private const ShaderData *sd)
ccl_device_forceinline bool _shader_bsdf_exclude(ClosureType type, uint light_shader_flags)
ccl_device bool shader_constant_emission_eval(KernelGlobals kg, int shader, ccl_private float3 *eval)
ccl_device float3 shader_bsdf_glossy(KernelGlobals kg, ccl_private const ShaderData *sd)
ccl_device float shader_bsdf_eval(KernelGlobals kg, ccl_private ShaderData *sd, const float3 omega_in, const bool is_transmission, ccl_private BsdfEval *bsdf_eval, const uint light_shader_flags)
ccl_device float3 shader_holdout_apply(KernelGlobals kg, ccl_private ShaderData *sd)
ccl_device float3 shader_bsdf_alpha(KernelGlobals kg, ccl_private const ShaderData *sd)
ccl_device int shader_bsdf_sample_closure(KernelGlobals kg, ccl_private ShaderData *sd, ccl_private const ShaderClosure *sc, float randu, float randv, ccl_private BsdfEval *bsdf_eval, ccl_private float3 *omega_in, ccl_private differential3 *domega_in, ccl_private float *pdf)
CCL_NAMESPACE_BEGIN ccl_device_inline void shader_prepare_surface_closures(KernelGlobals kg, ConstIntegratorState state, ccl_private ShaderData *sd, const uint32_t path_flag)
#define CLOSURE_IS_HOLDOUT(type)
#define CLOSURE_IS_BSDF_TRANSPARENT(type)
#define CLOSURE_IS_BSDF_TRANSMISSION(type)
#define CLOSURE_IS_BSDF(type)
#define CLOSURE_IS_BSDF_GLOSSY(type)
#define CLOSURE_IS_BSDF_DIFFUSE(type)
#define CLOSURE_IS_BSDF_OR_BSSRDF(type)
ClosureType
@ CLOSURE_VOLUME_HENYEY_GREENSTEIN_ID
@ CLOSURE_BSDF_TRANSPARENT_ID
@ CLOSURE_NONE_ID
@ CLOSURE_HOLDOUT_ID
@ NBUILTIN_CLOSURES
#define CLOSURE_IS_BSSRDF(type)
@ PATH_MNEE_VALID
Definition: kernel/types.h:293
@ FILTER_CLOSURE_EMISSION
Definition: kernel/types.h:424
@ FILTER_CLOSURE_GLOSSY
Definition: kernel/types.h:426
@ FILTER_CLOSURE_DIFFUSE
Definition: kernel/types.h:425
@ FILTER_CLOSURE_TRANSPARENT
Definition: kernel/types.h:428
@ FILTER_CLOSURE_DIRECT_LIGHT
Definition: kernel/types.h:429
@ FILTER_CLOSURE_TRANSMISSION
Definition: kernel/types.h:427
@ SD_CLOSURE_FLAGS
Definition: kernel/types.h:758
@ SD_BSDF_HAS_EVAL
Definition: kernel/types.h:744
@ SD_SHADER_FLAGS
Definition: kernel/types.h:794
@ SD_HAS_CONSTANT_EMISSION
Definition: kernel/types.h:786
@ SD_HAS_ONLY_VOLUME
Definition: kernel/types.h:770
@ SD_BSDF
Definition: kernel/types.h:742
@ SD_TRANSPARENT
Definition: kernel/types.h:754
@ SD_HOLDOUT
Definition: kernel/types.h:748
@ SD_EMISSION
Definition: kernel/types.h:740
#define MAX_VOLUME_CLOSURE
Definition: kernel/types.h:697
@ ATTR_STD_NOT_FOUND
Definition: kernel/types.h:647
@ ATTR_STD_VOLUME_VELOCITY
Definition: kernel/types.h:638
#define SHADER_NONE
Definition: kernel/types.h:39
@ PATH_RAY_SHADOW
Definition: kernel/types.h:206
@ PATH_RAY_TERMINATE
Definition: kernel/types.h:251
@ PATH_RAY_EMISSION
Definition: kernel/types.h:255
@ PATH_RAY_CAMERA
Definition: kernel/types.h:194
#define OBJECT_NONE
Definition: kernel/types.h:40
ShaderData
Definition: kernel/types.h:925
@ SHADER_EXCLUDE_DIFFUSE
Definition: kernel/types.h:439
@ SHADER_EXCLUDE_ANY
Definition: kernel/types.h:445
@ SHADER_EXCLUDE_GLOSSY
Definition: kernel/types.h:440
@ SHADER_EXCLUDE_TRANSMIT
Definition: kernel/types.h:441
@ SHADER_MASK
Definition: kernel/types.h:449
@ MOTION_POSITION_END
Definition: kernel/types.h:487
@ MOTION_POSITION_CENTER
Definition: kernel/types.h:485
@ SD_OBJECT_HOLDOUT_MASK
Definition: kernel/types.h:804
@ SD_OBJECT_HAS_VOLUME_MOTION
Definition: kernel/types.h:826
@ SD_OBJECT_FLAGS
Definition: kernel/types.h:831
@ LABEL_NONE
Definition: kernel/types.h:316
ShaderClosure
Definition: kernel/types.h:726
#define __MNEE__
Definition: kernel/types.h:100
#define LAMP_NONE
Definition: kernel/types.h:42
#define CAUSTICS_MAX_CLOSURE
Definition: kernel/types.h:686
ccl_device_inline float average(const float2 &a)
Definition: math_float2.h:170
ccl_device_inline float3 one_float3()
Definition: math_float3.h:89
ccl_device_inline float3 zero_float3()
Definition: math_float3.h:80
static float P(float k)
Definition: math_interp.c:25
#define N
#define fabsf(x)
Definition: metal/compat.h:219
#define sqrtf(x)
Definition: metal/compat.h:243
#define make_float3(x, y, z)
Definition: metal/compat.h:204
T dot(const vec_base< T, Size > &a, const vec_base< T, Size > &b)
vec_base< T, Size > normalize(const vec_base< T, Size > &v)
bool is_zero(const T &a)
static const pxr::TfToken roughness("roughness", pxr::TfToken::Immortal)
#define min(a, b)
Definition: sort.c:35
const IntegratorStateCPU *ccl_restrict ConstIntegratorState
Definition: state.h:148
#define INTEGRATOR_STATE(state, nested_struct, member)
Definition: state.h:154
closure color bssrdf(string method, normal N, vector radius, color albedo) BUILTIN
unsigned int uint32_t
Definition: stdint.h:80
Definition: bssrdf.h:8
static void eval_displacement(SubdivDisplacement *displacement, const int ptex_face_index, const float u, const float v, const float dPdu[3], const float dPdv[3], float r_D[3])
float max
#define N_(msgid)