style cleanup: block comments
[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 "light.h"
21 #include "mesh.h"
22 #include "object.h"
23 #include "scene.h"
24 #include "shader.h"
25
26 #include "util_foreach.h"
27 #include "util_progress.h"
28
29 CCL_NAMESPACE_BEGIN
30
31 static void dump_background_pixels(Device *device, DeviceScene *dscene, int res, vector<float3>& pixels)
32 {
33         /* create input */
34         int width = res;
35         int height = res;
36
37         device_vector<uint4> d_input;
38         device_vector<float4> d_output;
39
40         uint4 *d_input_data = d_input.resize(width*height);
41
42         for(int y = 0; y < height; y++) {
43                 for(int x = 0; x < width; x++) {
44                         float u = x/(float)width;
45                         float v = y/(float)height;
46
47                         uint4 in = make_uint4(__float_as_int(u), __float_as_int(v), 0, 0);
48                         d_input_data[x + y*width] = in;
49                 }
50         }
51
52         /* compute on device */
53         float4 *d_output_data = d_output.resize(width*height);
54         memset((void*)d_output.data_pointer, 0, d_output.memory_size());
55
56         device->const_copy_to("__data", &dscene->data, sizeof(dscene->data));
57
58         device->mem_alloc(d_input, MEM_READ_ONLY);
59         device->mem_copy_to(d_input);
60         device->mem_alloc(d_output, MEM_WRITE_ONLY);
61
62         DeviceTask main_task(DeviceTask::SHADER);
63         main_task.shader_input = d_input.device_pointer;
64         main_task.shader_output = d_output.device_pointer;
65         main_task.shader_eval_type = SHADER_EVAL_BACKGROUND;
66         main_task.shader_x = 0;
67         main_task.shader_w = width*height;
68
69         list<DeviceTask> split_tasks;
70         main_task.split_max_size(split_tasks, 128*128);
71
72         foreach(DeviceTask& task, split_tasks) {
73                 device->task_add(task);
74                 device->task_wait();
75         }
76
77         device->mem_copy_from(d_output, 0, 1, d_output.size(), sizeof(float4));
78         device->mem_free(d_input);
79         device->mem_free(d_output);
80
81         d_output_data = reinterpret_cast<float4*>(d_output.data_pointer);
82
83         pixels.resize(width*height);
84
85         for(int y = 0; y < height; y++) {
86                 for(int x = 0; x < width; x++) {
87                         pixels[y*width + x].x = d_output_data[y*width + x].x;
88                         pixels[y*width + x].y = d_output_data[y*width + x].y;
89                         pixels[y*width + x].z = d_output_data[y*width + x].z;
90                 }
91         }
92 }
93
94 /* Light */
95
96 Light::Light()
97 {
98         type = LIGHT_POINT;
99
100         co = make_float3(0.0f, 0.0f, 0.0f);
101
102         dir = make_float3(0.0f, 0.0f, 0.0f);
103         size = 0.0f;
104
105         axisu = make_float3(0.0f, 0.0f, 0.0f);
106         sizeu = 1.0f;
107         axisv = make_float3(0.0f, 0.0f, 0.0f);
108         sizev = 1.0f;
109
110         map_resolution = 512;
111
112         spot_angle = M_PI_F/4.0f;
113         spot_smooth = 0.0f;
114
115         cast_shadow = true;
116         shader = 0;
117 }
118
119 void Light::tag_update(Scene *scene)
120 {
121         scene->light_manager->need_update = true;
122 }
123
124 /* Light Manager */
125
126 LightManager::LightManager()
127 {
128         need_update = true;
129 }
130
131 LightManager::~LightManager()
132 {
133 }
134
135 void LightManager::device_update_distribution(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
136 {
137         progress.set_status("Updating Lights", "Computing distribution");
138
139         /* option to always sample all point lights */
140         bool multi_light = false;
141
142         /* count */
143         size_t num_lights = scene->lights.size();
144         size_t num_triangles = 0;
145
146         foreach(Object *object, scene->objects) {
147                 Mesh *mesh = object->mesh;
148                 bool have_emission = false;
149
150                 /* skip if we have no emission shaders */
151                 foreach(uint sindex, mesh->used_shaders) {
152                         Shader *shader = scene->shaders[sindex];
153
154                         if(shader->sample_as_light && shader->has_surface_emission) {
155                                 have_emission = true;
156                                 break;
157                         }
158                 }
159
160                 /* count triangles */
161                 if(have_emission) {
162                         for(size_t i = 0; i < mesh->triangles.size(); i++) {
163                                 Shader *shader = scene->shaders[mesh->shader[i]];
164
165                                 if(shader->sample_as_light && shader->has_surface_emission)
166                                         num_triangles++;
167                         }
168                 }
169         }
170
171         size_t num_distribution = num_triangles;
172
173         if(!multi_light)
174                 num_distribution += num_lights;
175
176         /* emission area */
177         float4 *distribution = dscene->light_distribution.resize(num_distribution + 1);
178         float totarea = 0.0f;
179
180         /* triangles */
181         size_t offset = 0;
182         int j = 0;
183
184         foreach(Object *object, scene->objects) {
185                 Mesh *mesh = object->mesh;
186                 bool have_emission = false;
187
188                 /* skip if we have no emission shaders */
189                 foreach(uint sindex, mesh->used_shaders) {
190                         Shader *shader = scene->shaders[sindex];
191
192                         if(shader->sample_as_light && shader->has_surface_emission) {
193                                 have_emission = true;
194                                 break;
195                         }
196                 }
197
198                 /* sum area */
199                 if(have_emission) {
200                         Transform tfm = object->tfm;
201                         int object_id = j;
202
203                         if(mesh->transform_applied)
204                                 object_id = ~object_id;
205
206                         for(size_t i = 0; i < mesh->triangles.size(); i++) {
207                                 Shader *shader = scene->shaders[mesh->shader[i]];
208
209                                 if(shader->sample_as_light && shader->has_surface_emission) {
210                                         distribution[offset].x = totarea;
211                                         distribution[offset].y = __int_as_float(i + mesh->tri_offset);
212                                         distribution[offset].z = 1.0f;
213                                         distribution[offset].w = __int_as_float(object_id);
214                                         offset++;
215
216                                         Mesh::Triangle t = mesh->triangles[i];
217                                         float3 p1 = transform_point(&tfm, mesh->verts[t.v[0]]);
218                                         float3 p2 = transform_point(&tfm, mesh->verts[t.v[1]]);
219                                         float3 p3 = transform_point(&tfm, mesh->verts[t.v[2]]);
220
221                                         totarea += triangle_area(p1, p2, p3);
222                                 }
223                         }
224                 }
225
226                 if(progress.get_cancel()) return;
227
228                 j++;
229         }
230
231         float trianglearea = totarea;
232
233         /* point lights */
234         if(!multi_light) {
235                 float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f;
236
237                 for(int i = 0; i < scene->lights.size(); i++, offset++) {
238                         distribution[offset].x = totarea;
239                         distribution[offset].y = __int_as_float(~(int)i);
240                         distribution[offset].z = 1.0f;
241                         distribution[offset].w = scene->lights[i]->size;
242                         totarea += lightarea;
243                 }
244         }
245
246         /* normalize cumulative distribution functions */
247         distribution[num_distribution].x = totarea;
248         distribution[num_distribution].y = 0.0f;
249         distribution[num_distribution].z = 0.0f;
250         distribution[num_distribution].w = 0.0f;
251
252         if(totarea > 0.0f) {
253                 for(size_t i = 0; i < num_distribution; i++)
254                         distribution[i].x /= totarea;
255                 distribution[num_distribution].x = 1.0f;
256         }
257
258         if(progress.get_cancel()) return;
259
260         /* update device */
261         KernelIntegrator *kintegrator = &dscene->data.integrator;
262         kintegrator->use_direct_light = (totarea > 0.0f) || (multi_light && num_lights);
263
264         if(kintegrator->use_direct_light) {
265                 /* number of emissives */
266                 kintegrator->num_distribution = (totarea > 0.0f)? num_distribution: 0;
267
268                 /* precompute pdfs */
269                 kintegrator->pdf_triangles = 0.0f;
270                 kintegrator->pdf_lights = 0.0f;
271
272                 if(multi_light) {
273                         /* sample one of all triangles and all lights */
274                         kintegrator->num_all_lights = num_lights;
275
276                         if(trianglearea > 0.0f)
277                                 kintegrator->pdf_triangles = 1.0f/trianglearea;
278                         if(num_lights)
279                                 kintegrator->pdf_lights = 1.0f;
280                 }
281                 else {
282                         /* sample one, with 0.5 probability of light or triangle */
283                         kintegrator->num_all_lights = 0;
284
285                         if(trianglearea > 0.0f) {
286                                 kintegrator->pdf_triangles = 1.0f/trianglearea;
287                                 if(num_lights)
288                                         kintegrator->pdf_triangles *= 0.5f;
289                         }
290
291                         if(num_lights) {
292                                 kintegrator->pdf_lights = 1.0f/num_lights;
293                                 if(trianglearea > 0.0f)
294                                         kintegrator->pdf_lights *= 0.5f;
295                         }
296                 }
297
298                 /* CDF */
299                 device->tex_alloc("__light_distribution", dscene->light_distribution);
300         }
301         else
302                 dscene->light_distribution.clear();
303 }
304
305 void LightManager::device_update_background(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
306 {
307         KernelIntegrator *kintegrator = &dscene->data.integrator;
308         Light *background_light = NULL;
309
310         /* find background light */
311         foreach(Light *light, scene->lights) {
312                 if(light->type == LIGHT_BACKGROUND) {
313                         background_light = light;
314                         break;
315                 }
316         }
317
318         /* no background light found, signal renderer to skip sampling */
319         if(!background_light) {
320                 kintegrator->pdf_background_res = 0;
321                 return;
322         }
323
324         progress.set_status("Updating Lights", "Importance map");
325
326         assert(kintegrator->use_direct_light);
327
328         /* get the resolution from the light's size (we stuff it in there) */
329         int res = background_light->map_resolution;
330         kintegrator->pdf_background_res = res;
331
332         assert(res > 0);
333
334         vector<float3> pixels;
335         dump_background_pixels(device, dscene, res, pixels);
336
337         if(progress.get_cancel())
338                 return;
339
340         /* build row distributions and column distribution for the infinite area environment light */
341         int cdf_count = res + 1;
342         float2 *marg_cdf = dscene->light_background_marginal_cdf.resize(cdf_count);
343         float2 *cond_cdf = dscene->light_background_conditional_cdf.resize(cdf_count * cdf_count);
344
345         /* conditional CDFs (rows, U direction) */
346         for(int i = 0; i < res; i++) {
347                 float sin_theta = sinf(M_PI_F * (i + 0.5f) / res);
348                 float3 env_color = pixels[i * res];
349                 float ave_luminamce = average(env_color);
350
351                 cond_cdf[i * cdf_count].x = ave_luminamce * sin_theta;
352                 cond_cdf[i * cdf_count].y = 0.0f;
353
354                 for(int j = 1; j < res; j++) {
355                         env_color = pixels[i * res + j];
356                         ave_luminamce = average(env_color);
357
358                         cond_cdf[i * cdf_count + j].x = ave_luminamce * sin_theta;
359                         cond_cdf[i * cdf_count + j].y = cond_cdf[i * cdf_count + j - 1].y + cond_cdf[i * cdf_count + j - 1].x / res;
360                 }
361
362                 float cdf_total = cond_cdf[i * cdf_count + res - 1].y + cond_cdf[i * cdf_count + res - 1].x / res;
363
364                 /* stuff the total into the brightness value for the last entry, because
365                  * we are going to normalize the CDFs to 0.0 to 1.0 afterwards */
366                 cond_cdf[i * cdf_count + res].x = cdf_total;
367
368                 if(cdf_total > 0.0f)
369                         for(int j = 1; j < res; j++)
370                                 cond_cdf[i * cdf_count + j].y /= cdf_total;
371
372                 cond_cdf[i * cdf_count + res].y = 1.0f;
373         }
374
375         /* marginal CDFs (column, V direction, sum of rows) */
376         marg_cdf[0].x = cond_cdf[res].x;
377         marg_cdf[0].y = 0.0f;
378
379         for(int i = 1; i < res; i++) {
380                 marg_cdf[i].x = cond_cdf[i * cdf_count + res].x;
381                 marg_cdf[i].y = marg_cdf[i - 1].y + marg_cdf[i - 1].x / res;
382         }
383
384         float cdf_total = marg_cdf[res - 1].y + marg_cdf[res - 1].x / res;
385         marg_cdf[res].x = cdf_total;
386
387         if(cdf_total > 0.0f)
388                 for(int i = 1; i < res; i++)
389                         marg_cdf[i].y /= cdf_total;
390
391         marg_cdf[res].y = 1.0f;
392
393         /* update device */
394         device->tex_alloc("__light_background_marginal_cdf", dscene->light_background_marginal_cdf);
395         device->tex_alloc("__light_background_conditional_cdf", dscene->light_background_conditional_cdf);
396 }
397
398 void LightManager::device_update_points(Device *device, DeviceScene *dscene, Scene *scene)
399 {
400         if(scene->lights.size() == 0)
401                 return;
402
403         float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE);
404
405         if(!device->info.advanced_shading) {
406                 /* remove unsupported light */
407                 foreach(Light *light, scene->lights) {
408                         if(light->type == LIGHT_BACKGROUND) {
409                                 scene->lights.erase(std::remove(scene->lights.begin(), scene->lights.end(), light), scene->lights.end());
410                                 break;
411                         }
412                 }
413         }
414
415         for(size_t i = 0; i < scene->lights.size(); i++) {
416                 Light *light = scene->lights[i];
417                 float3 co = light->co;
418                 float3 dir = normalize(light->dir);
419                 int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader);
420
421                 if(!light->cast_shadow)
422                         shader_id &= ~SHADER_CAST_SHADOW;
423
424                 if(light->type == LIGHT_POINT) {
425                         shader_id &= ~SHADER_AREA_LIGHT;
426
427                         light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
428                         light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, 0.0f, 0.0f);
429                         light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
430                         light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
431                 }
432                 else if(light->type == LIGHT_DISTANT) {
433                         shader_id &= ~SHADER_AREA_LIGHT;
434
435                         light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z);
436                         light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, 0.0f, 0.0f);
437                         light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
438                         light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
439                 }
440                 else if(light->type == LIGHT_BACKGROUND) {
441                         shader_id &= ~SHADER_AREA_LIGHT;
442
443                         light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), 0.0f, 0.0f, 0.0f);
444                         light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), 0.0f, 0.0f, 0.0f);
445                         light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
446                         light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
447                 }
448                 else if(light->type == LIGHT_AREA) {
449                         float3 axisu = light->axisu*(light->sizeu*light->size);
450                         float3 axisv = light->axisv*(light->sizev*light->size);
451
452                         light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
453                         light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
454                         light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, axisv.x, axisv.y, axisv.z);
455                         light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, dir.x, dir.y, dir.z);
456                 }
457                 else if(light->type == LIGHT_SPOT) {
458                         shader_id &= ~SHADER_AREA_LIGHT;
459
460                         float spot_angle = cosf(light->spot_angle*0.5f);
461                         float spot_smooth = (1.0f - spot_angle)*light->spot_smooth;
462
463                         light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
464                         light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, dir.x, dir.y);
465                         light_data[i*LIGHT_SIZE + 2] = make_float4(dir.z, spot_angle, spot_smooth, 0.0f);
466                         light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
467                 }
468         }
469         
470         device->tex_alloc("__light_data", dscene->light_data);
471 }
472
473 void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
474 {
475         if(!need_update)
476                 return;
477
478         device_free(device, dscene);
479
480         device_update_points(device, dscene, scene);
481         if(progress.get_cancel()) return;
482
483         device_update_distribution(device, dscene, scene, progress);
484         if(progress.get_cancel()) return;
485
486         device_update_background(device, dscene, scene, progress);
487         if(progress.get_cancel()) return;
488
489         need_update = false;
490 }
491
492 void LightManager::device_free(Device *device, DeviceScene *dscene)
493 {
494         device->tex_free(dscene->light_distribution);
495         device->tex_free(dscene->light_data);
496         device->tex_free(dscene->light_background_marginal_cdf);
497         device->tex_free(dscene->light_background_conditional_cdf);
498
499         dscene->light_distribution.clear();
500         dscene->light_data.clear();
501         dscene->light_background_marginal_cdf.clear();
502         dscene->light_background_conditional_cdf.clear();
503 }
504
505 void LightManager::tag_update(Scene *scene)
506 {
507         need_update = true;
508 }
509
510 CCL_NAMESPACE_END
511