add BLI_strcpy_rlen, replace strcat, which was used in misleading way.
[blender.git] / intern / cycles / render / light.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include "device.h"
20 #include "integrator.h"
21 #include "film.h"
22 #include "light.h"
23 #include "mesh.h"
24 #include "object.h"
25 #include "scene.h"
26 #include "shader.h"
27
28 #include "util_foreach.h"
29 #include "util_progress.h"
30
31 CCL_NAMESPACE_BEGIN
32
33 static void dump_background_pixels(Device *device, DeviceScene *dscene, int res, vector<float3>& pixels)
34 {
35         /* create input */
36         int width = res;
37         int height = res;
38
39         device_vector<uint4> d_input;
40         device_vector<float4> d_output;
41
42         uint4 *d_input_data = d_input.resize(width*height);
43
44         for(int y = 0; y < height; y++) {
45                 for(int x = 0; x < width; x++) {
46                         float u = x/(float)width;
47                         float v = y/(float)height;
48
49                         uint4 in = make_uint4(__float_as_int(u), __float_as_int(v), 0, 0);
50                         d_input_data[x + y*width] = in;
51                 }
52         }
53
54         /* compute on device */
55         float4 *d_output_data = d_output.resize(width*height);
56         memset((void*)d_output.data_pointer, 0, d_output.memory_size());
57
58         device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
59
60         device->mem_alloc(d_input, MEM_READ_ONLY);
61         device->mem_copy_to(d_input);
62         device->mem_alloc(d_output, MEM_WRITE_ONLY);
63
64         DeviceTask main_task(DeviceTask::SHADER);
65         main_task.shader_input = d_input.device_pointer;
66         main_task.shader_output = d_output.device_pointer;
67         main_task.shader_eval_type = SHADER_EVAL_BACKGROUND;
68         main_task.shader_x = 0;
69         main_task.shader_w = width*height;
70
71         /* disabled splitting for now, there's an issue with multi-GPU mem_copy_from */
72         list<DeviceTask> split_tasks;
73         main_task.split_max_size(split_tasks, 128*128); 
74
75         foreach(DeviceTask& task, split_tasks) {
76                 device->task_add(task);
77                 device->task_wait();
78                 device->mem_copy_from(d_output, task.shader_x, 1, task.shader_w, sizeof(float4));
79         }
80
81         device->mem_free(d_input);
82         device->mem_free(d_output);
83
84         d_output_data = reinterpret_cast<float4*>(d_output.data_pointer);
85
86         pixels.resize(width*height);
87
88         for(int y = 0; y < height; y++) {
89                 for(int x = 0; x < width; x++) {
90                         pixels[y*width + x].x = d_output_data[y*width + x].x;
91                         pixels[y*width + x].y = d_output_data[y*width + x].y;
92                         pixels[y*width + x].z = d_output_data[y*width + x].z;
93                 }
94         }
95 }
96
97 /* Light */
98
99 Light::Light()
100 {
101         type = LIGHT_POINT;
102
103         co = make_float3(0.0f, 0.0f, 0.0f);
104
105         dir = make_float3(0.0f, 0.0f, 0.0f);
106         size = 0.0f;
107
108         axisu = make_float3(0.0f, 0.0f, 0.0f);
109         sizeu = 1.0f;
110         axisv = make_float3(0.0f, 0.0f, 0.0f);
111         sizev = 1.0f;
112
113         map_resolution = 512;
114
115         spot_angle = M_PI_4_F;
116         spot_smooth = 0.0f;
117
118         cast_shadow = true;
119         use_mis = false;
120         use_diffuse = true;
121         use_glossy = true;
122         use_transmission = true;
123
124         shader = 0;
125         samples = 1;
126 }
127
128 void Light::tag_update(Scene *scene)
129 {
130         scene->light_manager->need_update = true;
131 }
132
133 /* Light Manager */
134
135 LightManager::LightManager()
136 {
137         need_update = true;
138         use_light_visibility = false;
139 }
140
141 LightManager::~LightManager()
142 {
143 }
144
145 void LightManager::device_update_distribution(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
146 {
147         progress.set_status("Updating Lights", "Computing distribution");
148
149         /* count */
150         size_t num_lights = scene->lights.size();
151         size_t num_background_lights = 0;
152         size_t num_triangles = 0;
153         size_t num_curve_segments = 0;
154
155         foreach(Object *object, scene->objects) {
156                 Mesh *mesh = object->mesh;
157                 bool have_emission = false;
158
159                 /* skip if we are not visible for BSDFs */
160                 if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT)))
161                         continue;
162
163                 /* skip if we have no emission shaders */
164                 foreach(uint sindex, mesh->used_shaders) {
165                         Shader *shader = scene->shaders[sindex];
166
167                         if(shader->sample_as_light && shader->has_surface_emission) {
168                                 have_emission = true;
169                                 break;
170                         }
171                 }
172
173                 /* count triangles */
174                 if(have_emission) {
175                         for(size_t i = 0; i < mesh->triangles.size(); i++) {
176                                 Shader *shader = scene->shaders[mesh->shader[i]];
177
178                                 if(shader->sample_as_light && shader->has_surface_emission)
179                                         num_triangles++;
180                         }
181
182                         /* disabled for curves */
183 #if 0
184                         foreach(Mesh::Curve& curve, mesh->curves) {
185                                 Shader *shader = scene->shaders[curve.shader];
186
187                                 if(shader->sample_as_light && shader->has_surface_emission)
188                                         num_curve_segments += curve.num_segments();
189 #endif
190                 }
191         }
192
193         size_t num_distribution = num_triangles + num_curve_segments;
194         num_distribution += num_lights;
195
196         /* emission area */
197         float4 *distribution = dscene->light_distribution.resize(num_distribution + 1);
198         float totarea = 0.0f;
199
200         /* triangles */
201         size_t offset = 0;
202         int j = 0;
203
204         foreach(Object *object, scene->objects) {
205                 Mesh *mesh = object->mesh;
206                 bool have_emission = false;
207
208                 /* skip if we are not visible for BSDFs */
209                 if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) {
210                         j++;
211                         continue;
212                 }
213
214                 /* skip if we have no emission shaders */
215                 foreach(uint sindex, mesh->used_shaders) {
216                         Shader *shader = scene->shaders[sindex];
217
218                         if(shader->sample_as_light && shader->has_surface_emission) {
219                                 have_emission = true;
220                                 break;
221                         }
222                 }
223
224                 /* sum area */
225                 if(have_emission) {
226                         bool transform_applied = mesh->transform_applied;
227                         Transform tfm = object->tfm;
228                         int object_id = j;
229                         int shader_id = SHADER_MASK;
230
231                         if(transform_applied)
232                                 object_id = ~object_id;
233
234                         if(!(object->visibility & PATH_RAY_DIFFUSE)) {
235                                 shader_id |= SHADER_EXCLUDE_DIFFUSE;
236                                 use_light_visibility = true;
237                         }
238                         if(!(object->visibility & PATH_RAY_GLOSSY)) {
239                                 shader_id |= SHADER_EXCLUDE_GLOSSY;
240                                 use_light_visibility = true;
241                         }
242                         if(!(object->visibility & PATH_RAY_TRANSMIT)) {
243                                 shader_id |= SHADER_EXCLUDE_TRANSMIT;
244                                 use_light_visibility = true;
245                         }
246
247                         for(size_t i = 0; i < mesh->triangles.size(); i++) {
248                                 Shader *shader = scene->shaders[mesh->shader[i]];
249
250                                 if(shader->sample_as_light && shader->has_surface_emission) {
251                                         distribution[offset].x = totarea;
252                                         distribution[offset].y = __int_as_float(i + mesh->tri_offset);
253                                         distribution[offset].z = __int_as_float(shader_id);
254                                         distribution[offset].w = __int_as_float(object_id);
255                                         offset++;
256
257                                         Mesh::Triangle t = mesh->triangles[i];
258                                         float3 p1 = mesh->verts[t.v[0]];
259                                         float3 p2 = mesh->verts[t.v[1]];
260                                         float3 p3 = mesh->verts[t.v[2]];
261
262                                         if(!transform_applied) {
263                                                 p1 = transform_point(&tfm, p1);
264                                                 p2 = transform_point(&tfm, p2);
265                                                 p3 = transform_point(&tfm, p3);
266                                         }
267
268                                         totarea += triangle_area(p1, p2, p3);
269                                 }
270                         }
271
272                         /* sample as light disabled for strands */
273 #if 0
274                         size_t i = 0;
275
276                         foreach(Mesh::Curve& curve, mesh->curves) {
277                                 Shader *shader = scene->shaders[curve.shader];
278                                 int first_key = curve.first_key;
279
280                                 if(shader->sample_as_light && shader->has_surface_emission) {
281                                         for(int j = 0; j < curve.num_segments(); j++) {
282                                                 distribution[offset].x = totarea;
283                                                 distribution[offset].y = __int_as_float(i + mesh->curve_offset); // XXX fix kernel code
284                                                 distribution[offset].z = __int_as_float(j) & SHADER_MASK;
285                                                 distribution[offset].w = __int_as_float(object_id);
286                                                 offset++;
287                                 
288                                                 float3 p1 = mesh->curve_keys[first_key + j].loc;
289                                                 float r1 = mesh->curve_keys[first_key + j].radius;
290                                                 float3 p2 = mesh->curve_keys[first_key + j + 1].loc;
291                                                 float r2 = mesh->curve_keys[first_key + j + 1].radius;
292                                 
293                                                 if(!transform_applied) {
294                                                         p1 = transform_point(&tfm, p1);
295                                                         p2 = transform_point(&tfm, p2);
296                                                 }
297                                 
298                                                 totarea += M_PI_F * (r1 + r2) * len(p1 - p2);
299                                         }
300                                 }
301
302                                 i++;
303                         }
304 #endif
305                 }
306
307                 if(progress.get_cancel()) return;
308
309                 j++;
310         }
311
312         float trianglearea = totarea;
313
314         /* point lights */
315         float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f;
316         bool use_lamp_mis = false;
317
318         for(int i = 0; i < scene->lights.size(); i++, offset++) {
319                 Light *light = scene->lights[i];
320
321                 distribution[offset].x = totarea;
322                 distribution[offset].y = __int_as_float(~(int)i);
323                 distribution[offset].z = 1.0f;
324                 distribution[offset].w = light->size;
325                 totarea += lightarea;
326
327                 if(light->size > 0.0f && light->use_mis)
328                         use_lamp_mis = true;
329                 if(light->type == LIGHT_BACKGROUND)
330                         num_background_lights++;
331         }
332
333         /* normalize cumulative distribution functions */
334         distribution[num_distribution].x = totarea;
335         distribution[num_distribution].y = 0.0f;
336         distribution[num_distribution].z = 0.0f;
337         distribution[num_distribution].w = 0.0f;
338
339         if(totarea > 0.0f) {
340                 for(size_t i = 0; i < num_distribution; i++)
341                         distribution[i].x /= totarea;
342                 distribution[num_distribution].x = 1.0f;
343         }
344
345         if(progress.get_cancel()) return;
346
347         /* update device */
348         KernelIntegrator *kintegrator = &dscene->data.integrator;
349         KernelFilm *kfilm = &dscene->data.film;
350         kintegrator->use_direct_light = (totarea > 0.0f);
351
352         if(kintegrator->use_direct_light) {
353                 /* number of emissives */
354                 kintegrator->num_distribution = num_distribution;
355
356                 /* precompute pdfs */
357                 kintegrator->pdf_triangles = 0.0f;
358                 kintegrator->pdf_lights = 0.0f;
359                 kintegrator->inv_pdf_lights = 0.0f;
360
361                 /* sample one, with 0.5 probability of light or triangle */
362                 kintegrator->num_all_lights = num_lights;
363
364                 if(trianglearea > 0.0f) {
365                         kintegrator->pdf_triangles = 1.0f/trianglearea;
366                         if(num_lights)
367                                 kintegrator->pdf_triangles *= 0.5f;
368                 }
369
370                 if(num_lights) {
371                         kintegrator->pdf_lights = 1.0f/num_lights;
372                         if(trianglearea > 0.0f)
373                                 kintegrator->pdf_lights *= 0.5f;
374
375                         kintegrator->inv_pdf_lights = 1.0f/kintegrator->pdf_lights;
376                 }
377
378                 kintegrator->use_lamp_mis = use_lamp_mis;
379
380                 /* bit of an ugly hack to compensate for emitting triangles influencing
381                  * amount of samples we get for this pass */
382                 kfilm->pass_shadow_scale = 1.0f;
383
384                 if(kintegrator->pdf_triangles != 0.0f)
385                         kfilm->pass_shadow_scale *= 0.5f;
386
387                 if(num_background_lights < num_lights)
388                         kfilm->pass_shadow_scale *= (float)(num_lights - num_background_lights)/(float)num_lights;
389
390                 /* CDF */
391                 device->tex_alloc("__light_distribution", dscene->light_distribution);
392         }
393         else {
394                 dscene->light_distribution.clear();
395
396                 kintegrator->num_distribution = 0;
397                 kintegrator->num_all_lights = 0;
398                 kintegrator->pdf_triangles = 0.0f;
399                 kintegrator->pdf_lights = 0.0f;
400                 kintegrator->inv_pdf_lights = 0.0f;
401                 kintegrator->use_lamp_mis = false;
402                 kfilm->pass_shadow_scale = 1.0f;
403         }
404 }
405
406 void LightManager::device_update_background(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
407 {
408         KernelIntegrator *kintegrator = &dscene->data.integrator;
409         Light *background_light = NULL;
410
411         /* find background light */
412         foreach(Light *light, scene->lights) {
413                 if(light->type == LIGHT_BACKGROUND) {
414                         background_light = light;
415                         break;
416                 }
417         }
418
419         /* no background light found, signal renderer to skip sampling */
420         if(!background_light) {
421                 kintegrator->pdf_background_res = 0;
422                 return;
423         }
424
425         progress.set_status("Updating Lights", "Importance map");
426
427         assert(kintegrator->use_direct_light);
428
429         /* get the resolution from the light's size (we stuff it in there) */
430         int res = background_light->map_resolution;
431         kintegrator->pdf_background_res = res;
432
433         assert(res > 0);
434
435         vector<float3> pixels;
436         dump_background_pixels(device, dscene, res, pixels);
437
438         if(progress.get_cancel())
439                 return;
440
441         /* build row distributions and column distribution for the infinite area environment light */
442         int cdf_count = res + 1;
443         float2 *marg_cdf = dscene->light_background_marginal_cdf.resize(cdf_count);
444         float2 *cond_cdf = dscene->light_background_conditional_cdf.resize(cdf_count * cdf_count);
445
446         /* conditional CDFs (rows, U direction) */
447         for(int i = 0; i < res; i++) {
448                 float sin_theta = sinf(M_PI_F * (i + 0.5f) / res);
449                 float3 env_color = pixels[i * res];
450                 float ave_luminamce = average(env_color);
451
452                 cond_cdf[i * cdf_count].x = ave_luminamce * sin_theta;
453                 cond_cdf[i * cdf_count].y = 0.0f;
454
455                 for(int j = 1; j < res; j++) {
456                         env_color = pixels[i * res + j];
457                         ave_luminamce = average(env_color);
458
459                         cond_cdf[i * cdf_count + j].x = ave_luminamce * sin_theta;
460                         cond_cdf[i * cdf_count + j].y = cond_cdf[i * cdf_count + j - 1].y + cond_cdf[i * cdf_count + j - 1].x / res;
461                 }
462
463                 float cdf_total = cond_cdf[i * cdf_count + res - 1].y + cond_cdf[i * cdf_count + res - 1].x / res;
464
465                 /* stuff the total into the brightness value for the last entry, because
466                  * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
467                 cond_cdf[i * cdf_count + res].x = cdf_total;
468
469                 if(cdf_total > 0.0f)
470                         for(int j = 1; j < res; j++)
471                                 cond_cdf[i * cdf_count + j].y /= cdf_total;
472
473                 cond_cdf[i * cdf_count + res].y = 1.0f;
474         }
475
476         /* marginal CDFs (column, V direction, sum of rows) */
477         marg_cdf[0].x = cond_cdf[res].x;
478         marg_cdf[0].y = 0.0f;
479
480         for(int i = 1; i < res; i++) {
481                 marg_cdf[i].x = cond_cdf[i * cdf_count + res].x;
482                 marg_cdf[i].y = marg_cdf[i - 1].y + marg_cdf[i - 1].x / res;
483         }
484
485         float cdf_total = marg_cdf[res - 1].y + marg_cdf[res - 1].x / res;
486         marg_cdf[res].x = cdf_total;
487
488         if(cdf_total > 0.0f)
489                 for(int i = 1; i < res; i++)
490                         marg_cdf[i].y /= cdf_total;
491
492         marg_cdf[res].y = 1.0f;
493
494         /* update device */
495         device->tex_alloc("__light_background_marginal_cdf", dscene->light_background_marginal_cdf);
496         device->tex_alloc("__light_background_conditional_cdf", dscene->light_background_conditional_cdf);
497 }
498
499 void LightManager::device_update_points(Device *device, DeviceScene *dscene, Scene *scene)
500 {
501         if(scene->lights.size() == 0)
502                 return;
503
504         float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE);
505
506         if(!device->info.advanced_shading) {
507                 /* remove unsupported light */
508                 foreach(Light *light, scene->lights) {
509                         if(light->type == LIGHT_BACKGROUND) {
510                                 scene->lights.erase(std::remove(scene->lights.begin(), scene->lights.end(), light), scene->lights.end());
511                                 break;
512                         }
513                 }
514         }
515
516         for(size_t i = 0; i < scene->lights.size(); i++) {
517                 Light *light = scene->lights[i];
518                 float3 co = light->co;
519                 float3 dir = normalize(light->dir);
520                 int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader);
521                 float samples = __int_as_float(light->samples);
522
523                 if(!light->cast_shadow)
524                         shader_id &= ~SHADER_CAST_SHADOW;
525
526                 if(!light->use_diffuse) {
527                         shader_id |= SHADER_EXCLUDE_DIFFUSE;
528                         use_light_visibility = true;
529                 }
530                 if(!light->use_glossy) {
531                         shader_id |= SHADER_EXCLUDE_GLOSSY;
532                         use_light_visibility = true;
533                 }
534                 if(!light->use_transmission) {
535                         shader_id |= SHADER_EXCLUDE_TRANSMIT;
536                         use_light_visibility = true;
537                 }
538
539                 if(light->type == LIGHT_POINT) {
540                         shader_id &= ~SHADER_AREA_LIGHT;
541
542                         float radius = light->size;
543                         float invarea = (radius > 0.0f)? 1.0f/(M_PI_F*radius*radius): 1.0f;
544
545                         if(light->use_mis && radius > 0.0f)
546                                 shader_id |= SHADER_USE_MIS;
547
548                         light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
549                         light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f);
550                         light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
551                         light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
552                 }
553                 else if(light->type == LIGHT_DISTANT) {
554                         shader_id &= ~SHADER_AREA_LIGHT;
555
556                         float radius = light->size;
557                         float angle = atanf(radius);
558                         float cosangle = cosf(angle);
559                         float area = M_PI_F*radius*radius;
560                         float invarea = (area > 0.0f)? 1.0f/area: 1.0f;
561
562                         if(light->use_mis && area > 0.0f)
563                                 shader_id |= SHADER_USE_MIS;
564
565                         light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z);
566                         light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea);
567                         light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
568                         light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
569                 }
570                 else if(light->type == LIGHT_BACKGROUND) {
571                         shader_id &= ~SHADER_AREA_LIGHT;
572                         shader_id |= SHADER_USE_MIS;
573
574                         light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f);
575                         light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
576                         light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
577                         light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
578                 }
579                 else if(light->type == LIGHT_AREA) {
580                         float3 axisu = light->axisu*(light->sizeu*light->size);
581                         float3 axisv = light->axisv*(light->sizev*light->size);
582                         float area = len(axisu)*len(axisv);
583                         float invarea = (area > 0.0f)? 1.0f/area: 1.0f;
584
585                         if(light->use_mis && area > 0.0f)
586                                 shader_id |= SHADER_USE_MIS;
587
588                         light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
589                         light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
590                         light_data[i*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
591                         light_data[i*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z);
592                 }
593                 else if(light->type == LIGHT_SPOT) {
594                         shader_id &= ~SHADER_AREA_LIGHT;
595
596                         float radius = light->size;
597                         float invarea = (radius > 0.0f)? 1.0f/(M_PI_F*radius*radius): 1.0f;
598                         float spot_angle = cosf(light->spot_angle*0.5f);
599                         float spot_smooth = (1.0f - spot_angle)*light->spot_smooth;
600
601                         if(light->use_mis && radius > 0.0f)
602                                 shader_id |= SHADER_USE_MIS;
603
604                         light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
605                         light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle);
606                         light_data[i*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z);
607                         light_data[i*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
608                 }
609         }
610         
611         device->tex_alloc("__light_data", dscene->light_data);
612 }
613
614 void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
615 {
616         if(!need_update)
617                 return;
618
619         device_free(device, dscene);
620
621         use_light_visibility = false;
622
623         device_update_points(device, dscene, scene);
624         if(progress.get_cancel()) return;
625
626         device_update_distribution(device, dscene, scene, progress);
627         if(progress.get_cancel()) return;
628
629         device_update_background(device, dscene, scene, progress);
630         if(progress.get_cancel()) return;
631
632         if(use_light_visibility != scene->film->use_light_visibility) {
633                 scene->film->use_light_visibility = use_light_visibility;
634                 scene->film->tag_update(scene);
635         }
636
637         need_update = false;
638 }
639
640 void LightManager::device_free(Device *device, DeviceScene *dscene)
641 {
642         device->tex_free(dscene->light_distribution);
643         device->tex_free(dscene->light_data);
644         device->tex_free(dscene->light_background_marginal_cdf);
645         device->tex_free(dscene->light_background_conditional_cdf);
646
647         dscene->light_distribution.clear();
648         dscene->light_data.clear();
649         dscene->light_background_marginal_cdf.clear();
650         dscene->light_background_conditional_cdf.clear();
651 }
652
653 void LightManager::tag_update(Scene *scene)
654 {
655         need_update = true;
656 }
657
658 CCL_NAMESPACE_END
659