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