Blender V4.3
film.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "scene/film.h"
6#include "device/device.h"
7#include "scene/background.h"
8#include "scene/bake.h"
9#include "scene/camera.h"
10#include "scene/integrator.h"
11#include "scene/mesh.h"
12#include "scene/object.h"
13#include "scene/scene.h"
14#include "scene/stats.h"
15#include "scene/tables.h"
16
17#include "util/algorithm.h"
18#include "util/foreach.h"
19#include "util/math.h"
20#include "util/math_cdf.h"
21#include "util/time.h"
22
24
25/* Pixel Filter */
26
27static float filter_func_box(float /*v*/, float /*width*/)
28{
29 return 1.0f;
30}
31
32static float filter_func_gaussian(float v, float width)
33{
34 v *= 6.0f / width;
35 return expf(-2.0f * v * v);
36}
37
38static float filter_func_blackman_harris(float v, float width)
39{
40 v = M_2PI_F * (v / width + 0.5f);
41 return 0.35875f - 0.48829f * cosf(v) + 0.14128f * cosf(2.0f * v) - 0.01168f * cosf(3.0f * v);
42}
43
44static vector<float> filter_table(FilterType type, float width)
45{
47 float (*filter_func)(float, float) = NULL;
48
49 switch (type) {
50 case FILTER_BOX:
51 filter_func = filter_func_box;
52 break;
53 case FILTER_GAUSSIAN:
54 filter_func = filter_func_gaussian;
55 width *= 3.0f;
56 break;
58 filter_func = filter_func_blackman_harris;
59 width *= 2.0f;
60 break;
61 default:
62 assert(0);
63 }
64
65 /* Create importance sampling table. */
66
67 /* TODO(sergey): With the even filter table size resolution we can not
68 * really make it nice symmetric importance map without sampling full range
69 * (meaning, we would need to sample full filter range and not use the
70 * make_symmetric argument).
71 *
72 * Current code matches exactly initial filter table code, but we should
73 * consider either making FILTER_TABLE_SIZE odd value or sample full filter.
74 */
75
77 0.0f,
78 width * 0.5f,
79 function_bind(filter_func, _1, width),
80 true,
82
83 return filter_table;
84}
85
86/* Film */
87
89{
90 NodeType *type = NodeType::add("film", create);
91
92 SOCKET_FLOAT(exposure, "Exposure", 1.0f);
93 SOCKET_FLOAT(pass_alpha_threshold, "Pass Alpha Threshold", 0.0f);
94
95 static NodeEnum filter_enum;
96 filter_enum.insert("box", FILTER_BOX);
97 filter_enum.insert("gaussian", FILTER_GAUSSIAN);
98 filter_enum.insert("blackman_harris", FILTER_BLACKMAN_HARRIS);
99
100 SOCKET_ENUM(filter_type, "Filter Type", filter_enum, FILTER_BOX);
101 SOCKET_FLOAT(filter_width, "Filter Width", 1.0f);
102
103 SOCKET_FLOAT(mist_start, "Mist Start", 0.0f);
104 SOCKET_FLOAT(mist_depth, "Mist Depth", 100.0f);
105 SOCKET_FLOAT(mist_falloff, "Mist Falloff", 1.0f);
106
107 const NodeEnum *pass_type_enum = Pass::get_type_enum();
108 SOCKET_ENUM(display_pass, "Display Pass", *pass_type_enum, PASS_COMBINED);
109
110 SOCKET_BOOLEAN(show_active_pixels, "Show Active Pixels", false);
111
112 static NodeEnum cryptomatte_passes_enum;
113 cryptomatte_passes_enum.insert("none", CRYPT_NONE);
114 cryptomatte_passes_enum.insert("object", CRYPT_OBJECT);
115 cryptomatte_passes_enum.insert("material", CRYPT_MATERIAL);
116 cryptomatte_passes_enum.insert("asset", CRYPT_ASSET);
117 cryptomatte_passes_enum.insert("accurate", CRYPT_ACCURATE);
118 SOCKET_ENUM(cryptomatte_passes, "Cryptomatte Passes", cryptomatte_passes_enum, CRYPT_NONE);
119
120 SOCKET_INT(cryptomatte_depth, "Cryptomatte Depth", 0);
121
122 SOCKET_BOOLEAN(use_approximate_shadow_catcher, "Use Approximate Shadow Catcher", false);
123
124 return type;
125}
126
127Film::Film() : Node(get_node_type()), filter_table_offset_(TABLE_OFFSET_INVALID) {}
128
130
132{
133 Pass *pass = scene->create_node<Pass>();
134 pass->set_type(PASS_COMBINED);
135}
136
137void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
138{
139 if (!is_modified()) {
140 return;
141 }
142
143 scoped_callback_timer timer([scene](double time) {
144 if (scene->update_stats) {
145 scene->update_stats->film.times.add_entry({"update", time});
146 }
147 });
148
149 device_free(device, dscene, scene);
150
151 KernelFilm *kfilm = &dscene->data.film;
152
153 /* update data */
154 kfilm->exposure = exposure;
155 kfilm->pass_alpha_threshold = pass_alpha_threshold;
156 kfilm->pass_flag = 0;
157
158 kfilm->use_approximate_shadow_catcher = get_use_approximate_shadow_catcher();
159
160 kfilm->light_pass_flag = 0;
161 kfilm->pass_stride = 0;
162
163 /* Mark with PASS_UNUSED to avoid mask test in the kernel. */
164 kfilm->pass_combined = PASS_UNUSED;
165 kfilm->pass_depth = PASS_UNUSED;
166 kfilm->pass_position = PASS_UNUSED;
167 kfilm->pass_normal = PASS_UNUSED;
168 kfilm->pass_roughness = PASS_UNUSED;
169 kfilm->pass_motion = PASS_UNUSED;
170 kfilm->pass_motion_weight = PASS_UNUSED;
171 kfilm->pass_uv = PASS_UNUSED;
172 kfilm->pass_object_id = PASS_UNUSED;
173 kfilm->pass_material_id = PASS_UNUSED;
174 kfilm->pass_diffuse_color = PASS_UNUSED;
175 kfilm->pass_glossy_color = PASS_UNUSED;
176 kfilm->pass_transmission_color = PASS_UNUSED;
177 kfilm->pass_background = PASS_UNUSED;
178 kfilm->pass_emission = PASS_UNUSED;
179 kfilm->pass_ao = PASS_UNUSED;
180 kfilm->pass_diffuse_direct = PASS_UNUSED;
181 kfilm->pass_diffuse_indirect = PASS_UNUSED;
182 kfilm->pass_glossy_direct = PASS_UNUSED;
183 kfilm->pass_glossy_indirect = PASS_UNUSED;
184 kfilm->pass_transmission_direct = PASS_UNUSED;
185 kfilm->pass_transmission_indirect = PASS_UNUSED;
186 kfilm->pass_volume_direct = PASS_UNUSED;
187 kfilm->pass_volume_indirect = PASS_UNUSED;
188 kfilm->pass_lightgroup = PASS_UNUSED;
189
190 /* Mark passes as unused so that the kernel knows the pass is inaccessible. */
191 kfilm->pass_denoising_normal = PASS_UNUSED;
192 kfilm->pass_denoising_albedo = PASS_UNUSED;
193 kfilm->pass_denoising_depth = PASS_UNUSED;
194 kfilm->pass_sample_count = PASS_UNUSED;
195 kfilm->pass_adaptive_aux_buffer = PASS_UNUSED;
196 kfilm->pass_shadow_catcher = PASS_UNUSED;
197 kfilm->pass_shadow_catcher_sample_count = PASS_UNUSED;
198 kfilm->pass_shadow_catcher_matte = PASS_UNUSED;
199
200 kfilm->pass_guiding_color = PASS_UNUSED;
201 kfilm->pass_guiding_probability = PASS_UNUSED;
202 kfilm->pass_guiding_avg_roughness = PASS_UNUSED;
203
204 bool have_cryptomatte = false;
205 bool have_aov_color = false;
206 bool have_aov_value = false;
207 bool have_lightgroup = false;
208
209 for (size_t i = 0; i < scene->passes.size(); i++) {
210 const Pass *pass = scene->passes[i];
211
212 if (pass->get_type() == PASS_NONE || !pass->is_written()) {
213 continue;
214 }
215
216 if (pass->get_mode() == PassMode::DENOISED) {
217 /* Generally we only storing offsets of the noisy passes. The display pass is an exception
218 * since it is a read operation and not a write. */
219 kfilm->pass_stride += pass->get_info().num_components;
220 continue;
221 }
222
223 /* Can't do motion pass if no motion vectors are available. */
224 if (pass->get_type() == PASS_MOTION || pass->get_type() == PASS_MOTION_WEIGHT) {
225 if (scene->need_motion() != Scene::MOTION_PASS) {
226 kfilm->pass_stride += pass->get_info().num_components;
227 continue;
228 }
229 }
230
231 const int pass_flag = (1 << (pass->get_type() % 32));
232 if (pass->get_type() <= PASS_CATEGORY_LIGHT_END) {
233 kfilm->light_pass_flag |= pass_flag;
234 }
235 else if (pass->get_type() <= PASS_CATEGORY_DATA_END) {
236 kfilm->pass_flag |= pass_flag;
237 }
238 else {
239 assert(pass->get_type() <= PASS_CATEGORY_BAKE_END);
240 }
241
242 if (pass->get_lightgroup() != ustring()) {
243 if (!have_lightgroup) {
244 kfilm->pass_lightgroup = kfilm->pass_stride;
245 have_lightgroup = true;
246 }
247 kfilm->pass_stride += pass->get_info().num_components;
248 continue;
249 }
250
251 switch (pass->get_type()) {
252 case PASS_COMBINED:
253 kfilm->pass_combined = kfilm->pass_stride;
254 break;
255 case PASS_DEPTH:
256 kfilm->pass_depth = kfilm->pass_stride;
257 break;
258 case PASS_NORMAL:
259 kfilm->pass_normal = kfilm->pass_stride;
260 break;
261 case PASS_POSITION:
262 kfilm->pass_position = kfilm->pass_stride;
263 break;
264 case PASS_ROUGHNESS:
265 kfilm->pass_roughness = kfilm->pass_stride;
266 break;
267 case PASS_UV:
268 kfilm->pass_uv = kfilm->pass_stride;
269 break;
270 case PASS_MOTION:
271 kfilm->pass_motion = kfilm->pass_stride;
272 break;
274 kfilm->pass_motion_weight = kfilm->pass_stride;
275 break;
276 case PASS_OBJECT_ID:
277 kfilm->pass_object_id = kfilm->pass_stride;
278 break;
279 case PASS_MATERIAL_ID:
280 kfilm->pass_material_id = kfilm->pass_stride;
281 break;
282
283 case PASS_MIST:
284 kfilm->pass_mist = kfilm->pass_stride;
285 break;
286 case PASS_EMISSION:
287 kfilm->pass_emission = kfilm->pass_stride;
288 break;
289 case PASS_BACKGROUND:
290 kfilm->pass_background = kfilm->pass_stride;
291 break;
292 case PASS_AO:
293 kfilm->pass_ao = kfilm->pass_stride;
294 break;
295
297 kfilm->pass_diffuse_color = kfilm->pass_stride;
298 break;
300 kfilm->pass_glossy_color = kfilm->pass_stride;
301 break;
303 kfilm->pass_transmission_color = kfilm->pass_stride;
304 break;
306 kfilm->pass_diffuse_indirect = kfilm->pass_stride;
307 break;
309 kfilm->pass_glossy_indirect = kfilm->pass_stride;
310 break;
312 kfilm->pass_transmission_indirect = kfilm->pass_stride;
313 break;
315 kfilm->pass_volume_indirect = kfilm->pass_stride;
316 break;
318 kfilm->pass_diffuse_direct = kfilm->pass_stride;
319 break;
321 kfilm->pass_glossy_direct = kfilm->pass_stride;
322 break;
324 kfilm->pass_transmission_direct = kfilm->pass_stride;
325 break;
327 kfilm->pass_volume_direct = kfilm->pass_stride;
328 break;
329
331 kfilm->pass_bake_primitive = kfilm->pass_stride;
332 break;
333 case PASS_BAKE_SEED:
334 kfilm->pass_bake_seed = kfilm->pass_stride;
335 break;
337 kfilm->pass_bake_differential = kfilm->pass_stride;
338 break;
339
340 case PASS_CRYPTOMATTE:
341 kfilm->pass_cryptomatte = have_cryptomatte ?
342 min(kfilm->pass_cryptomatte, kfilm->pass_stride) :
343 kfilm->pass_stride;
344 have_cryptomatte = true;
345 break;
346
348 kfilm->pass_denoising_normal = kfilm->pass_stride;
349 break;
351 kfilm->pass_denoising_albedo = kfilm->pass_stride;
352 break;
354 kfilm->pass_denoising_depth = kfilm->pass_stride;
355 break;
356
358 kfilm->pass_shadow_catcher = kfilm->pass_stride;
359 break;
361 kfilm->pass_shadow_catcher_sample_count = kfilm->pass_stride;
362 break;
364 kfilm->pass_shadow_catcher_matte = kfilm->pass_stride;
365 break;
366
368 kfilm->pass_adaptive_aux_buffer = kfilm->pass_stride;
369 break;
371 kfilm->pass_sample_count = kfilm->pass_stride;
372 break;
373
374 case PASS_AOV_COLOR:
375 if (!have_aov_color) {
376 kfilm->pass_aov_color = kfilm->pass_stride;
377 have_aov_color = true;
378 }
379 break;
380 case PASS_AOV_VALUE:
381 if (!have_aov_value) {
382 kfilm->pass_aov_value = kfilm->pass_stride;
383 have_aov_value = true;
384 }
385 break;
387 kfilm->pass_guiding_color = kfilm->pass_stride;
388 break;
390 kfilm->pass_guiding_probability = kfilm->pass_stride;
391 break;
393 kfilm->pass_guiding_avg_roughness = kfilm->pass_stride;
394 break;
395 default:
396 assert(false);
397 break;
398 }
399
400 kfilm->pass_stride += pass->get_info().num_components;
401 }
402
403 /* update filter table */
404 vector<float> table = filter_table(filter_type, filter_width);
405 scene->lookup_tables->remove_table(&filter_table_offset_);
406 filter_table_offset_ = scene->lookup_tables->add_table(dscene, table);
407 dscene->data.tables.filter_table_offset = (int)filter_table_offset_;
408
409 /* mist pass parameters */
410 kfilm->mist_start = mist_start;
411 kfilm->mist_inv_depth = (mist_depth > 0.0f) ? 1.0f / mist_depth : 0.0f;
412 kfilm->mist_falloff = mist_falloff;
413
414 kfilm->cryptomatte_passes = cryptomatte_passes;
415 kfilm->cryptomatte_depth = cryptomatte_depth;
416
417 clear_modified();
418}
419
420void Film::device_free(Device * /*device*/, DeviceScene * /*dscene*/, Scene *scene)
421{
422 scene->lookup_tables->remove_table(&filter_table_offset_);
423}
424
425int Film::get_aov_offset(Scene *scene, string name, bool &is_color)
426{
427 int offset_color = 0, offset_value = 0;
428 foreach (const Pass *pass, scene->passes) {
429 if (pass->get_name() == name) {
430 if (pass->get_type() == PASS_AOV_VALUE) {
431 is_color = false;
432 return offset_value;
433 }
434 else if (pass->get_type() == PASS_AOV_COLOR) {
435 is_color = true;
436 return offset_color;
437 }
438 }
439
440 if (pass->get_type() == PASS_AOV_VALUE) {
441 offset_value += pass->get_info().num_components;
442 }
443 else if (pass->get_type() == PASS_AOV_COLOR) {
444 offset_color += pass->get_info().num_components;
445 }
446 }
447
448 return -1;
449}
450
452{
453 map<ustring, int> lightgroups;
454 int i = 0;
455 foreach (const Pass *pass, scene->passes) {
456 ustring lightgroup = pass->get_lightgroup();
457 if (!lightgroup.empty()) {
458 if (!lightgroups.count(lightgroup)) {
459 lightgroups[lightgroup] = i++;
460 }
461 }
462 }
463 if (scene->lightgroups != lightgroups) {
464 scene->lightgroups = lightgroups;
465 return true;
466 }
467
468 return false;
469}
470
471void Film::update_passes(Scene *scene, bool add_sample_count_pass)
472{
473 const Background *background = scene->background;
474 const BakeManager *bake_manager = scene->bake_manager;
475 const ObjectManager *object_manager = scene->object_manager;
476 Integrator *integrator = scene->integrator;
477
478 if (!is_modified() && !object_manager->need_update() && !integrator->is_modified() &&
479 !background->is_modified())
480 {
481 return;
482 }
483
484 /* Remove auto generated passes and recreate them. */
485 remove_auto_passes(scene);
486
487 /* Display pass for viewport. */
488 const PassType display_pass = get_display_pass();
489 add_auto_pass(scene, display_pass);
490
491 /* Assumption is that a combined pass always exists for now, for example
492 * adaptive sampling is always based on a combined pass. But we should
493 * try to lift this limitation in the future for faster rendering of
494 * individual passes. */
495 if (display_pass != PASS_COMBINED) {
496 add_auto_pass(scene, PASS_COMBINED);
497 }
498
499 /* Create passes needed for adaptive sampling. */
500 const AdaptiveSampling adaptive_sampling = integrator->get_adaptive_sampling();
501 if (adaptive_sampling.use) {
502 add_auto_pass(scene, PASS_SAMPLE_COUNT);
503 add_auto_pass(scene, PASS_ADAPTIVE_AUX_BUFFER);
504 }
505
506 /* Create passes needed for denoising. */
507 const bool use_denoise = integrator->get_use_denoise();
508 if (use_denoise) {
509 if (integrator->get_use_denoise_pass_normal()) {
510 add_auto_pass(scene, PASS_DENOISING_NORMAL);
511 }
512 if (integrator->get_use_denoise_pass_albedo()) {
513 add_auto_pass(scene, PASS_DENOISING_ALBEDO);
514 }
515 }
516
517 /* Create passes for shadow catcher. */
518 if (scene->has_shadow_catcher()) {
519 const bool need_background = get_use_approximate_shadow_catcher() &&
520 !background->get_transparent();
521
522 add_auto_pass(scene, PASS_SHADOW_CATCHER);
523 add_auto_pass(scene, PASS_SHADOW_CATCHER_SAMPLE_COUNT);
524 add_auto_pass(scene, PASS_SHADOW_CATCHER_MATTE);
525
526 if (need_background) {
527 add_auto_pass(scene, PASS_BACKGROUND);
528 }
529 }
530 else if (Pass::contains(scene->passes, PASS_SHADOW_CATCHER)) {
531 add_auto_pass(scene, PASS_SHADOW_CATCHER);
532 add_auto_pass(scene, PASS_SHADOW_CATCHER_SAMPLE_COUNT);
533 }
534
535 const vector<Pass *> passes_immutable = scene->passes;
536 for (const Pass *pass : passes_immutable) {
537 const PassInfo info = pass->get_info();
538 /* Add utility passes needed to generate some light passes. */
539 if (info.divide_type != PASS_NONE) {
540 add_auto_pass(scene, info.divide_type);
541 }
542 if (info.direct_type != PASS_NONE) {
543 add_auto_pass(scene, info.direct_type);
544 }
545 if (info.indirect_type != PASS_NONE) {
546 add_auto_pass(scene, info.indirect_type);
547 }
548
549 /* NOTE: Enable all denoised passes when storage is requested.
550 * This way it is possible to tweak denoiser parameters later on. */
551 if (info.support_denoise && use_denoise) {
552 add_auto_pass(scene, pass->get_type(), PassMode::DENOISED);
553 }
554 }
555
556 if (bake_manager->get_baking()) {
557 add_auto_pass(scene, PASS_BAKE_PRIMITIVE, "BakePrimitive");
558 add_auto_pass(scene, PASS_BAKE_DIFFERENTIAL, "BakeDifferential");
559 if (bake_manager->get_use_seed()) {
560 add_auto_pass(scene, PASS_BAKE_SEED, "BakeSeed");
561 }
562 }
563
564 if (add_sample_count_pass) {
565 if (!Pass::contains(scene->passes, PASS_SAMPLE_COUNT)) {
566 add_auto_pass(scene, PASS_SAMPLE_COUNT);
567 }
568 }
569
570 /* Remove duplicates and initialize internal pass info. */
571 finalize_passes(scene, use_denoise);
572
573 /* Flush scene updates. */
574 const bool have_uv_pass = Pass::contains(scene->passes, PASS_UV);
575 const bool have_motion_pass = Pass::contains(scene->passes, PASS_MOTION);
576 const bool have_ao_pass = Pass::contains(scene->passes, PASS_AO);
577
578 if (have_uv_pass != prev_have_uv_pass) {
579 scene->geometry_manager->tag_update(scene, GeometryManager::UV_PASS_NEEDED);
580 foreach (Shader *shader, scene->shaders)
581 shader->need_update_uvs = true;
582 }
583 if (have_motion_pass != prev_have_motion_pass) {
584 scene->geometry_manager->tag_update(scene, GeometryManager::MOTION_PASS_NEEDED);
585 }
586 if (have_ao_pass != prev_have_ao_pass) {
587 scene->integrator->tag_update(scene, Integrator::AO_PASS_MODIFIED);
588 }
589
590 prev_have_uv_pass = have_uv_pass;
591 prev_have_motion_pass = have_motion_pass;
592 prev_have_ao_pass = have_ao_pass;
593
594 tag_modified();
595
596 /* Debug logging. */
597 if (VLOG_INFO_IS_ON) {
598 VLOG_INFO << "Effective scene passes:";
599 for (const Pass *pass : scene->passes) {
600 VLOG_INFO << "- " << *pass;
601 }
602 }
603}
604
605void Film::add_auto_pass(Scene *scene, PassType type, const char *name)
606{
607 add_auto_pass(scene, type, PassMode::NOISY, name);
608}
609
610void Film::add_auto_pass(Scene *scene, PassType type, PassMode mode, const char *name)
611{
612 Pass *pass = new Pass();
613 pass->set_type(type);
614 pass->set_mode(mode);
615 pass->set_name(ustring((name) ? name : ""));
616 pass->is_auto_ = true;
617
618 pass->set_owner(scene);
619 scene->passes.push_back(pass);
620}
621
622void Film::remove_auto_passes(Scene *scene)
623{
624 /* Remove all passes which were automatically created. */
625 vector<Pass *> new_passes;
626
627 for (Pass *pass : scene->passes) {
628 if (!pass->is_auto_) {
629 new_passes.push_back(pass);
630 }
631 else {
632 delete pass;
633 }
634 }
635
636 scene->passes = new_passes;
637}
638
639static bool compare_pass_order(const Pass *a, const Pass *b)
640{
641 /* On the highest level, sort by number of components.
642 * Within passes of the same component count, sort so that all non-lightgroup passes come first.
643 * Within that group, sort by type. */
644 const int num_components_a = a->get_info().num_components;
645 const int num_components_b = b->get_info().num_components;
646
647 if (num_components_a == num_components_b) {
648 const int is_lightgroup_a = !a->get_lightgroup().empty();
649 const int is_lightgroup_b = !b->get_lightgroup().empty();
650 if (is_lightgroup_a == is_lightgroup_b) {
651 return (a->get_type() < b->get_type());
652 }
653 return is_lightgroup_b;
654 }
655
656 return num_components_a > num_components_b;
657}
658
659void Film::finalize_passes(Scene *scene, const bool use_denoise)
660{
661 /* Remove duplicate passes. */
662 vector<Pass *> new_passes;
663
664 for (Pass *pass : scene->passes) {
665 /* Disable denoising on passes if denoising is disabled, or if the
666 * pass does not support it. */
667 pass->set_mode((use_denoise && pass->get_info().support_denoise) ? pass->get_mode() :
668 PassMode::NOISY);
669
670 /* Merge duplicate passes. */
671 bool duplicate_found = false;
672 for (Pass *new_pass : new_passes) {
673 /* If different type or denoising, don't merge. */
674 if (new_pass->get_type() != pass->get_type() || new_pass->get_mode() != pass->get_mode()) {
675 continue;
676 }
677
678 /* If both passes have a name and the names are different, don't merge.
679 * If either pass has a name, we'll use that name. */
680 if (!pass->get_name().empty() && !new_pass->get_name().empty() &&
681 pass->get_name() != new_pass->get_name())
682 {
683 continue;
684 }
685
686 if (!pass->get_name().empty() && new_pass->get_name().empty()) {
687 new_pass->set_name(pass->get_name());
688 }
689
690 new_pass->is_auto_ &= pass->is_auto_;
691 duplicate_found = true;
692 break;
693 }
694
695 if (!duplicate_found) {
696 new_passes.push_back(pass);
697 }
698 else {
699 delete pass;
700 }
701 }
702
703 /* Order from by components and type, This is required to for AOVs and cryptomatte passes,
704 * which the kernel assumes to be in order. Note this must use stable sort so cryptomatte
705 * passes remain in the right order. */
706 stable_sort(new_passes.begin(), new_passes.end(), compare_pass_order);
707
708 scene->passes = new_passes;
709}
710
712{
713 uint kernel_features = 0;
714
715 for (const Pass *pass : scene->passes) {
716 if (!pass->is_written()) {
717 continue;
718 }
719
720 const PassType pass_type = pass->get_type();
721 const PassMode pass_mode = pass->get_mode();
722
723 if (pass_mode == PassMode::DENOISED || pass_type == PASS_DENOISING_NORMAL ||
724 pass_type == PASS_DENOISING_ALBEDO || pass_type == PASS_DENOISING_DEPTH)
725 {
726 kernel_features |= KERNEL_FEATURE_DENOISING;
727 }
728
729 if (pass_type >= PASS_DIFFUSE && pass_type <= PASS_VOLUME_INDIRECT) {
730 kernel_features |= KERNEL_FEATURE_LIGHT_PASSES;
731 }
732
733 if (pass_type == PASS_AO) {
734 kernel_features |= KERNEL_FEATURE_AO_PASS;
735 }
736 }
737
738 return kernel_features;
739}
740
unsigned int uint
ATTR_WARN_UNUSED_RESULT const BMVert * v
bool get_use_seed() const
Definition bake.cpp:54
bool get_baking() const
Definition bake.cpp:25
Definition film.h:30
int get_aov_offset(Scene *scene, string name, bool &is_color)
Definition film.cpp:425
uint get_kernel_features(const Scene *scene) const
Definition film.cpp:711
~Film()
Definition film.cpp:129
static void add_default(Scene *scene)
Definition film.cpp:131
void update_passes(Scene *scene, bool add_sample_count_pass)
Definition film.cpp:471
void device_free(Device *device, DeviceScene *dscene, Scene *scene)
Definition film.cpp:420
void device_update(Device *device, DeviceScene *dscene, Scene *scene)
Definition film.cpp:137
Film()
Definition film.cpp:127
bool update_lightgroups(Scene *scene)
Definition film.cpp:451
AdaptiveSampling get_adaptive_sampling() const
bool need_update() const
Definition pass.h:49
PassInfo get_info() const
Definition pass.cpp:141
static const NodeEnum * get_type_enum()
Definition pass.cpp:45
static bool contains(const vector< Pass * > &passes, PassType type)
Definition pass.cpp:368
local_group_size(16, 16) .push_constant(Type b
#define function_bind
#define cosf(x)
#define expf(x)
#define CCL_NAMESPACE_END
#define NULL
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
static float filter_func_gaussian(float v, float width)
Definition film.cpp:32
static bool compare_pass_order(const Pass *a, const Pass *b)
Definition film.cpp:639
static CCL_NAMESPACE_BEGIN float filter_func_box(float, float)
Definition film.cpp:27
static float filter_func_blackman_harris(float v, float width)
Definition film.cpp:38
static vector< float > filter_table(FilterType type, float width)
Definition film.cpp:44
FilterType
Definition film.h:22
@ FILTER_BOX
Definition film.h:23
@ FILTER_BLACKMAN_HARRIS
Definition film.h:25
@ FILTER_GAUSSIAN
Definition film.h:24
#define PASS_UNUSED
#define FILTER_TABLE_SIZE
@ CRYPT_ASSET
@ CRYPT_NONE
@ CRYPT_ACCURATE
@ CRYPT_OBJECT
@ CRYPT_MATERIAL
#define KERNEL_FEATURE_LIGHT_PASSES
#define KERNEL_FEATURE_AO_PASS
PassType
@ PASS_SHADOW_CATCHER_SAMPLE_COUNT
@ PASS_EMISSION
@ PASS_POSITION
@ PASS_BACKGROUND
@ PASS_TRANSMISSION_DIRECT
@ PASS_VOLUME_DIRECT
@ PASS_UV
@ PASS_TRANSMISSION_COLOR
@ PASS_SHADOW_CATCHER_MATTE
@ PASS_GUIDING_COLOR
@ PASS_DEPTH
@ PASS_MIST
@ PASS_TRANSMISSION_INDIRECT
@ PASS_BAKE_SEED
@ PASS_SHADOW_CATCHER
@ PASS_DENOISING_NORMAL
@ PASS_ROUGHNESS
@ PASS_DIFFUSE_DIRECT
@ PASS_MOTION
@ PASS_CATEGORY_BAKE_END
@ PASS_MATERIAL_ID
@ PASS_AO
@ PASS_COMBINED
@ PASS_DIFFUSE
@ PASS_DIFFUSE_INDIRECT
@ PASS_GUIDING_PROBABILITY
@ PASS_CATEGORY_DATA_END
@ PASS_ADAPTIVE_AUX_BUFFER
@ PASS_OBJECT_ID
@ PASS_AOV_COLOR
@ PASS_NONE
@ PASS_VOLUME_INDIRECT
@ PASS_NORMAL
@ PASS_CRYPTOMATTE
@ PASS_DIFFUSE_COLOR
@ PASS_SAMPLE_COUNT
@ PASS_GLOSSY_DIRECT
@ PASS_MOTION_WEIGHT
@ PASS_DENOISING_ALBEDO
@ PASS_AOV_VALUE
@ PASS_GUIDING_AVG_ROUGHNESS
@ PASS_GLOSSY_COLOR
@ PASS_GLOSSY_INDIRECT
@ PASS_BAKE_DIFFERENTIAL
@ PASS_DENOISING_DEPTH
@ PASS_BAKE_PRIMITIVE
@ PASS_CATEGORY_LIGHT_END
#define KERNEL_FEATURE_DENOISING
#define VLOG_INFO
Definition log.h:72
#define VLOG_INFO_IS_ON
Definition log.h:73
void util_cdf_inverted(const int resolution, const float from, const float to, Functor functor, const bool make_symmetric, vector< float > &inv_cdf)
Definition math_cdf.h:47
#define SOCKET_FLOAT(name, ui_name, default_value,...)
Definition node_type.h:200
#define SOCKET_INT(name, ui_name, default_value,...)
Definition node_type.h:194
#define NODE_DEFINE(structname)
Definition node_type.h:148
#define SOCKET_BOOLEAN(name, ui_name, default_value,...)
Definition node_type.h:192
#define SOCKET_ENUM(name, ui_name, values, default_value,...)
Definition node_type.h:216
PassMode
Definition pass.h:20
@ TABLE_OFFSET_INVALID
#define M_2PI_F
Definition sky_float3.h:23
#define min(a, b)
Definition sort.c:32
void insert(const char *x, int y)
Definition node_enum.h:21
static NodeType * add(const char *name, CreateFunc create, Type type=NONE, const NodeType *base=NULL)
void tag_modified()
bool is_modified() const
PassType direct_type
Definition pass.h:33
int num_components
Definition pass.h:28
bool support_denoise
Definition pass.h:46
PassType divide_type
Definition pass.h:32
PassType indirect_type
Definition pass.h:34
@ MOTION_PASS
Definition scene.h:177
wmTimer * timer