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