Cycles: svn merge -r41225:41232 ^/trunk/blender
[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 /* Light */
32
33 Light::Light()
34 {
35         type = LIGHT_POINT;
36
37         co = make_float3(0.0f, 0.0f, 0.0f);
38
39         dir = make_float3(0.0f, 0.0f, 0.0f);
40         size = 0.0f;
41
42         axisu = make_float3(0.0f, 0.0f, 0.0f);
43         sizeu = 1.0f;
44         axisv = make_float3(0.0f, 0.0f, 0.0f);
45         sizev = 1.0f;
46
47         cast_shadow = true;
48         shader = 0;
49 }
50
51 void Light::tag_update(Scene *scene)
52 {
53         scene->light_manager->need_update = true;
54 }
55
56 /* Light Manager */
57
58 LightManager::LightManager()
59 {
60         need_update = true;
61 }
62
63 LightManager::~LightManager()
64 {
65 }
66
67 void LightManager::device_update_distribution(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
68 {
69         /* option to always sample all point lights */
70         bool multi_light = false;
71
72         /* count */
73         size_t num_lights = scene->lights.size();
74         size_t num_triangles = 0;
75
76         foreach(Object *object, scene->objects) {
77                 Mesh *mesh = object->mesh;
78                 bool have_emission = false;
79
80                 /* skip if we have no emission shaders */
81                 foreach(uint sindex, mesh->used_shaders) {
82                         Shader *shader = scene->shaders[sindex];
83
84                         if(shader->sample_as_light && shader->has_surface_emission) {
85                                 have_emission = true;
86                                 break;
87                         }
88                 }
89
90                 /* count triangles */
91                 if(have_emission) {
92                         for(size_t i = 0; i < mesh->triangles.size(); i++) {
93                                 Shader *shader = scene->shaders[mesh->shader[i]];
94
95                                 if(shader->sample_as_light && shader->has_surface_emission)
96                                         num_triangles++;
97                         }
98                 }
99         }
100
101         size_t num_distribution = num_triangles;
102
103         if(!multi_light)
104                 num_distribution += num_lights;
105
106         /* emission area */
107         float4 *distribution = dscene->light_distribution.resize(num_distribution + 1);
108         float totarea = 0.0f;
109
110         /* triangles */
111         size_t offset = 0;
112         size_t j = 0;
113
114         foreach(Object *object, scene->objects) {
115                 Mesh *mesh = object->mesh;
116                 bool have_emission = false;
117
118                 /* skip if we have no emission shaders */
119                 foreach(uint sindex, mesh->used_shaders) {
120                         Shader *shader = scene->shaders[sindex];
121
122                         if(shader->sample_as_light && shader->has_surface_emission) {
123                                 have_emission = true;
124                                 break;
125                         }
126                 }
127
128                 /* sum area */
129                 if(have_emission) {
130                         Transform tfm = object->tfm;
131                         int object_id = (mesh->transform_applied)? -j-1: j;
132
133                         for(size_t i = 0; i < mesh->triangles.size(); i++) {
134                                 Shader *shader = scene->shaders[mesh->shader[i]];
135
136                                 if(shader->sample_as_light && shader->has_surface_emission) {
137                                         distribution[offset].x = totarea;
138                                         distribution[offset].y = __int_as_float(i + mesh->tri_offset);
139                                         distribution[offset].z = 1.0f;
140                                         distribution[offset].w = __int_as_float(object_id);
141                                         offset++;
142
143                                         Mesh::Triangle t = mesh->triangles[i];
144                                         float3 p1 = transform(&tfm, mesh->verts[t.v[0]]);
145                                         float3 p2 = transform(&tfm, mesh->verts[t.v[1]]);
146                                         float3 p3 = transform(&tfm, mesh->verts[t.v[2]]);
147
148                                         totarea += triangle_area(p1, p2, p3);
149                                 }
150                         }
151                 }
152
153                 if(progress.get_cancel()) return;
154
155                 j++;
156         }
157
158         float trianglearea = totarea;
159
160         /* point lights */
161         if(!multi_light) {
162                 float lightarea = (totarea > 0.0f)? totarea/scene->lights.size(): 1.0f;
163
164                 for(size_t i = 0; i < scene->lights.size(); i++, offset++) {
165                         distribution[offset].x = totarea;
166                         distribution[offset].y = __int_as_float(-i-1);
167                         distribution[offset].z = 1.0f;
168                         distribution[offset].w = scene->lights[i]->size;
169                         totarea += lightarea;
170                 }
171         }
172
173         /* normalize cumulative distribution functions */
174         distribution[num_distribution].x = totarea;
175         distribution[num_distribution].y = 0.0f;
176         distribution[num_distribution].z = 0.0f;
177         distribution[num_distribution].w = 0.0f;
178
179         if(totarea > 0.0f) {
180                 for(size_t i = 0; i < num_distribution; i++)
181                         distribution[i].x /= totarea;
182                 distribution[num_distribution].x = 1.0f;
183         }
184
185         if(progress.get_cancel()) return;
186
187         /* update device */
188         KernelIntegrator *kintegrator = &dscene->data.integrator;
189         kintegrator->use_direct_light = (totarea > 0.0f) || (multi_light && num_lights);
190
191         if(kintegrator->use_direct_light) {
192                 /* number of emissives */
193                 kintegrator->num_distribution = (totarea > 0.0f)? num_distribution: 0;
194
195                 /* precompute pdfs */
196                 kintegrator->pdf_triangles = 0.0f;
197                 kintegrator->pdf_lights = 0.0f;
198
199                 if(multi_light) {
200                         /* sample one of all triangles and all lights */
201                         kintegrator->num_all_lights = num_lights;
202
203                         if(trianglearea > 0.0f)
204                                 kintegrator->pdf_triangles = 1.0f/trianglearea;
205                         if(num_lights)
206                                 kintegrator->pdf_lights = 1.0f;
207                 }
208                 else {
209                         /* sample one, with 0.5 probability of light or triangle */
210                         kintegrator->num_all_lights = 0;
211
212                         if(trianglearea > 0.0f) {
213                                 kintegrator->pdf_triangles = 1.0f/trianglearea;
214                                 if(num_lights)
215                                         kintegrator->pdf_triangles *= 0.5f;
216                         }
217
218                         if(num_lights) {
219                                 kintegrator->pdf_lights = 1.0f/num_lights;
220                                 if(trianglearea > 0.0f)
221                                         kintegrator->pdf_lights *= 0.5f;
222                         }
223                 }
224
225                 /* CDF */
226                 device->tex_alloc("__light_distribution", dscene->light_distribution);
227         }
228         else
229                 dscene->light_distribution.clear();
230 }
231
232 void LightManager::device_update_points(Device *device, DeviceScene *dscene, Scene *scene)
233 {
234         if(scene->lights.size() == 0)
235                 return;
236
237         float4 *light_data = dscene->light_data.resize(scene->lights.size()*LIGHT_SIZE);
238
239         for(size_t i = 0; i < scene->lights.size(); i++) {
240                 Light *light = scene->lights[i];
241                 float3 co = light->co;
242                 float3 dir = normalize(light->dir);
243                 int shader_id = scene->shader_manager->get_shader_id(scene->lights[i]->shader);
244
245                 if(!light->cast_shadow)
246                         shader_id &= ~SHADER_CAST_SHADOW;
247
248                 if(light->type == LIGHT_POINT) {
249                         shader_id &= ~SHADER_AREA_LIGHT;
250
251                         light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
252                         light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, 0.0f, 0.0f);
253                         light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
254                         light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
255                 }
256                 else if(light->type == LIGHT_DISTANT) {
257                         shader_id &= ~SHADER_AREA_LIGHT;
258
259                         light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), dir.x, dir.y, dir.z);
260                         light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), light->size, 0.0f, 0.0f);
261                         light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
262                         light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
263                 }
264                 else if(light->type == LIGHT_AREA) {
265                         float3 axisu = light->axisu*(light->sizeu*light->size);
266                         float3 axisv = light->axisv*(light->sizev*light->size);
267
268                         light_data[i*LIGHT_SIZE + 0] = make_float4(__int_as_float(light->type), co.x, co.y, co.z);
269                         light_data[i*LIGHT_SIZE + 1] = make_float4(__int_as_float(shader_id), axisu.x, axisu.y, axisu.z);
270                         light_data[i*LIGHT_SIZE + 2] = make_float4(0.0f, axisv.x, axisv.y, axisv.z);
271                         light_data[i*LIGHT_SIZE + 3] = make_float4(0.0f, dir.x, dir.y, dir.z);
272                 }
273         }
274         
275         device->tex_alloc("__light_data", dscene->light_data);
276 }
277
278 void LightManager::device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress)
279 {
280         if(!need_update)
281                 return;
282
283         device_free(device, dscene);
284
285         device_update_points(device, dscene, scene);
286         if(progress.get_cancel()) return;
287
288         device_update_distribution(device, dscene, scene, progress);
289         if(progress.get_cancel()) return;
290
291         need_update = false;
292 }
293
294 void LightManager::device_free(Device *device, DeviceScene *dscene)
295 {
296         device->tex_free(dscene->light_distribution);
297         device->tex_free(dscene->light_data);
298
299         dscene->light_distribution.clear();
300         dscene->light_data.clear();
301 }
302
303 void LightManager::tag_update(Scene *scene)
304 {
305         need_update = true;
306 }
307
308 CCL_NAMESPACE_END
309