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