daadb6c04c8de21b60724a231c54277a10209c3a
[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 "scene.h"
23
24 #include "util_algorithm.h"
25 #include "util_foreach.h"
26
27 CCL_NAMESPACE_BEGIN
28
29 /* Pass */
30
31 static bool compare_pass_order(const Pass& a, const Pass& b)
32 {
33         if(a.components == b.components)
34                 return (a.type < b.type);
35         return (a.components > b.components);
36 }
37
38 void Pass::add(PassType type, vector<Pass>& passes)
39 {
40         Pass pass;
41
42         pass.type = type;
43         pass.filter = true;
44         pass.exposure = false;
45
46         switch(type) {
47                 case PASS_NONE:
48                         pass.components = 0;
49                         break;
50                 case PASS_COMBINED:
51                         pass.components = 4;
52                         pass.exposure = true;
53                         break;
54                 case PASS_DEPTH:
55                         pass.components = 1;
56                         pass.filter = false;
57                         break;
58                 case PASS_NORMAL:
59                         pass.components = 4;
60                         break;
61                 case PASS_UV:
62                         pass.components = 4;
63                         break;
64                 case PASS_OBJECT_ID:
65                         pass.components = 1;
66                         pass.filter = false;
67                         break;
68                 case PASS_MATERIAL_ID:
69                         pass.components = 1;
70                         pass.filter = false;
71                         break;
72                 case PASS_DIFFUSE_COLOR:
73                         pass.components = 4;
74                         break;
75                 case PASS_GLOSSY_COLOR:
76                         pass.components = 4;
77                         break;
78                 case PASS_TRANSMISSION_COLOR:
79                         pass.components = 4;
80                         break;
81                 case PASS_DIFFUSE_INDIRECT:
82                         pass.components = 4;
83                         pass.exposure = true;
84                         break;
85                 case PASS_GLOSSY_INDIRECT:
86                         pass.components = 4;
87                         pass.exposure = true;
88                         break;
89                 case PASS_TRANSMISSION_INDIRECT:
90                         pass.components = 4;
91                         pass.exposure = true;
92                         break;
93                 case PASS_DIFFUSE_DIRECT:
94                         pass.components = 4;
95                         pass.exposure = true;
96                         break;
97                 case PASS_GLOSSY_DIRECT:
98                         pass.components = 4;
99                         pass.exposure = true;
100                         break;
101                 case PASS_TRANSMISSION_DIRECT:
102                         pass.components = 4;
103                         pass.exposure = true;
104                         break;
105
106                 case PASS_EMISSION:
107                         pass.components = 4;
108                         pass.exposure = true;
109                         break;
110                 case PASS_BACKGROUND:
111                         pass.components = 4;
112                         pass.exposure = true;
113                         break;
114                 case PASS_AO:
115                         pass.components = 4;
116                         pass.exposure = true;
117                         break;
118         }
119
120         passes.push_back(pass);
121
122         /* order from by components, to ensure alignment so passes with size 4
123            come first and then passes with size 1 */
124         sort(passes.begin(), passes.end(), compare_pass_order);
125 }
126
127 bool Pass::equals(const vector<Pass>& A, const vector<Pass>& B)
128 {
129         if(A.size() != B.size())
130                 return false;
131         
132         for(int i = 0; i < A.size(); i++)
133                 if(A[i].type != B[i].type)
134                         return false;
135         
136         return true;
137 }
138
139 /* Film */
140
141 Film::Film()
142 {
143         exposure = 0.8f;
144         Pass::add(PASS_COMBINED, passes);
145         need_update = true;
146 }
147
148 Film::~Film()
149 {
150 }
151
152 void Film::device_update(Device *device, DeviceScene *dscene)
153 {
154         if(!need_update)
155                 return;
156
157         KernelFilm *kfilm = &dscene->data.film;
158
159         /* update __data */
160         kfilm->exposure = exposure;
161         kfilm->pass_flag = 0;
162         kfilm->pass_stride = 0;
163         kfilm->use_light_pass = 0;
164
165         foreach(Pass& pass, passes) {
166                 kfilm->pass_flag |= pass.type;
167
168                 switch(pass.type) {
169                         case PASS_COMBINED:
170                                 kfilm->pass_combined = kfilm->pass_stride;
171                                 break;
172                         case PASS_DEPTH:
173                                 kfilm->pass_depth = kfilm->pass_stride;
174                                 break;
175                         case PASS_NORMAL:
176                                 kfilm->pass_normal = kfilm->pass_stride;
177                                 break;
178                         case PASS_UV:
179                                 kfilm->pass_uv = kfilm->pass_stride;
180                                 break;
181                         case PASS_OBJECT_ID:
182                                 kfilm->pass_object_id = kfilm->pass_stride;
183                                 break;
184                         case PASS_MATERIAL_ID:
185                                 kfilm->pass_material_id = kfilm->pass_stride;
186                                 break;
187                         case PASS_DIFFUSE_COLOR:
188                                 kfilm->pass_diffuse_color = kfilm->pass_stride;
189                                 kfilm->use_light_pass = 1;
190                                 break;
191                         case PASS_GLOSSY_COLOR:
192                                 kfilm->pass_glossy_color = kfilm->pass_stride;
193                                 kfilm->use_light_pass = 1;
194                                 break;
195                         case PASS_TRANSMISSION_COLOR:
196                                 kfilm->pass_transmission_color = kfilm->pass_stride;
197                                 kfilm->use_light_pass = 1;
198                                 break;
199                         case PASS_DIFFUSE_INDIRECT:
200                                 kfilm->pass_diffuse_indirect = kfilm->pass_stride;
201                                 kfilm->use_light_pass = 1;
202                                 break;
203                         case PASS_GLOSSY_INDIRECT:
204                                 kfilm->pass_glossy_indirect = kfilm->pass_stride;
205                                 kfilm->use_light_pass = 1;
206                                 break;
207                         case PASS_TRANSMISSION_INDIRECT:
208                                 kfilm->pass_transmission_indirect = kfilm->pass_stride;
209                                 kfilm->use_light_pass = 1;
210                                 break;
211                         case PASS_DIFFUSE_DIRECT:
212                                 kfilm->pass_diffuse_direct = kfilm->pass_stride;
213                                 kfilm->use_light_pass = 1;
214                                 break;
215                         case PASS_GLOSSY_DIRECT:
216                                 kfilm->pass_glossy_direct = kfilm->pass_stride;
217                                 kfilm->use_light_pass = 1;
218                                 break;
219                         case PASS_TRANSMISSION_DIRECT:
220                                 kfilm->pass_transmission_direct = kfilm->pass_stride;
221                                 kfilm->use_light_pass = 1;
222                                 break;
223
224                         case PASS_EMISSION:
225                                 kfilm->pass_emission = kfilm->pass_stride;
226                                 kfilm->use_light_pass = 1;
227                                 break;
228                         case PASS_BACKGROUND:
229                                 kfilm->pass_background = kfilm->pass_stride;
230                                 kfilm->use_light_pass = 1;
231                         case PASS_AO:
232                                 kfilm->pass_ao = kfilm->pass_stride;
233                                 kfilm->use_light_pass = 1;
234                         case PASS_NONE:
235                                 break;
236                 }
237
238                 kfilm->pass_stride += pass.components;
239         }
240
241         kfilm->pass_stride = align_up(kfilm->pass_stride, 4);
242
243         need_update = false;
244 }
245
246 void Film::device_free(Device *device, DeviceScene *dscene)
247 {
248 }
249
250 bool Film::modified(const Film& film)
251 {
252         return !(exposure == film.exposure
253                 && Pass::equals(passes, film.passes));
254 }
255
256 void Film::tag_update(Scene *scene)
257 {
258         need_update = true;
259 }
260
261 CCL_NAMESPACE_END
262