Code refactor: move more memory allocation logic into device API.
[blender-staging.git] / intern / cycles / render / light.cpp
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/background.h"
18 #include "device/device.h"
19 #include "render/integrator.h"
20 #include "render/film.h"
21 #include "render/light.h"
22 #include "render/mesh.h"
23 #include "render/object.h"
24 #include "render/scene.h"
25 #include "render/shader.h"
26
27 #include "util/util_foreach.h"
28 #include "util/util_progress.h"
29 #include "util/util_logging.h"
30
31 CCL_NAMESPACE_BEGIN
32
33 static void shade_background_pixels(Device *device, DeviceScene *dscene, int res, vector<float3>& pixels, Progress& progress)
34 {
35         /* create input */
36         int width = res;
37         int height = res;
38
39         device_vector<uint4> d_input(device, "background_input", MEM_READ_ONLY);
40         device_vector<float4> d_output(device, "background_output", MEM_WRITE_ONLY);
41
42         uint4 *d_input_data = d_input.alloc(width*height);
43
44         for(int y = 0; y < height; y++) {
45                 for(int x = 0; x < width; x++) {
46                         float u = (x + 0.5f)/width;
47                         float v = (y + 0.5f)/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         d_output.alloc(width*height);
56         d_output.zero_to_device();
57         d_input.copy_to_device();
58
59         device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
60
61         DeviceTask main_task(DeviceTask::SHADER);
62         main_task.shader_input = d_input.device_pointer;
63         main_task.shader_output = d_output.device_pointer;
64         main_task.shader_eval_type = SHADER_EVAL_BACKGROUND;
65         main_task.shader_x = 0;
66         main_task.shader_w = width*height;
67         main_task.num_samples = 1;
68         main_task.get_cancel = function_bind(&Progress::get_cancel, &progress);
69
70         /* disabled splitting for now, there's an issue with multi-GPU mem_copy_from */
71         list<DeviceTask> split_tasks;
72         main_task.split(split_tasks, 1, 128*128);
73
74         foreach(DeviceTask& task, split_tasks) {
75                 device->task_add(task);
76                 device->task_wait();
77                 d_output.copy_from_device(task.shader_x, 1, task.shader_w);
78         }
79
80         d_input.free();
81
82         float4 *d_output_data = reinterpret_cast<float4*>(d_output.data_pointer);
83
84         pixels.resize(width*height);
85
86         for(int y = 0; y < height; y++) {
87                 for(int x = 0; x < width; x++) {
88                         pixels[y*width + x].x = d_output_data[y*width + x].x;
89                         pixels[y*width + x].y = d_output_data[y*width + x].y;
90                         pixels[y*width + x].z = d_output_data[y*width + x].z;
91                 }
92         }
93
94         d_output.free();
95 }
96
97 /* Light */
98
99 NODE_DEFINE(Light)
100 {
101         NodeType* type = NodeType::add("light", create);
102
103         static NodeEnum type_enum;
104         type_enum.insert("point", LIGHT_POINT);
105         type_enum.insert("distant", LIGHT_DISTANT);
106         type_enum.insert("background", LIGHT_BACKGROUND);
107         type_enum.insert("area", LIGHT_AREA);
108         type_enum.insert("spot", LIGHT_SPOT);
109         SOCKET_ENUM(type, "Type", type_enum, LIGHT_POINT);
110
111         SOCKET_POINT(co, "Co", make_float3(0.0f, 0.0f, 0.0f));
112
113         SOCKET_VECTOR(dir, "Dir", make_float3(0.0f, 0.0f, 0.0f));
114         SOCKET_FLOAT(size, "Size", 0.0f);
115
116         SOCKET_VECTOR(axisu, "Axis U", make_float3(0.0f, 0.0f, 0.0f));
117         SOCKET_FLOAT(sizeu, "Size U", 1.0f);
118         SOCKET_VECTOR(axisv, "Axis V", make_float3(0.0f, 0.0f, 0.0f));
119         SOCKET_FLOAT(sizev, "Size V", 1.0f);
120
121         SOCKET_INT(map_resolution, "Map Resolution", 512);
122
123         SOCKET_FLOAT(spot_angle, "Spot Angle", M_PI_4_F);
124         SOCKET_FLOAT(spot_smooth, "Spot Smooth", 0.0f);
125
126         SOCKET_TRANSFORM(tfm, "Transform", transform_identity());
127
128         SOCKET_BOOLEAN(cast_shadow, "Cast Shadow", true);
129         SOCKET_BOOLEAN(use_mis, "Use Mis", false);
130         SOCKET_BOOLEAN(use_diffuse, "Use Diffuse", true);
131         SOCKET_BOOLEAN(use_glossy, "Use Glossy", true);
132         SOCKET_BOOLEAN(use_transmission, "Use Transmission", true);
133         SOCKET_BOOLEAN(use_scatter, "Use Scatter", true);
134
135         SOCKET_INT(samples, "Samples", 1);
136         SOCKET_INT(max_bounces, "Max Bounces", 1024);
137
138         SOCKET_BOOLEAN(is_portal, "Is Portal", false);
139         SOCKET_BOOLEAN(is_enabled, "Is Enabled", true);
140
141         SOCKET_NODE(shader, "Shader", &Shader::node_type);
142
143         return type;
144 }
145
146 Light::Light()
147 : Node(node_type)
148 {
149 }
150
151 void Light::tag_update(Scene *scene)
152 {
153         scene->light_manager->need_update = true;
154 }
155
156 bool Light::has_contribution(Scene *scene)
157 {
158         if(is_portal) {
159                 return false;
160         }
161         if(type == LIGHT_BACKGROUND) {
162                 return true;
163         }
164         return (shader) ? shader->has_surface_emission : scene->default_light->has_surface_emission;
165 }
166
167 /* Light Manager */
168
169 LightManager::LightManager()
170 {
171         need_update = true;
172         use_light_visibility = false;
173 }
174
175 LightManager::~LightManager()
176 {
177 }
178
179 bool LightManager::has_background_light(Scene *scene)
180 {
181         foreach(Light *light, scene->lights) {
182                 if(light->type == LIGHT_BACKGROUND) {
183                         return true;
184                 }
185         }
186         return false;
187 }
188
189 void LightManager::disable_ineffective_light(Device *device, Scene *scene)
190 {
191         /* Make all lights enabled by default, and perform some preliminary checks
192          * needed for finer-tuning of settings (for example, check whether we've
193          * got portals or not).
194          */
195         bool has_portal = false, has_background = false;
196         foreach(Light *light, scene->lights) {
197                 light->is_enabled = light->has_contribution(scene);
198                 has_portal |= light->is_portal;
199                 has_background |= light->type == LIGHT_BACKGROUND;
200         }
201
202         if(has_background) {
203                 /* Ignore background light if:
204                  * - If unsupported on a device
205                  * - If we don't need it (no HDRs etc.)
206                  */
207                 Shader *shader = (scene->background->shader) ? scene->background->shader : scene->default_background;
208                 bool disable_mis = !(has_portal || shader->has_surface_spatial_varying) ||
209                                    !(device->info.advanced_shading);
210                 if(disable_mis) {
211                         VLOG(1) << "Background MIS has been disabled.\n";
212                         foreach(Light *light, scene->lights) {
213                                 if(light->type == LIGHT_BACKGROUND) {
214                                         light->is_enabled = false;
215                                 }
216                         }
217                 }
218         }
219 }
220
221 bool LightManager::object_usable_as_light(Object *object) {
222         Mesh *mesh = object->mesh;
223         /* Skip objects with NaNs */
224         if(!object->bounds.valid()) {
225                 return false;
226         }
227         /* Skip if we are not visible for BSDFs. */
228         if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) {
229                 return false;
230         }
231         /* Skip if we have no emission shaders. */
232         /* TODO(sergey): Ideally we want to avoid such duplicated loop, since it'll
233          * iterate all mesh shaders twice (when counting and when calculating
234          * triangle area.
235          */
236         foreach(const Shader *shader, mesh->used_shaders) {
237                 if(shader->use_mis && shader->has_surface_emission) {
238                         return true;
239                 }
240         }
241         return false;
242 }
243
244 void LightManager::device_update_distribution(Device *, DeviceScene *dscene, Scene *scene, Progress& progress)
245 {
246         progress.set_status("Updating Lights", "Computing distribution");
247
248         /* count */
249         size_t num_lights = 0;
250         size_t num_portals = 0;
251         size_t num_background_lights = 0;
252         size_t num_triangles = 0;
253
254         bool background_mis = false;
255
256         foreach(Light *light, scene->lights) {
257                 if(light->is_enabled) {
258                         num_lights++;
259                 }
260                 if(light->is_portal) {
261                         num_portals++;
262                 }
263         }
264
265         foreach(Object *object, scene->objects) {
266                 if(progress.get_cancel()) return;
267
268                 if(!object_usable_as_light(object)) {
269                         continue;
270                 }
271                 /* Count triangles. */
272                 Mesh *mesh = object->mesh;
273                 size_t mesh_num_triangles = mesh->num_triangles();
274                 for(size_t i = 0; i < mesh_num_triangles; i++) {
275                         int shader_index = mesh->shader[i];
276                         Shader *shader = (shader_index < mesh->used_shaders.size())
277                                                  ? mesh->used_shaders[shader_index]
278                                                  : scene->default_surface;
279
280                         if(shader->use_mis && shader->has_surface_emission) {
281                                 num_triangles++;
282                         }
283                 }
284         }
285
286         size_t num_distribution = num_triangles + num_lights;
287         VLOG(1) << "Total " << num_distribution << " of light distribution primitives.";
288
289         /* emission area */
290         float4 *distribution = dscene->light_distribution.alloc(num_distribution + 1);
291         float totarea = 0.0f;
292
293         /* triangles */
294         size_t offset = 0;
295         int j = 0;
296
297         foreach(Object *object, scene->objects) {
298                 if(progress.get_cancel()) return;
299
300                 if(!object_usable_as_light(object)) {
301                         j++;
302                         continue;
303                 }
304                 /* Sum area. */
305                 Mesh *mesh = object->mesh;
306                 bool transform_applied = mesh->transform_applied;
307                 Transform tfm = object->tfm;
308                 int object_id = j;
309                 int shader_flag = 0;
310
311                 if(!(object->visibility & PATH_RAY_DIFFUSE)) {
312                         shader_flag |= SHADER_EXCLUDE_DIFFUSE;
313                         use_light_visibility = true;
314                 }
315                 if(!(object->visibility & PATH_RAY_GLOSSY)) {
316                         shader_flag |= SHADER_EXCLUDE_GLOSSY;
317                         use_light_visibility = true;
318                 }
319                 if(!(object->visibility & PATH_RAY_TRANSMIT)) {
320                         shader_flag |= SHADER_EXCLUDE_TRANSMIT;
321                         use_light_visibility = true;
322                 }
323                 if(!(object->visibility & PATH_RAY_VOLUME_SCATTER)) {
324                         shader_flag |= SHADER_EXCLUDE_SCATTER;
325                         use_light_visibility = true;
326                 }
327
328                 size_t mesh_num_triangles = mesh->num_triangles();
329                 for(size_t i = 0; i < mesh_num_triangles; i++) {
330                         int shader_index = mesh->shader[i];
331                         Shader *shader = (shader_index < mesh->used_shaders.size())
332                                                  ? mesh->used_shaders[shader_index]
333                                                  : scene->default_surface;
334
335                         if(shader->use_mis && shader->has_surface_emission) {
336                                 distribution[offset].x = totarea;
337                                 distribution[offset].y = __int_as_float(i + mesh->tri_offset);
338                                 distribution[offset].z = __int_as_float(shader_flag);
339                                 distribution[offset].w = __int_as_float(object_id);
340                                 offset++;
341
342                                 Mesh::Triangle t = mesh->get_triangle(i);
343                                 if(!t.valid(&mesh->verts[0])) {
344                                         continue;
345                                 }
346                                 float3 p1 = mesh->verts[t.v[0]];
347                                 float3 p2 = mesh->verts[t.v[1]];
348                                 float3 p3 = mesh->verts[t.v[2]];
349
350                                 if(!transform_applied) {
351                                         p1 = transform_point(&tfm, p1);
352                                         p2 = transform_point(&tfm, p2);
353                                         p3 = transform_point(&tfm, p3);
354                                 }
355
356                                 totarea += triangle_area(p1, p2, p3);
357                         }
358                 }
359
360                 j++;
361         }
362
363         float trianglearea = totarea;
364
365         /* point lights */
366         float lightarea = (totarea > 0.0f) ? totarea / num_lights : 1.0f;
367         bool use_lamp_mis = false;
368
369         int light_index = 0;
370         foreach(Light *light, scene->lights) {
371                 if(!light->is_enabled)
372                         continue;
373
374                 distribution[offset].x = totarea;
375                 distribution[offset].y = __int_as_float(~light_index);
376                 distribution[offset].z = 1.0f;
377                 distribution[offset].w = light->size;
378                 totarea += lightarea;
379
380                 if(light->size > 0.0f && light->use_mis)
381                         use_lamp_mis = true;
382                 if(light->type == LIGHT_BACKGROUND) {
383                         num_background_lights++;
384                         background_mis = light->use_mis;
385                 }
386
387                 light_index++;
388                 offset++;
389         }
390
391         /* normalize cumulative distribution functions */
392         distribution[num_distribution].x = totarea;
393         distribution[num_distribution].y = 0.0f;
394         distribution[num_distribution].z = 0.0f;
395         distribution[num_distribution].w = 0.0f;
396
397         if(totarea > 0.0f) {
398                 for(size_t i = 0; i < num_distribution; i++)
399                         distribution[i].x /= totarea;
400                 distribution[num_distribution].x = 1.0f;
401         }
402
403         if(progress.get_cancel()) return;
404
405         /* update device */
406         KernelIntegrator *kintegrator = &dscene->data.integrator;
407         KernelFilm *kfilm = &dscene->data.film;
408         kintegrator->use_direct_light = (totarea > 0.0f);
409
410         if(kintegrator->use_direct_light) {
411                 /* number of emissives */
412                 kintegrator->num_distribution = num_distribution;
413
414                 /* precompute pdfs */
415                 kintegrator->pdf_triangles = 0.0f;
416                 kintegrator->pdf_lights = 0.0f;
417                 kintegrator->inv_pdf_lights = 0.0f;
418
419                 /* sample one, with 0.5 probability of light or triangle */
420                 kintegrator->num_all_lights = num_lights;
421
422                 if(trianglearea > 0.0f) {
423                         kintegrator->pdf_triangles = 1.0f/trianglearea;
424                         if(num_lights)
425                                 kintegrator->pdf_triangles *= 0.5f;
426                 }
427
428                 if(num_lights) {
429                         kintegrator->pdf_lights = 1.0f/num_lights;
430                         if(trianglearea > 0.0f)
431                                 kintegrator->pdf_lights *= 0.5f;
432
433                         kintegrator->inv_pdf_lights = 1.0f/kintegrator->pdf_lights;
434                 }
435
436                 kintegrator->use_lamp_mis = use_lamp_mis;
437
438                 /* bit of an ugly hack to compensate for emitting triangles influencing
439                  * amount of samples we get for this pass */
440                 kfilm->pass_shadow_scale = 1.0f;
441
442                 if(kintegrator->pdf_triangles != 0.0f)
443                         kfilm->pass_shadow_scale *= 0.5f;
444
445                 if(num_background_lights < num_lights)
446                         kfilm->pass_shadow_scale *= (float)(num_lights - num_background_lights)/(float)num_lights;
447
448                 /* CDF */
449                 dscene->light_distribution.copy_to_device();
450
451                 /* Portals */
452                 if(num_portals > 0) {
453                         kintegrator->portal_offset = light_index;
454                         kintegrator->num_portals = num_portals;
455                         kintegrator->portal_pdf = background_mis? 0.5f: 1.0f;
456                 }
457                 else {
458                         kintegrator->num_portals = 0;
459                         kintegrator->portal_offset = 0;
460                         kintegrator->portal_pdf = 0.0f;
461                 }
462         }
463         else {
464                 dscene->light_distribution.free();
465
466                 kintegrator->num_distribution = 0;
467                 kintegrator->num_all_lights = 0;
468                 kintegrator->pdf_triangles = 0.0f;
469                 kintegrator->pdf_lights = 0.0f;
470                 kintegrator->inv_pdf_lights = 0.0f;
471                 kintegrator->use_lamp_mis = false;
472                 kintegrator->num_portals = 0;
473                 kintegrator->portal_offset = 0;
474                 kintegrator->portal_pdf = 0.0f;
475
476                 kfilm->pass_shadow_scale = 1.0f;
477         }
478 }
479
480 static void background_cdf(int start,
481                            int end,
482                            int res,
483                            int cdf_count,
484                            const vector<float3> *pixels,
485                            float2 *cond_cdf)
486 {
487         /* Conditional CDFs (rows, U direction). */
488         for(int i = start; i < end; i++) {
489                 float sin_theta = sinf(M_PI_F * (i + 0.5f) / res);
490                 float3 env_color = (*pixels)[i * res];
491                 float ave_luminance = average(env_color);
492
493                 cond_cdf[i * cdf_count].x = ave_luminance * sin_theta;
494                 cond_cdf[i * cdf_count].y = 0.0f;
495
496                 for(int j = 1; j < res; j++) {
497                         env_color = (*pixels)[i * res + j];
498                         ave_luminance = average(env_color);
499
500                         cond_cdf[i * cdf_count + j].x = ave_luminance * sin_theta;
501                         cond_cdf[i * cdf_count + j].y = cond_cdf[i * cdf_count + j - 1].y + cond_cdf[i * cdf_count + j - 1].x / res;
502                 }
503
504                 float cdf_total = cond_cdf[i * cdf_count + res - 1].y + cond_cdf[i * cdf_count + res - 1].x / res;
505                 float cdf_total_inv = 1.0f / cdf_total;
506
507                 /* stuff the total into the brightness value for the last entry, because
508                  * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
509                 cond_cdf[i * cdf_count + res].x = cdf_total;
510
511                 if(cdf_total > 0.0f)
512                         for(int j = 1; j < res; j++)
513                                 cond_cdf[i * cdf_count + j].y *= cdf_total_inv;
514
515                 cond_cdf[i * cdf_count + res].y = 1.0f;
516         }
517 }
518
519 void LightManager::device_update_background(Device *device,
520                                             DeviceScene *dscene,
521                                             Scene *scene,
522                                             Progress& progress)
523 {
524         KernelIntegrator *kintegrator = &dscene->data.integrator;
525         Light *background_light = NULL;
526
527         /* find background light */
528         foreach(Light *light, scene->lights) {
529                 if(light->type == LIGHT_BACKGROUND) {
530                         background_light = light;
531                         break;
532                 }
533         }
534
535         /* no background light found, signal renderer to skip sampling */
536         if(!background_light || !background_light->is_enabled) {
537                 kintegrator->pdf_background_res = 0;
538                 return;
539         }
540
541         progress.set_status("Updating Lights", "Importance map");
542
543         assert(kintegrator->use_direct_light);
544
545         /* get the resolution from the light's size (we stuff it in there) */
546         int res = background_light->map_resolution;
547         kintegrator->pdf_background_res = res;
548
549         assert(res > 0);
550
551         vector<float3> pixels;
552         shade_background_pixels(device, dscene, res, pixels, progress);
553
554         if(progress.get_cancel())
555                 return;
556
557         /* build row distributions and column distribution for the infinite area environment light */
558         int cdf_count = res + 1;
559         float2 *marg_cdf = dscene->light_background_marginal_cdf.alloc(cdf_count);
560         float2 *cond_cdf = dscene->light_background_conditional_cdf.alloc(cdf_count * cdf_count);
561
562         double time_start = time_dt();
563         if(res < 512) {
564                 /* Small enough resolution, faster to do single-threaded. */
565                 background_cdf(0, res, res, cdf_count, &pixels, cond_cdf);
566         }
567         else {
568                 /* Threaded evaluation for large resolution. */
569                 const int num_blocks = TaskScheduler::num_threads();
570                 const int chunk_size = res / num_blocks;
571                 int start_row = 0;
572                 TaskPool pool;
573                 for(int i = 0; i < num_blocks; ++i) {
574                         const int current_chunk_size =
575                             (i != num_blocks - 1) ? chunk_size
576                                                   : (res - i * chunk_size);
577                         pool.push(function_bind(&background_cdf,
578                                                 start_row, start_row + current_chunk_size,
579                                                 res,
580                                                 cdf_count,
581                                                 &pixels,
582                                                 cond_cdf));
583                         start_row += current_chunk_size;
584                 }
585                 pool.wait_work();
586         }
587
588         /* marginal CDFs (column, V direction, sum of rows) */
589         marg_cdf[0].x = cond_cdf[res].x;
590         marg_cdf[0].y = 0.0f;
591
592         for(int i = 1; i < res; i++) {
593                 marg_cdf[i].x = cond_cdf[i * cdf_count + res].x;
594                 marg_cdf[i].y = marg_cdf[i - 1].y + marg_cdf[i - 1].x / res;
595         }
596
597         float cdf_total = marg_cdf[res - 1].y + marg_cdf[res - 1].x / res;
598         marg_cdf[res].x = cdf_total;
599
600         if(cdf_total > 0.0f)
601                 for(int i = 1; i < res; i++)
602                         marg_cdf[i].y /= cdf_total;
603
604         marg_cdf[res].y = 1.0f;
605
606         VLOG(2) << "Background MIS build time " << time_dt() - time_start << "\n";
607
608         /* update device */
609         dscene->light_background_marginal_cdf.copy_to_device();
610         dscene->light_background_conditional_cdf.copy_to_device();
611 }
612
613 void LightManager::device_update_points(Device *,
614                                         DeviceScene *dscene,
615                                         Scene *scene)
616 {
617         int num_scene_lights = scene->lights.size();
618
619         int num_lights = 0;
620         foreach(Light *light, scene->lights) {
621                 if(light->is_enabled || light->is_portal) {
622                         num_lights++;
623                 }
624         }
625
626         float4 *light_data = dscene->light_data.alloc(num_lights*LIGHT_SIZE);
627
628         if(num_lights == 0) {
629                 VLOG(1) << "No effective light, ignoring points update.";
630                 return;
631         }
632
633         int light_index = 0;
634
635         foreach(Light *light, scene->lights) {
636                 if(!light->is_enabled) {
637                         continue;
638                 }
639
640                 float3 co = light->co;
641                 Shader *shader = (light->shader) ? light->shader : scene->default_light;
642                 int shader_id = scene->shader_manager->get_shader_id(shader);
643                 float samples = __int_as_float(light->samples);
644                 float max_bounces = __int_as_float(light->max_bounces);
645
646                 if(!light->cast_shadow)
647                         shader_id &= ~SHADER_CAST_SHADOW;
648
649                 if(!light->use_diffuse) {
650                         shader_id |= SHADER_EXCLUDE_DIFFUSE;
651                         use_light_visibility = true;
652                 }
653                 if(!light->use_glossy) {
654                         shader_id |= SHADER_EXCLUDE_GLOSSY;
655                         use_light_visibility = true;
656                 }
657                 if(!light->use_transmission) {
658                         shader_id |= SHADER_EXCLUDE_TRANSMIT;
659                         use_light_visibility = true;
660                 }
661                 if(!light->use_scatter) {
662                         shader_id |= SHADER_EXCLUDE_SCATTER;
663                         use_light_visibility = true;
664                 }
665
666                 if(light->type == LIGHT_POINT) {
667                         shader_id &= ~SHADER_AREA_LIGHT;
668
669                         float radius = light->size;
670                         float invarea = (radius > 0.0f)? 1.0f/(M_PI_F*radius*radius): 1.0f;
671
672                         if(light->use_mis && radius > 0.0f)
673                                 shader_id |= SHADER_USE_MIS;
674
675                         light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
676                         light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, 0.0f);
677                         light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
678                         light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
679                 }
680                 else if(light->type == LIGHT_DISTANT) {
681                         shader_id &= ~SHADER_AREA_LIGHT;
682
683                         float radius = light->size;
684                         float angle = atanf(radius);
685                         float cosangle = cosf(angle);
686                         float area = M_PI_F*radius*radius;
687                         float invarea = (area > 0.0f)? 1.0f/area: 1.0f;
688                         float3 dir = light->dir;
689
690                         dir = safe_normalize(dir);
691
692                         if(light->use_mis && area > 0.0f)
693                                 shader_id |= SHADER_USE_MIS;
694
695                         light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z);
696                         light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, cosangle, invarea);
697                         light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
698                         light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
699                 }
700                 else if(light->type == LIGHT_BACKGROUND) {
701                         uint visibility = scene->background->visibility;
702
703                         shader_id &= ~SHADER_AREA_LIGHT;
704                         shader_id |= SHADER_USE_MIS;
705
706                         if(!(visibility & PATH_RAY_DIFFUSE)) {
707                                 shader_id |= SHADER_EXCLUDE_DIFFUSE;
708                                 use_light_visibility = true;
709                         }
710                         if(!(visibility & PATH_RAY_GLOSSY)) {
711                                 shader_id |= SHADER_EXCLUDE_GLOSSY;
712                                 use_light_visibility = true;
713                         }
714                         if(!(visibility & PATH_RAY_TRANSMIT)) {
715                                 shader_id |= SHADER_EXCLUDE_TRANSMIT;
716                                 use_light_visibility = true;
717                         }
718                         if(!(visibility & PATH_RAY_VOLUME_SCATTER)) {
719                                 shader_id |= SHADER_EXCLUDE_SCATTER;
720                                 use_light_visibility = true;
721                         }
722
723                         light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f);
724                         light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
725                         light_data[light_index*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
726                         light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
727                 }
728                 else if(light->type == LIGHT_AREA) {
729                         float3 axisu = light->axisu*(light->sizeu*light->size);
730                         float3 axisv = light->axisv*(light->sizev*light->size);
731                         float area = len(axisu)*len(axisv);
732                         float invarea = (area > 0.0f)? 1.0f/area: 1.0f;
733                         float3 dir = light->dir;
734                         
735                         dir = safe_normalize(dir);
736
737                         if(light->use_mis && area > 0.0f)
738                                 shader_id |= SHADER_USE_MIS;
739
740                         light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
741                         light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
742                         light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
743                         light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, dir.x, dir.y, dir.z);
744                 }
745                 else if(light->type == LIGHT_SPOT) {
746                         shader_id &= ~SHADER_AREA_LIGHT;
747
748                         float radius = light->size;
749                         float invarea = (radius > 0.0f)? 1.0f/(M_PI_F*radius*radius): 1.0f;
750                         float spot_angle = cosf(light->spot_angle*0.5f);
751                         float spot_smooth = (1.0f - spot_angle)*light->spot_smooth;
752                         float3 dir = light->dir;
753                         
754                         dir = safe_normalize(dir);
755
756                         if(light->use_mis && radius > 0.0f)
757                                 shader_id |= SHADER_USE_MIS;
758
759                         light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
760                         light_data[light_index*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), radius, invarea, spot_angle);
761                         light_data[light_index*LIGHT_SIZE + 2] = make_float4(spot_smooth, dir.x, dir.y, dir.z);
762                         light_data[light_index*LIGHT_SIZE + 3] = make_float4(samples, 0.0f, 0.0f, 0.0f);
763                 }
764
765                 light_data[light_index*LIGHT_SIZE + 4] = make_float4(max_bounces, 0.0f, 0.0f, 0.0f);
766
767                 Transform tfm = light->tfm;
768                 Transform itfm = transform_inverse(tfm);
769                 memcpy(&light_data[light_index*LIGHT_SIZE + 5], &tfm, sizeof(float4)*3);
770                 memcpy(&light_data[light_index*LIGHT_SIZE + 8], &itfm, sizeof(float4)*3);
771
772                 light_index++;
773         }
774
775         /* TODO(sergey): Consider moving portals update to their own function
776          * keeping this one more manageable.
777          */
778         foreach(Light *light, scene->lights) {
779                 if(!light->is_portal)
780                         continue;
781                 assert(light->type == LIGHT_AREA);
782
783                 float3 co = light->co;
784                 float3 axisu = light->axisu*(light->sizeu*light->size);
785                 float3 axisv = light->axisv*(light->sizev*light->size);
786                 float area = len(axisu)*len(axisv);
787                 float invarea = (area > 0.0f) ? 1.0f / area : 1.0f;
788                 float3 dir = light->dir;
789
790                 dir = safe_normalize(dir);
791
792                 light_data[light_index*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
793                 light_data[light_index*LIGHT_SIZE + 1] = make_float4(area, axisu.x, axisu.y, axisu.z);
794                 light_data[light_index*LIGHT_SIZE + 2] = make_float4(invarea, axisv.x, axisv.y, axisv.z);
795                 light_data[light_index*LIGHT_SIZE + 3] = make_float4(-1, dir.x, dir.y, dir.z);
796                 light_data[light_index*LIGHT_SIZE + 4] = make_float4(-1, 0.0f, 0.0f, 0.0f);
797
798                 Transform tfm = light->tfm;
799                 Transform itfm = transform_inverse(tfm);
800                 memcpy(&light_data[light_index*LIGHT_SIZE + 5], &tfm, sizeof(float4)*3);
801                 memcpy(&light_data[light_index*LIGHT_SIZE + 8], &itfm, sizeof(float4)*3);
802
803                 light_index++;
804         }
805
806         VLOG(1) << "Number of lights sent to the device: " << light_index;
807
808         VLOG(1) << "Number of lights without contribution: "
809                 << num_scene_lights - light_index;
810
811         dscene->light_data.copy_to_device();
812 }
813
814 void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
815 {
816         if(!need_update)
817                 return;
818
819         VLOG(1) << "Total " << scene->lights.size() << " lights.";
820
821         device_free(device, dscene);
822
823         use_light_visibility = false;
824
825         disable_ineffective_light(device, scene);
826
827         device_update_points(device, dscene, scene);
828         if(progress.get_cancel()) return;
829
830         device_update_distribution(device, dscene, scene, progress);
831         if(progress.get_cancel()) return;
832
833         device_update_background(device, dscene, scene, progress);
834         if(progress.get_cancel()) return;
835
836         if(use_light_visibility != scene->film->use_light_visibility) {
837                 scene->film->use_light_visibility = use_light_visibility;
838                 scene->film->tag_update(scene);
839         }
840
841         need_update = false;
842 }
843
844 void LightManager::device_free(Device *, DeviceScene *dscene)
845 {
846         dscene->light_distribution.free();
847         dscene->light_data.free();
848         dscene->light_background_marginal_cdf.free();
849         dscene->light_background_conditional_cdf.free();
850 }
851
852 void LightManager::tag_update(Scene * /*scene*/)
853 {
854         need_update = true;
855 }
856
857 CCL_NAMESPACE_END
858