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