1 /*
2 * Copyright 2011-2013 Blender Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "render/film.h"
18 #include "device/device.h"
19 #include "render/camera.h"
20 #include "render/integrator.h"
21 #include "render/mesh.h"
22 #include "render/scene.h"
23 #include "render/stats.h"
24 #include "render/tables.h"
25
26 #include "util/util_algorithm.h"
27 #include "util/util_foreach.h"
28 #include "util/util_math.h"
29 #include "util/util_math_cdf.h"
30 #include "util/util_time.h"
31
32 CCL_NAMESPACE_BEGIN
33
34 /* Pass */
35
compare_pass_order(const Pass & a,const Pass & b)36 static bool compare_pass_order(const Pass &a, const Pass &b)
37 {
38 if (a.components == b.components)
39 return (a.type < b.type);
40 return (a.components > b.components);
41 }
42
NODE_DEFINE(Pass)43 NODE_DEFINE(Pass)
44 {
45 NodeType *type = NodeType::add("pass", create);
46
47 static NodeEnum pass_type_enum;
48 pass_type_enum.insert("combined", PASS_COMBINED);
49 pass_type_enum.insert("depth", PASS_DEPTH);
50 pass_type_enum.insert("normal", PASS_NORMAL);
51 pass_type_enum.insert("uv", PASS_UV);
52 pass_type_enum.insert("object_id", PASS_OBJECT_ID);
53 pass_type_enum.insert("material_id", PASS_MATERIAL_ID);
54 pass_type_enum.insert("motion", PASS_MOTION);
55 pass_type_enum.insert("motion_weight", PASS_MOTION_WEIGHT);
56 #ifdef __KERNEL_DEBUG__
57 pass_type_enum.insert("traversed_nodes", PASS_BVH_TRAVERSED_NODES);
58 pass_type_enum.insert("traverse_instances", PASS_BVH_TRAVERSED_INSTANCES);
59 pass_type_enum.insert("bvh_intersections", PASS_BVH_INTERSECTIONS);
60 pass_type_enum.insert("ray_bounces", PASS_RAY_BOUNCES);
61 #endif
62 pass_type_enum.insert("render_time", PASS_RENDER_TIME);
63 pass_type_enum.insert("cryptomatte", PASS_CRYPTOMATTE);
64 pass_type_enum.insert("aov_color", PASS_AOV_COLOR);
65 pass_type_enum.insert("aov_value", PASS_AOV_VALUE);
66 pass_type_enum.insert("adaptive_aux_buffer", PASS_ADAPTIVE_AUX_BUFFER);
67 pass_type_enum.insert("sample_count", PASS_SAMPLE_COUNT);
68 pass_type_enum.insert("mist", PASS_MIST);
69 pass_type_enum.insert("emission", PASS_EMISSION);
70 pass_type_enum.insert("background", PASS_BACKGROUND);
71 pass_type_enum.insert("ambient_occlusion", PASS_AO);
72 pass_type_enum.insert("shadow", PASS_SHADOW);
73 pass_type_enum.insert("diffuse_direct", PASS_DIFFUSE_DIRECT);
74 pass_type_enum.insert("diffuse_indirect", PASS_DIFFUSE_INDIRECT);
75 pass_type_enum.insert("diffuse_color", PASS_DIFFUSE_COLOR);
76 pass_type_enum.insert("glossy_direct", PASS_GLOSSY_DIRECT);
77 pass_type_enum.insert("glossy_indirect", PASS_GLOSSY_INDIRECT);
78 pass_type_enum.insert("glossy_color", PASS_GLOSSY_COLOR);
79 pass_type_enum.insert("transmission_direct", PASS_TRANSMISSION_DIRECT);
80 pass_type_enum.insert("transmission_indirect", PASS_TRANSMISSION_INDIRECT);
81 pass_type_enum.insert("transmission_color", PASS_TRANSMISSION_COLOR);
82 pass_type_enum.insert("volume_direct", PASS_VOLUME_DIRECT);
83 pass_type_enum.insert("volume_indirect", PASS_VOLUME_INDIRECT);
84 pass_type_enum.insert("bake_primitive", PASS_BAKE_PRIMITIVE);
85 pass_type_enum.insert("bake_differential", PASS_BAKE_DIFFERENTIAL);
86
87 SOCKET_ENUM(type, "Type", pass_type_enum, PASS_COMBINED);
88 SOCKET_STRING(name, "Name", ustring());
89
90 return type;
91 }
92
Pass()93 Pass::Pass() : Node(node_type)
94 {
95 }
96
add(PassType type,vector<Pass> & passes,const char * name)97 void Pass::add(PassType type, vector<Pass> &passes, const char *name)
98 {
99 for (size_t i = 0; i < passes.size(); i++) {
100 if (passes[i].type != type) {
101 continue;
102 }
103
104 /* An empty name is used as a placeholder to signal that any pass of
105 * that type is fine (because the content always is the same).
106 * This is important to support divide_type: If the pass that has a
107 * divide_type is added first, a pass for divide_type with an empty
108 * name will be added. Then, if a matching pass with a name is later
109 * requested, the existing placeholder will be renamed to that.
110 * If the divide_type is explicitly allocated with a name first and
111 * then again as part of another pass, the second one will just be
112 * skipped because that type already exists. */
113
114 /* If no name is specified, any pass of the correct type will match. */
115 if (name == NULL) {
116 return;
117 }
118
119 /* If we already have a placeholder pass, rename that one. */
120 if (passes[i].name.empty()) {
121 passes[i].name = name;
122 return;
123 }
124
125 /* If neither existing nor requested pass have placeholder name, they
126 * must match. */
127 if (name == passes[i].name) {
128 return;
129 }
130 }
131
132 Pass pass;
133
134 pass.type = type;
135 pass.filter = true;
136 pass.exposure = false;
137 pass.divide_type = PASS_NONE;
138 if (name) {
139 pass.name = name;
140 }
141
142 switch (type) {
143 case PASS_NONE:
144 pass.components = 0;
145 break;
146 case PASS_COMBINED:
147 pass.components = 4;
148 pass.exposure = true;
149 break;
150 case PASS_DEPTH:
151 pass.components = 1;
152 pass.filter = false;
153 break;
154 case PASS_MIST:
155 pass.components = 1;
156 break;
157 case PASS_NORMAL:
158 pass.components = 4;
159 break;
160 case PASS_UV:
161 pass.components = 4;
162 break;
163 case PASS_MOTION:
164 pass.components = 4;
165 pass.divide_type = PASS_MOTION_WEIGHT;
166 break;
167 case PASS_MOTION_WEIGHT:
168 pass.components = 1;
169 break;
170 case PASS_OBJECT_ID:
171 case PASS_MATERIAL_ID:
172 pass.components = 1;
173 pass.filter = false;
174 break;
175
176 case PASS_EMISSION:
177 case PASS_BACKGROUND:
178 pass.components = 4;
179 pass.exposure = true;
180 break;
181 case PASS_AO:
182 pass.components = 4;
183 break;
184 case PASS_SHADOW:
185 pass.components = 4;
186 pass.exposure = false;
187 break;
188 case PASS_LIGHT:
189 /* This isn't a real pass, used by baking to see whether
190 * light data is needed or not.
191 *
192 * Set components to 0 so pass sort below happens in a
193 * determined way.
194 */
195 pass.components = 0;
196 break;
197 #ifdef WITH_CYCLES_DEBUG
198 case PASS_BVH_TRAVERSED_NODES:
199 case PASS_BVH_TRAVERSED_INSTANCES:
200 case PASS_BVH_INTERSECTIONS:
201 case PASS_RAY_BOUNCES:
202 pass.components = 1;
203 pass.exposure = false;
204 break;
205 #endif
206 case PASS_RENDER_TIME:
207 /* This pass is handled entirely on the host side. */
208 pass.components = 0;
209 break;
210
211 case PASS_DIFFUSE_COLOR:
212 case PASS_GLOSSY_COLOR:
213 case PASS_TRANSMISSION_COLOR:
214 pass.components = 4;
215 break;
216 case PASS_DIFFUSE_DIRECT:
217 case PASS_DIFFUSE_INDIRECT:
218 pass.components = 4;
219 pass.exposure = true;
220 pass.divide_type = PASS_DIFFUSE_COLOR;
221 break;
222 case PASS_GLOSSY_DIRECT:
223 case PASS_GLOSSY_INDIRECT:
224 pass.components = 4;
225 pass.exposure = true;
226 pass.divide_type = PASS_GLOSSY_COLOR;
227 break;
228 case PASS_TRANSMISSION_DIRECT:
229 case PASS_TRANSMISSION_INDIRECT:
230 pass.components = 4;
231 pass.exposure = true;
232 pass.divide_type = PASS_TRANSMISSION_COLOR;
233 break;
234 case PASS_VOLUME_DIRECT:
235 case PASS_VOLUME_INDIRECT:
236 pass.components = 4;
237 pass.exposure = true;
238 break;
239 case PASS_CRYPTOMATTE:
240 pass.components = 4;
241 break;
242 case PASS_ADAPTIVE_AUX_BUFFER:
243 pass.components = 4;
244 break;
245 case PASS_SAMPLE_COUNT:
246 pass.components = 1;
247 pass.exposure = false;
248 break;
249 case PASS_AOV_COLOR:
250 pass.components = 4;
251 break;
252 case PASS_AOV_VALUE:
253 pass.components = 1;
254 break;
255 case PASS_BAKE_PRIMITIVE:
256 case PASS_BAKE_DIFFERENTIAL:
257 pass.components = 4;
258 pass.exposure = false;
259 pass.filter = false;
260 break;
261 default:
262 assert(false);
263 break;
264 }
265
266 passes.push_back(pass);
267
268 /* Order from by components, to ensure alignment so passes with size 4
269 * come first and then passes with size 1. Note this must use stable sort
270 * so cryptomatte passes remain in the right order. */
271 stable_sort(&passes[0], &passes[0] + passes.size(), compare_pass_order);
272
273 if (pass.divide_type != PASS_NONE)
274 Pass::add(pass.divide_type, passes);
275 }
276
equals(const vector<Pass> & A,const vector<Pass> & B)277 bool Pass::equals(const vector<Pass> &A, const vector<Pass> &B)
278 {
279 if (A.size() != B.size())
280 return false;
281
282 for (int i = 0; i < A.size(); i++)
283 if (A[i].type != B[i].type || A[i].name != B[i].name)
284 return false;
285
286 return true;
287 }
288
contains(const vector<Pass> & passes,PassType type)289 bool Pass::contains(const vector<Pass> &passes, PassType type)
290 {
291 for (size_t i = 0; i < passes.size(); i++)
292 if (passes[i].type == type)
293 return true;
294
295 return false;
296 }
297
298 /* Pixel Filter */
299
filter_func_box(float,float)300 static float filter_func_box(float /*v*/, float /*width*/)
301 {
302 return 1.0f;
303 }
304
filter_func_gaussian(float v,float width)305 static float filter_func_gaussian(float v, float width)
306 {
307 v *= 6.0f / width;
308 return expf(-2.0f * v * v);
309 }
310
filter_func_blackman_harris(float v,float width)311 static float filter_func_blackman_harris(float v, float width)
312 {
313 v = M_2PI_F * (v / width + 0.5f);
314 return 0.35875f - 0.48829f * cosf(v) + 0.14128f * cosf(2.0f * v) - 0.01168f * cosf(3.0f * v);
315 }
316
filter_table(FilterType type,float width)317 static vector<float> filter_table(FilterType type, float width)
318 {
319 vector<float> filter_table(FILTER_TABLE_SIZE);
320 float (*filter_func)(float, float) = NULL;
321
322 switch (type) {
323 case FILTER_BOX:
324 filter_func = filter_func_box;
325 break;
326 case FILTER_GAUSSIAN:
327 filter_func = filter_func_gaussian;
328 width *= 3.0f;
329 break;
330 case FILTER_BLACKMAN_HARRIS:
331 filter_func = filter_func_blackman_harris;
332 width *= 2.0f;
333 break;
334 default:
335 assert(0);
336 }
337
338 /* Create importance sampling table. */
339
340 /* TODO(sergey): With the even filter table size resolution we can not
341 * really make it nice symmetric importance map without sampling full range
342 * (meaning, we would need to sample full filter range and not use the
343 * make_symmetric argument).
344 *
345 * Current code matches exactly initial filter table code, but we should
346 * consider either making FILTER_TABLE_SIZE odd value or sample full filter.
347 */
348
349 util_cdf_inverted(FILTER_TABLE_SIZE,
350 0.0f,
351 width * 0.5f,
352 function_bind(filter_func, _1, width),
353 true,
354 filter_table);
355
356 return filter_table;
357 }
358
359 /* Film */
360
NODE_DEFINE(Film)361 NODE_DEFINE(Film)
362 {
363 NodeType *type = NodeType::add("film", create);
364
365 SOCKET_FLOAT(exposure, "Exposure", 0.8f);
366 SOCKET_FLOAT(pass_alpha_threshold, "Pass Alpha Threshold", 0.0f);
367
368 static NodeEnum filter_enum;
369 filter_enum.insert("box", FILTER_BOX);
370 filter_enum.insert("gaussian", FILTER_GAUSSIAN);
371 filter_enum.insert("blackman_harris", FILTER_BLACKMAN_HARRIS);
372
373 SOCKET_ENUM(filter_type, "Filter Type", filter_enum, FILTER_BOX);
374 SOCKET_FLOAT(filter_width, "Filter Width", 1.0f);
375
376 SOCKET_FLOAT(mist_start, "Mist Start", 0.0f);
377 SOCKET_FLOAT(mist_depth, "Mist Depth", 100.0f);
378 SOCKET_FLOAT(mist_falloff, "Mist Falloff", 1.0f);
379
380 SOCKET_BOOLEAN(denoising_data_pass, "Generate Denoising Data Pass", false);
381 SOCKET_BOOLEAN(denoising_clean_pass, "Generate Denoising Clean Pass", false);
382 SOCKET_BOOLEAN(denoising_prefiltered_pass, "Generate Denoising Prefiltered Pass", false);
383 SOCKET_INT(denoising_flags, "Denoising Flags", 0);
384 SOCKET_BOOLEAN(use_adaptive_sampling, "Use Adaptive Sampling", false);
385
386 return type;
387 }
388
Film()389 Film::Film() : Node(node_type)
390 {
391 use_light_visibility = false;
392 filter_table_offset = TABLE_OFFSET_INVALID;
393 cryptomatte_passes = CRYPT_NONE;
394 display_pass = PASS_COMBINED;
395
396 need_update = true;
397 }
398
~Film()399 Film::~Film()
400 {
401 }
402
add_default(Scene * scene)403 void Film::add_default(Scene *scene)
404 {
405 Pass::add(PASS_COMBINED, scene->passes);
406 }
407
device_update(Device * device,DeviceScene * dscene,Scene * scene)408 void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
409 {
410 if (!need_update)
411 return;
412
413 scoped_callback_timer timer([scene](double time) {
414 if (scene->update_stats) {
415 scene->update_stats->film.times.add_entry({"update", time});
416 }
417 });
418
419 device_free(device, dscene, scene);
420
421 KernelFilm *kfilm = &dscene->data.film;
422
423 /* update __data */
424 kfilm->exposure = exposure;
425 kfilm->pass_flag = 0;
426
427 kfilm->display_pass_stride = -1;
428 kfilm->display_pass_components = 0;
429 kfilm->display_divide_pass_stride = -1;
430 kfilm->use_display_exposure = false;
431 kfilm->use_display_pass_alpha = (display_pass == PASS_COMBINED);
432
433 kfilm->light_pass_flag = 0;
434 kfilm->pass_stride = 0;
435 kfilm->use_light_pass = use_light_visibility;
436 kfilm->pass_aov_value_num = 0;
437 kfilm->pass_aov_color_num = 0;
438
439 bool have_cryptomatte = false;
440
441 for (size_t i = 0; i < scene->passes.size(); i++) {
442 Pass &pass = scene->passes[i];
443
444 if (pass.type == PASS_NONE) {
445 continue;
446 }
447
448 /* Can't do motion pass if no motion vectors are available. */
449 if (pass.type == PASS_MOTION || pass.type == PASS_MOTION_WEIGHT) {
450 if (scene->need_motion() != Scene::MOTION_PASS) {
451 kfilm->pass_stride += pass.components;
452 continue;
453 }
454 }
455
456 int pass_flag = (1 << (pass.type % 32));
457 if (pass.type <= PASS_CATEGORY_MAIN_END) {
458 kfilm->pass_flag |= pass_flag;
459 }
460 else if (pass.type <= PASS_CATEGORY_LIGHT_END) {
461 kfilm->use_light_pass = 1;
462 kfilm->light_pass_flag |= pass_flag;
463 }
464 else {
465 assert(pass.type <= PASS_CATEGORY_BAKE_END);
466 }
467
468 switch (pass.type) {
469 case PASS_COMBINED:
470 kfilm->pass_combined = kfilm->pass_stride;
471 break;
472 case PASS_DEPTH:
473 kfilm->pass_depth = kfilm->pass_stride;
474 break;
475 case PASS_NORMAL:
476 kfilm->pass_normal = kfilm->pass_stride;
477 break;
478 case PASS_UV:
479 kfilm->pass_uv = kfilm->pass_stride;
480 break;
481 case PASS_MOTION:
482 kfilm->pass_motion = kfilm->pass_stride;
483 break;
484 case PASS_MOTION_WEIGHT:
485 kfilm->pass_motion_weight = kfilm->pass_stride;
486 break;
487 case PASS_OBJECT_ID:
488 kfilm->pass_object_id = kfilm->pass_stride;
489 break;
490 case PASS_MATERIAL_ID:
491 kfilm->pass_material_id = kfilm->pass_stride;
492 break;
493
494 case PASS_MIST:
495 kfilm->pass_mist = kfilm->pass_stride;
496 break;
497 case PASS_EMISSION:
498 kfilm->pass_emission = kfilm->pass_stride;
499 break;
500 case PASS_BACKGROUND:
501 kfilm->pass_background = kfilm->pass_stride;
502 break;
503 case PASS_AO:
504 kfilm->pass_ao = kfilm->pass_stride;
505 break;
506 case PASS_SHADOW:
507 kfilm->pass_shadow = kfilm->pass_stride;
508 break;
509
510 case PASS_LIGHT:
511 break;
512
513 case PASS_DIFFUSE_COLOR:
514 kfilm->pass_diffuse_color = kfilm->pass_stride;
515 break;
516 case PASS_GLOSSY_COLOR:
517 kfilm->pass_glossy_color = kfilm->pass_stride;
518 break;
519 case PASS_TRANSMISSION_COLOR:
520 kfilm->pass_transmission_color = kfilm->pass_stride;
521 break;
522 case PASS_DIFFUSE_INDIRECT:
523 kfilm->pass_diffuse_indirect = kfilm->pass_stride;
524 break;
525 case PASS_GLOSSY_INDIRECT:
526 kfilm->pass_glossy_indirect = kfilm->pass_stride;
527 break;
528 case PASS_TRANSMISSION_INDIRECT:
529 kfilm->pass_transmission_indirect = kfilm->pass_stride;
530 break;
531 case PASS_VOLUME_INDIRECT:
532 kfilm->pass_volume_indirect = kfilm->pass_stride;
533 break;
534 case PASS_DIFFUSE_DIRECT:
535 kfilm->pass_diffuse_direct = kfilm->pass_stride;
536 break;
537 case PASS_GLOSSY_DIRECT:
538 kfilm->pass_glossy_direct = kfilm->pass_stride;
539 break;
540 case PASS_TRANSMISSION_DIRECT:
541 kfilm->pass_transmission_direct = kfilm->pass_stride;
542 break;
543 case PASS_VOLUME_DIRECT:
544 kfilm->pass_volume_direct = kfilm->pass_stride;
545 break;
546
547 case PASS_BAKE_PRIMITIVE:
548 kfilm->pass_bake_primitive = kfilm->pass_stride;
549 break;
550 case PASS_BAKE_DIFFERENTIAL:
551 kfilm->pass_bake_differential = kfilm->pass_stride;
552 break;
553
554 #ifdef WITH_CYCLES_DEBUG
555 case PASS_BVH_TRAVERSED_NODES:
556 kfilm->pass_bvh_traversed_nodes = kfilm->pass_stride;
557 break;
558 case PASS_BVH_TRAVERSED_INSTANCES:
559 kfilm->pass_bvh_traversed_instances = kfilm->pass_stride;
560 break;
561 case PASS_BVH_INTERSECTIONS:
562 kfilm->pass_bvh_intersections = kfilm->pass_stride;
563 break;
564 case PASS_RAY_BOUNCES:
565 kfilm->pass_ray_bounces = kfilm->pass_stride;
566 break;
567 #endif
568 case PASS_RENDER_TIME:
569 break;
570 case PASS_CRYPTOMATTE:
571 kfilm->pass_cryptomatte = have_cryptomatte ?
572 min(kfilm->pass_cryptomatte, kfilm->pass_stride) :
573 kfilm->pass_stride;
574 have_cryptomatte = true;
575 break;
576 case PASS_ADAPTIVE_AUX_BUFFER:
577 kfilm->pass_adaptive_aux_buffer = kfilm->pass_stride;
578 break;
579 case PASS_SAMPLE_COUNT:
580 kfilm->pass_sample_count = kfilm->pass_stride;
581 break;
582 case PASS_AOV_COLOR:
583 if (kfilm->pass_aov_color_num == 0) {
584 kfilm->pass_aov_color = kfilm->pass_stride;
585 }
586 kfilm->pass_aov_color_num++;
587 break;
588 case PASS_AOV_VALUE:
589 if (kfilm->pass_aov_value_num == 0) {
590 kfilm->pass_aov_value = kfilm->pass_stride;
591 }
592 kfilm->pass_aov_value_num++;
593 break;
594 default:
595 assert(false);
596 break;
597 }
598
599 if (pass.type == display_pass) {
600 kfilm->display_pass_stride = kfilm->pass_stride;
601 kfilm->display_pass_components = pass.components;
602 kfilm->use_display_exposure = pass.exposure && (kfilm->exposure != 1.0f);
603 }
604 else if (pass.type == PASS_DIFFUSE_COLOR || pass.type == PASS_TRANSMISSION_COLOR ||
605 pass.type == PASS_GLOSSY_COLOR) {
606 kfilm->display_divide_pass_stride = kfilm->pass_stride;
607 }
608
609 kfilm->pass_stride += pass.components;
610 }
611
612 kfilm->pass_denoising_data = 0;
613 kfilm->pass_denoising_clean = 0;
614 kfilm->denoising_flags = 0;
615 if (denoising_data_pass) {
616 kfilm->pass_denoising_data = kfilm->pass_stride;
617 kfilm->pass_stride += DENOISING_PASS_SIZE_BASE;
618 kfilm->denoising_flags = denoising_flags;
619 if (denoising_clean_pass) {
620 kfilm->pass_denoising_clean = kfilm->pass_stride;
621 kfilm->pass_stride += DENOISING_PASS_SIZE_CLEAN;
622 kfilm->use_light_pass = 1;
623 }
624 if (denoising_prefiltered_pass) {
625 kfilm->pass_stride += DENOISING_PASS_SIZE_PREFILTERED;
626 }
627 }
628
629 kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
630
631 /* When displaying the normal/uv pass in the viewport we need to disable
632 * transparency.
633 *
634 * We also don't need to perform light accumulations. Later we want to optimize this to suppress
635 * light calculations. */
636 if (display_pass == PASS_NORMAL || display_pass == PASS_UV) {
637 kfilm->use_light_pass = 0;
638 }
639 else {
640 kfilm->pass_alpha_threshold = pass_alpha_threshold;
641 }
642
643 /* update filter table */
644 vector<float> table = filter_table(filter_type, filter_width);
645 scene->lookup_tables->remove_table(&filter_table_offset);
646 filter_table_offset = scene->lookup_tables->add_table(dscene, table);
647 kfilm->filter_table_offset = (int)filter_table_offset;
648
649 /* mist pass parameters */
650 kfilm->mist_start = mist_start;
651 kfilm->mist_inv_depth = (mist_depth > 0.0f) ? 1.0f / mist_depth : 0.0f;
652 kfilm->mist_falloff = mist_falloff;
653
654 kfilm->cryptomatte_passes = cryptomatte_passes;
655 kfilm->cryptomatte_depth = cryptomatte_depth;
656
657 pass_stride = kfilm->pass_stride;
658 denoising_data_offset = kfilm->pass_denoising_data;
659 denoising_clean_offset = kfilm->pass_denoising_clean;
660
661 need_update = false;
662 }
663
device_free(Device *,DeviceScene *,Scene * scene)664 void Film::device_free(Device * /*device*/, DeviceScene * /*dscene*/, Scene *scene)
665 {
666 scene->lookup_tables->remove_table(&filter_table_offset);
667 }
668
modified(const Film & film)669 bool Film::modified(const Film &film)
670 {
671 return !Node::equals(film);
672 }
673
tag_passes_update(Scene * scene,const vector<Pass> & passes_,bool update_passes)674 void Film::tag_passes_update(Scene *scene, const vector<Pass> &passes_, bool update_passes)
675 {
676 if (Pass::contains(scene->passes, PASS_UV) != Pass::contains(passes_, PASS_UV)) {
677 scene->geometry_manager->tag_update(scene);
678
679 foreach (Shader *shader, scene->shaders)
680 shader->need_update_geometry = true;
681 }
682 else if (Pass::contains(scene->passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION)) {
683 scene->geometry_manager->tag_update(scene);
684 }
685 else if (Pass::contains(scene->passes, PASS_AO) != Pass::contains(passes_, PASS_AO)) {
686 scene->integrator->tag_update(scene);
687 }
688
689 if (update_passes) {
690 scene->passes = passes_;
691 }
692 }
693
tag_update(Scene *)694 void Film::tag_update(Scene * /*scene*/)
695 {
696 need_update = true;
697 }
698
get_aov_offset(Scene * scene,string name,bool & is_color)699 int Film::get_aov_offset(Scene *scene, string name, bool &is_color)
700 {
701 int num_color = 0, num_value = 0;
702 foreach (const Pass &pass, scene->passes) {
703 if (pass.type == PASS_AOV_COLOR) {
704 num_color++;
705 }
706 else if (pass.type == PASS_AOV_VALUE) {
707 num_value++;
708 }
709 else {
710 continue;
711 }
712
713 if (pass.name == name) {
714 is_color = (pass.type == PASS_AOV_COLOR);
715 return (is_color ? num_color : num_value) - 1;
716 }
717 }
718
719 return -1;
720 }
721
722 CCL_NAMESPACE_END
723