2a16b7b6c217b9948f16f99a6cb8adef0f01871d
[blender.git] / intern / cycles / render / film.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 "camera.h"
20 #include "device.h"
21 #include "film.h"
22 #include "integrator.h"
23 #include "mesh.h"
24 #include "scene.h"
25 #include "tables.h"
26
27 #include "util_algorithm.h"
28 #include "util_debug.h"
29 #include "util_foreach.h"
30 #include "util_math.h"
31
32 CCL_NAMESPACE_BEGIN
33
34 /* Pass */
35
36 static bool compare_pass_order(const Pass& a, const Pass& b)
37 {
38         if(a.components == b.components)
39                 return (a.type < b.type);
40         return (a.components > b.components);
41 }
42
43 void Pass::add(PassType type, vector<Pass>& passes)
44 {
45         foreach(Pass& existing_pass, passes)
46                 if(existing_pass.type == type)
47                         return;
48
49         Pass pass;
50
51         pass.type = type;
52         pass.filter = true;
53         pass.exposure = false;
54         pass.divide_type = PASS_NONE;
55
56         switch(type) {
57                 case PASS_NONE:
58                         pass.components = 0;
59                         break;
60                 case PASS_COMBINED:
61                         pass.components = 4;
62                         pass.exposure = true;
63                         break;
64                 case PASS_DEPTH:
65                         pass.components = 1;
66                         pass.filter = false;
67                         break;
68                 case PASS_MIST:
69                         pass.components = 1;
70                         break;
71                 case PASS_NORMAL:
72                         pass.components = 4;
73                         break;
74                 case PASS_UV:
75                         pass.components = 4;
76                         break;
77                 case PASS_MOTION:
78                         pass.components = 4;
79                         pass.divide_type = PASS_MOTION_WEIGHT;
80                         break;
81                 case PASS_MOTION_WEIGHT:
82                         pass.components = 1;
83                         break;
84                 case PASS_OBJECT_ID:
85                         pass.components = 1;
86                         pass.filter = false;
87                         break;
88                 case PASS_MATERIAL_ID:
89                         pass.components = 1;
90                         pass.filter = false;
91                         break;
92                 case PASS_DIFFUSE_COLOR:
93                         pass.components = 4;
94                         break;
95                 case PASS_GLOSSY_COLOR:
96                         pass.components = 4;
97                         break;
98                 case PASS_TRANSMISSION_COLOR:
99                         pass.components = 4;
100                         break;
101                 case PASS_DIFFUSE_INDIRECT:
102                         pass.components = 4;
103                         pass.exposure = true;
104                         pass.divide_type = PASS_DIFFUSE_COLOR;
105                         break;
106                 case PASS_GLOSSY_INDIRECT:
107                         pass.components = 4;
108                         pass.exposure = true;
109                         pass.divide_type = PASS_GLOSSY_COLOR;
110                         break;
111                 case PASS_TRANSMISSION_INDIRECT:
112                         pass.components = 4;
113                         pass.exposure = true;
114                         pass.divide_type = PASS_TRANSMISSION_COLOR;
115                         break;
116                 case PASS_DIFFUSE_DIRECT:
117                         pass.components = 4;
118                         pass.exposure = true;
119                         pass.divide_type = PASS_DIFFUSE_COLOR;
120                         break;
121                 case PASS_GLOSSY_DIRECT:
122                         pass.components = 4;
123                         pass.exposure = true;
124                         pass.divide_type = PASS_GLOSSY_COLOR;
125                         break;
126                 case PASS_TRANSMISSION_DIRECT:
127                         pass.components = 4;
128                         pass.exposure = true;
129                         pass.divide_type = PASS_TRANSMISSION_COLOR;
130                         break;
131
132                 case PASS_EMISSION:
133                         pass.components = 4;
134                         pass.exposure = true;
135                         break;
136                 case PASS_BACKGROUND:
137                         pass.components = 4;
138                         pass.exposure = true;
139                         break;
140                 case PASS_AO:
141                         pass.components = 4;
142                         break;
143                 case PASS_SHADOW:
144                         pass.components = 4;
145                         pass.exposure = false;
146                         break;
147         }
148
149         passes.push_back(pass);
150
151         /* order from by components, to ensure alignment so passes with size 4
152          * come first and then passes with size 1 */
153         sort(passes.begin(), passes.end(), compare_pass_order);
154
155         if(pass.divide_type != PASS_NONE)
156                 Pass::add(pass.divide_type, passes);
157 }
158
159 bool Pass::equals(const vector<Pass>& A, const vector<Pass>& B)
160 {
161         if(A.size() != B.size())
162                 return false;
163         
164         for(int i = 0; i < A.size(); i++)
165                 if(A[i].type != B[i].type)
166                         return false;
167         
168         return true;
169 }
170
171 bool Pass::contains(const vector<Pass>& passes, PassType type)
172 {
173         foreach(const Pass& pass, passes)
174                 if(pass.type == type)
175                         return true;
176         
177         return false;
178 }
179
180 /* Pixel Filter */
181
182 static float filter_func_box(float v, float width)
183 {
184         return 1.0f;
185 }
186
187 static float filter_func_gaussian(float v, float width)
188 {
189         v *= 2.0f/width;
190         return expf(-2.0f*v*v);
191 }
192
193 static vector<float> filter_table(FilterType type, float width)
194 {
195         const int filter_table_size = FILTER_TABLE_SIZE-1;
196         vector<float> filter_table_cdf(filter_table_size+1);
197         vector<float> filter_table(filter_table_size+1);
198         float (*filter_func)(float, float) = NULL;
199         int i, half_size = filter_table_size/2;
200
201         switch(type) {
202                 case FILTER_BOX:
203                         filter_func = filter_func_box;
204                         break;
205                 case FILTER_GAUSSIAN:
206                         filter_func = filter_func_gaussian;
207                         break;
208                 default:
209                         assert(0);
210         }
211
212         /* compute cumulative distribution function */
213         filter_table_cdf[0] = 0.0f;
214         
215         for(i = 0; i < filter_table_size; i++) {
216                 float x = i*width*0.5f/(filter_table_size-1);
217                 float y = filter_func(x, width);
218                 filter_table_cdf[i+1] += filter_table_cdf[i] + fabsf(y);
219         }
220
221         for(i = 0; i <= filter_table_size; i++)
222                 filter_table_cdf[i] /= filter_table_cdf[filter_table_size];
223         
224         /* create importance sampling table */
225         for(i = 0; i <= half_size; i++) {
226                 float x = i/(float)half_size;
227                 int index = upper_bound(filter_table_cdf.begin(), filter_table_cdf.end(), x) - filter_table_cdf.begin();
228                 float t;
229
230                 if(index < filter_table_size+1) {
231                         t = (x - filter_table_cdf[index])/(filter_table_cdf[index+1] - filter_table_cdf[index]);
232                 }
233                 else {
234                         t = 0.0f;
235                         index = filter_table_size;
236                 }
237
238                 float y = ((index + t)/(filter_table_size))*width;
239
240                 filter_table[half_size+i] = 0.5f*(1.0f + y);
241                 filter_table[half_size-i] = 0.5f*(1.0f - y);
242         }
243
244         return filter_table;
245 }
246
247 /* Film */
248
249 Film::Film()
250 {
251         exposure = 0.8f;
252         Pass::add(PASS_COMBINED, passes);
253
254         filter_type = FILTER_BOX;
255         filter_width = 1.0f;
256         filter_table_offset = TABLE_OFFSET_INVALID;
257
258         mist_start = 0.0f;
259         mist_depth = 100.0f;
260         mist_falloff = 1.0f;
261
262         use_light_visibility = false;
263
264         need_update = true;
265 }
266
267 Film::~Film()
268 {
269 }
270
271 void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
272 {
273         if(!need_update)
274                 return;
275         
276         device_free(device, dscene, scene);
277
278         KernelFilm *kfilm = &dscene->data.film;
279
280         /* update __data */
281         kfilm->exposure = exposure;
282         kfilm->pass_flag = 0;
283         kfilm->pass_stride = 0;
284         kfilm->use_light_pass = use_light_visibility;
285
286         foreach(Pass& pass, passes) {
287                 kfilm->pass_flag |= pass.type;
288
289                 switch(pass.type) {
290                         case PASS_COMBINED:
291                                 kfilm->pass_combined = kfilm->pass_stride;
292                                 break;
293                         case PASS_DEPTH:
294                                 kfilm->pass_depth = kfilm->pass_stride;
295                                 break;
296                         case PASS_MIST:
297                                 kfilm->pass_mist = kfilm->pass_stride;
298                                 kfilm->use_light_pass = 1;
299                                 break;
300                         case PASS_NORMAL:
301                                 kfilm->pass_normal = kfilm->pass_stride;
302                                 break;
303                         case PASS_UV:
304                                 kfilm->pass_uv = kfilm->pass_stride;
305                                 break;
306                         case PASS_MOTION:
307                                 kfilm->pass_motion = kfilm->pass_stride;
308                                 break;
309                         case PASS_MOTION_WEIGHT:
310                                 kfilm->pass_motion_weight = kfilm->pass_stride;
311                                 break;
312                         case PASS_OBJECT_ID:
313                                 kfilm->pass_object_id = kfilm->pass_stride;
314                                 break;
315                         case PASS_MATERIAL_ID:
316                                 kfilm->pass_material_id = kfilm->pass_stride;
317                                 break;
318                         case PASS_DIFFUSE_COLOR:
319                                 kfilm->pass_diffuse_color = kfilm->pass_stride;
320                                 kfilm->use_light_pass = 1;
321                                 break;
322                         case PASS_GLOSSY_COLOR:
323                                 kfilm->pass_glossy_color = kfilm->pass_stride;
324                                 kfilm->use_light_pass = 1;
325                                 break;
326                         case PASS_TRANSMISSION_COLOR:
327                                 kfilm->pass_transmission_color = kfilm->pass_stride;
328                                 kfilm->use_light_pass = 1;
329                                 break;
330                         case PASS_DIFFUSE_INDIRECT:
331                                 kfilm->pass_diffuse_indirect = kfilm->pass_stride;
332                                 kfilm->use_light_pass = 1;
333                                 break;
334                         case PASS_GLOSSY_INDIRECT:
335                                 kfilm->pass_glossy_indirect = kfilm->pass_stride;
336                                 kfilm->use_light_pass = 1;
337                                 break;
338                         case PASS_TRANSMISSION_INDIRECT:
339                                 kfilm->pass_transmission_indirect = kfilm->pass_stride;
340                                 kfilm->use_light_pass = 1;
341                                 break;
342                         case PASS_DIFFUSE_DIRECT:
343                                 kfilm->pass_diffuse_direct = kfilm->pass_stride;
344                                 kfilm->use_light_pass = 1;
345                                 break;
346                         case PASS_GLOSSY_DIRECT:
347                                 kfilm->pass_glossy_direct = kfilm->pass_stride;
348                                 kfilm->use_light_pass = 1;
349                                 break;
350                         case PASS_TRANSMISSION_DIRECT:
351                                 kfilm->pass_transmission_direct = kfilm->pass_stride;
352                                 kfilm->use_light_pass = 1;
353                                 break;
354
355                         case PASS_EMISSION:
356                                 kfilm->pass_emission = kfilm->pass_stride;
357                                 kfilm->use_light_pass = 1;
358                                 break;
359                         case PASS_BACKGROUND:
360                                 kfilm->pass_background = kfilm->pass_stride;
361                                 kfilm->use_light_pass = 1;
362                                 break;
363                         case PASS_AO:
364                                 kfilm->pass_ao = kfilm->pass_stride;
365                                 kfilm->use_light_pass = 1;
366                                 break;
367                         case PASS_SHADOW:
368                                 kfilm->pass_shadow = kfilm->pass_stride;
369                                 kfilm->use_light_pass = 1;
370                                 break;
371                         case PASS_NONE:
372                                 break;
373                 }
374
375                 kfilm->pass_stride += pass.components;
376         }
377
378         kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
379
380         /* update filter table */
381         vector<float> table = filter_table(filter_type, filter_width);
382         filter_table_offset = scene->lookup_tables->add_table(dscene, table);
383         kfilm->filter_table_offset = (int)filter_table_offset;
384
385         /* mist pass parameters */
386         kfilm->mist_start = mist_start;
387         kfilm->mist_inv_depth = (mist_depth > 0.0f)? 1.0f/mist_depth: 0.0f;
388         kfilm->mist_falloff = mist_falloff;
389
390         need_update = false;
391 }
392
393 void Film::device_free(Device *device, DeviceScene *dscene, Scene *scene)
394 {
395         if(filter_table_offset != TABLE_OFFSET_INVALID) {
396                 scene->lookup_tables->remove_table(filter_table_offset);
397                 filter_table_offset = TABLE_OFFSET_INVALID;
398         }
399 }
400
401 bool Film::modified(const Film& film)
402 {
403         return !(exposure == film.exposure
404                 && Pass::equals(passes, film.passes)
405                 && filter_type == film.filter_type
406                 && filter_width == film.filter_width);
407 }
408
409 void Film::tag_passes_update(Scene *scene, const vector<Pass>& passes_)
410 {
411         if(Pass::contains(passes, PASS_UV) != Pass::contains(passes_, PASS_UV))
412                 scene->mesh_manager->tag_update(scene);
413         else if(Pass::contains(passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION))
414                 scene->mesh_manager->tag_update(scene);
415
416         passes = passes_;
417 }
418
419 void Film::tag_update(Scene *scene)
420 {
421         need_update = true;
422 }
423
424 CCL_NAMESPACE_END
425