1fe30376adcc095f2a384a70f6799dc3d8b759f4
[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         need_update = true;
263 }
264
265 Film::~Film()
266 {
267 }
268
269 void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene)
270 {
271         if(!need_update)
272                 return;
273         
274         device_free(device, dscene, scene);
275
276         KernelFilm *kfilm = &dscene->data.film;
277
278         /* update __data */
279         kfilm->exposure = exposure;
280         kfilm->pass_flag = 0;
281         kfilm->pass_stride = 0;
282         kfilm->use_light_pass = 0;
283
284         foreach(Pass& pass, passes) {
285                 kfilm->pass_flag |= pass.type;
286
287                 switch(pass.type) {
288                         case PASS_COMBINED:
289                                 kfilm->pass_combined = kfilm->pass_stride;
290                                 break;
291                         case PASS_DEPTH:
292                                 kfilm->pass_depth = kfilm->pass_stride;
293                                 break;
294                         case PASS_MIST:
295                                 kfilm->pass_mist = kfilm->pass_stride;
296                                 kfilm->use_light_pass = 1;
297                                 break;
298                         case PASS_NORMAL:
299                                 kfilm->pass_normal = kfilm->pass_stride;
300                                 break;
301                         case PASS_UV:
302                                 kfilm->pass_uv = kfilm->pass_stride;
303                                 break;
304                         case PASS_MOTION:
305                                 kfilm->pass_motion = kfilm->pass_stride;
306                                 break;
307                         case PASS_MOTION_WEIGHT:
308                                 kfilm->pass_motion_weight = kfilm->pass_stride;
309                                 break;
310                         case PASS_OBJECT_ID:
311                                 kfilm->pass_object_id = kfilm->pass_stride;
312                                 break;
313                         case PASS_MATERIAL_ID:
314                                 kfilm->pass_material_id = kfilm->pass_stride;
315                                 break;
316                         case PASS_DIFFUSE_COLOR:
317                                 kfilm->pass_diffuse_color = kfilm->pass_stride;
318                                 kfilm->use_light_pass = 1;
319                                 break;
320                         case PASS_GLOSSY_COLOR:
321                                 kfilm->pass_glossy_color = kfilm->pass_stride;
322                                 kfilm->use_light_pass = 1;
323                                 break;
324                         case PASS_TRANSMISSION_COLOR:
325                                 kfilm->pass_transmission_color = kfilm->pass_stride;
326                                 kfilm->use_light_pass = 1;
327                                 break;
328                         case PASS_DIFFUSE_INDIRECT:
329                                 kfilm->pass_diffuse_indirect = kfilm->pass_stride;
330                                 kfilm->use_light_pass = 1;
331                                 break;
332                         case PASS_GLOSSY_INDIRECT:
333                                 kfilm->pass_glossy_indirect = kfilm->pass_stride;
334                                 kfilm->use_light_pass = 1;
335                                 break;
336                         case PASS_TRANSMISSION_INDIRECT:
337                                 kfilm->pass_transmission_indirect = kfilm->pass_stride;
338                                 kfilm->use_light_pass = 1;
339                                 break;
340                         case PASS_DIFFUSE_DIRECT:
341                                 kfilm->pass_diffuse_direct = kfilm->pass_stride;
342                                 kfilm->use_light_pass = 1;
343                                 break;
344                         case PASS_GLOSSY_DIRECT:
345                                 kfilm->pass_glossy_direct = kfilm->pass_stride;
346                                 kfilm->use_light_pass = 1;
347                                 break;
348                         case PASS_TRANSMISSION_DIRECT:
349                                 kfilm->pass_transmission_direct = kfilm->pass_stride;
350                                 kfilm->use_light_pass = 1;
351                                 break;
352
353                         case PASS_EMISSION:
354                                 kfilm->pass_emission = kfilm->pass_stride;
355                                 kfilm->use_light_pass = 1;
356                                 break;
357                         case PASS_BACKGROUND:
358                                 kfilm->pass_background = kfilm->pass_stride;
359                                 kfilm->use_light_pass = 1;
360                         case PASS_AO:
361                                 kfilm->pass_ao = kfilm->pass_stride;
362                                 kfilm->use_light_pass = 1;
363                         case PASS_SHADOW:
364                                 kfilm->pass_shadow = kfilm->pass_stride;
365                                 kfilm->use_light_pass = 1;
366                         case PASS_NONE:
367                                 break;
368                 }
369
370                 kfilm->pass_stride += pass.components;
371         }
372
373         kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
374
375         /* update filter table */
376         vector<float> table = filter_table(filter_type, filter_width);
377         filter_table_offset = scene->lookup_tables->add_table(dscene, table);
378         kfilm->filter_table_offset = (int)filter_table_offset;
379
380         /* mist pass parameters */
381         kfilm->mist_start = mist_start;
382         kfilm->mist_inv_depth = (mist_depth > 0.0f)? 1.0f/mist_depth: 0.0f;
383         kfilm->mist_falloff = mist_falloff;
384
385         need_update = false;
386 }
387
388 void Film::device_free(Device *device, DeviceScene *dscene, Scene *scene)
389 {
390         if(filter_table_offset != TABLE_OFFSET_INVALID) {
391                 scene->lookup_tables->remove_table(filter_table_offset);
392                 filter_table_offset = TABLE_OFFSET_INVALID;
393         }
394 }
395
396 bool Film::modified(const Film& film)
397 {
398         return !(exposure == film.exposure
399                 && Pass::equals(passes, film.passes)
400                 && filter_type == film.filter_type
401                 && filter_width == film.filter_width);
402 }
403
404 void Film::tag_passes_update(Scene *scene, const vector<Pass>& passes_)
405 {
406         if(Pass::contains(passes, PASS_UV) != Pass::contains(passes_, PASS_UV))
407                 scene->mesh_manager->tag_update(scene);
408         else if(Pass::contains(passes, PASS_MOTION) != Pass::contains(passes_, PASS_MOTION))
409                 scene->mesh_manager->tag_update(scene);
410
411         passes = passes_;
412 }
413
414 void Film::tag_update(Scene *scene)
415 {
416         need_update = true;
417 }
418
419 CCL_NAMESPACE_END
420