Cycles: Clamp Direct now affects the Background too.
[blender.git] / intern / cycles / kernel / kernel_accumulate.h
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16
17 CCL_NAMESPACE_BEGIN
18
19 /* BSDF Eval
20  *
21  * BSDF evaluation result, split per BSDF type. This is used to accumulate
22  * render passes separately. */
23
24 ccl_device_inline void bsdf_eval_init(BsdfEval *eval, ClosureType type, float3 value, int use_light_pass)
25 {
26 #ifdef __PASSES__
27         eval->use_light_pass = use_light_pass;
28
29         if(eval->use_light_pass) {
30                 eval->diffuse = make_float3(0.0f, 0.0f, 0.0f);
31                 eval->glossy = make_float3(0.0f, 0.0f, 0.0f);
32                 eval->transmission = make_float3(0.0f, 0.0f, 0.0f);
33                 eval->transparent = make_float3(0.0f, 0.0f, 0.0f);
34                 eval->subsurface = make_float3(0.0f, 0.0f, 0.0f);
35
36                 if(type == CLOSURE_BSDF_TRANSPARENT_ID)
37                         eval->transparent = value;
38                 else if(CLOSURE_IS_BSDF_DIFFUSE(type) || CLOSURE_IS_PHASE(type))
39                         eval->diffuse = value;
40                 else if(CLOSURE_IS_BSDF_GLOSSY(type))
41                         eval->glossy = value;
42                 else if(CLOSURE_IS_BSDF_TRANSMISSION(type))
43                         eval->transmission = value;
44                 else if(CLOSURE_IS_BSDF_BSSRDF(type))
45                         eval->subsurface = value;
46         }
47         else
48                 eval->diffuse = value;
49 #else
50         *eval = value;
51 #endif
52 }
53
54 ccl_device_inline void bsdf_eval_accum(BsdfEval *eval, ClosureType type, float3 value)
55 {
56 #ifdef __PASSES__
57         if(eval->use_light_pass) {
58                 if(CLOSURE_IS_BSDF_DIFFUSE(type) || CLOSURE_IS_PHASE(type))
59                         eval->diffuse += value;
60                 else if(CLOSURE_IS_BSDF_GLOSSY(type))
61                         eval->glossy += value;
62                 else if(CLOSURE_IS_BSDF_TRANSMISSION(type))
63                         eval->transmission += value;
64                 else if(CLOSURE_IS_BSDF_BSSRDF(type))
65                         eval->subsurface += value;
66
67                 /* skipping transparent, this function is used by for eval(), will be zero then */
68         }
69         else
70                 eval->diffuse += value;
71 #else
72         *eval += value;
73 #endif
74 }
75
76 ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
77 {
78 #ifdef __PASSES__
79         if(eval->use_light_pass) {
80                 return is_zero(eval->diffuse)
81                         && is_zero(eval->glossy)
82                         && is_zero(eval->transmission)
83                         && is_zero(eval->transparent)
84                         && is_zero(eval->subsurface);
85         }
86         else
87                 return is_zero(eval->diffuse);
88 #else
89         return is_zero(*eval);
90 #endif
91 }
92
93 ccl_device_inline void bsdf_eval_mul(BsdfEval *eval, float3 value)
94 {
95 #ifdef __PASSES__
96         if(eval->use_light_pass) {
97                 eval->diffuse *= value;
98                 eval->glossy *= value;
99                 eval->transmission *= value;
100                 eval->subsurface *= value;
101
102                 /* skipping transparent, this function is used by for eval(), will be zero then */
103         }
104         else
105                 eval->diffuse *= value;
106 #else
107         *eval *= value;
108 #endif
109 }
110
111 /* Path Radiance
112  *
113  * We accumulate different render passes separately. After summing at the end
114  * to get the combined result, it should be identical. We definte directly
115  * visible as the first non-transparent hit, while indirectly visible are the
116  * bounces after that. */
117
118 ccl_device_inline void path_radiance_init(PathRadiance *L, int use_light_pass)
119 {
120         /* clear all */
121 #ifdef __PASSES__
122         L->use_light_pass = use_light_pass;
123
124         if(use_light_pass) {
125                 L->indirect = make_float3(0.0f, 0.0f, 0.0f);
126                 L->direct_throughput = make_float3(0.0f, 0.0f, 0.0f);
127                 L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
128
129                 L->color_diffuse = make_float3(0.0f, 0.0f, 0.0f);
130                 L->color_glossy = make_float3(0.0f, 0.0f, 0.0f);
131                 L->color_transmission = make_float3(0.0f, 0.0f, 0.0f);
132                 L->color_subsurface = make_float3(0.0f, 0.0f, 0.0f);
133
134                 L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
135                 L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
136                 L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
137                 L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
138
139                 L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
140                 L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
141                 L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
142                 L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
143
144                 L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f);
145                 L->path_glossy = make_float3(0.0f, 0.0f, 0.0f);
146                 L->path_transmission = make_float3(0.0f, 0.0f, 0.0f);
147                 L->path_subsurface = make_float3(0.0f, 0.0f, 0.0f);
148
149                 L->emission = make_float3(0.0f, 0.0f, 0.0f);
150                 L->background = make_float3(0.0f, 0.0f, 0.0f);
151                 L->ao = make_float3(0.0f, 0.0f, 0.0f);
152                 L->shadow = make_float4(0.0f, 0.0f, 0.0f, 0.0f);
153                 L->mist = 0.0f;
154         }
155         else
156                 L->emission = make_float3(0.0f, 0.0f, 0.0f);
157 #else
158         *L = make_float3(0.0f, 0.0f, 0.0f);
159 #endif
160 }
161
162 ccl_device_inline void path_radiance_bsdf_bounce(PathRadiance *L, float3 *throughput,
163         BsdfEval *bsdf_eval, float bsdf_pdf, int bounce, int bsdf_label)
164 {
165         float inverse_pdf = 1.0f/bsdf_pdf;
166
167 #ifdef __PASSES__
168         if(L->use_light_pass) {
169                 if(bounce == 0 && !(bsdf_label & LABEL_TRANSPARENT)) {
170                         /* first on directly visible surface */
171                         float3 value = *throughput*inverse_pdf;
172
173                         L->path_diffuse = bsdf_eval->diffuse*value;
174                         L->path_glossy = bsdf_eval->glossy*value;
175                         L->path_transmission = bsdf_eval->transmission*value;
176                         L->path_subsurface = bsdf_eval->subsurface*value;
177
178                         *throughput = L->path_diffuse + L->path_glossy + L->path_transmission + L->path_subsurface;
179                         
180                         L->direct_throughput = *throughput;
181                 }
182                 else {
183                         /* transparent bounce before first hit, or indirectly visible through BSDF */
184                         float3 sum = (bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission + bsdf_eval->transparent + bsdf_eval->subsurface)*inverse_pdf;
185                         *throughput *= sum;
186                 }
187         }
188         else
189                 *throughput *= bsdf_eval->diffuse*inverse_pdf;
190 #else
191         *throughput *= *bsdf_eval*inverse_pdf;
192 #endif
193 }
194
195 ccl_device_inline void path_radiance_accum_emission(PathRadiance *L, float3 throughput, float3 value, int bounce)
196 {
197 #ifdef __PASSES__
198         if(L->use_light_pass) {
199                 if(bounce == 0)
200                         L->emission += throughput*value;
201                 else if(bounce == 1)
202                         L->direct_emission += throughput*value;
203                 else
204                         L->indirect += throughput*value;
205         }
206         else
207                 L->emission += throughput*value;
208 #else
209         *L += throughput*value;
210 #endif
211 }
212
213 ccl_device_inline void path_radiance_accum_ao(PathRadiance *L, float3 throughput, float3 alpha, float3 bsdf, float3 ao, int bounce)
214 {
215 #ifdef __PASSES__
216         if(L->use_light_pass) {
217                 if(bounce == 0) {
218                         /* directly visible lighting */
219                         L->direct_diffuse += throughput*bsdf*ao;
220                         L->ao += alpha*throughput*ao;
221                 }
222                 else {
223                         /* indirectly visible lighting after BSDF bounce */
224                         L->indirect += throughput*bsdf*ao;
225                 }
226         }
227         else
228                 L->emission += throughput*bsdf*ao;
229 #else
230         *L += throughput*bsdf*ao;
231 #endif
232 }
233
234 ccl_device_inline void path_radiance_accum_light(PathRadiance *L, float3 throughput, BsdfEval *bsdf_eval, float3 shadow, float shadow_fac, int bounce, bool is_lamp)
235 {
236 #ifdef __PASSES__
237         if(L->use_light_pass) {
238                 if(bounce == 0) {
239                         /* directly visible lighting */
240                         L->direct_diffuse += throughput*bsdf_eval->diffuse*shadow;
241                         L->direct_glossy += throughput*bsdf_eval->glossy*shadow;
242                         L->direct_transmission += throughput*bsdf_eval->transmission*shadow;
243                         L->direct_subsurface += throughput*bsdf_eval->subsurface*shadow;
244
245                         if(is_lamp) {
246                                 L->shadow.x += shadow.x*shadow_fac;
247                                 L->shadow.y += shadow.y*shadow_fac;
248                                 L->shadow.z += shadow.z*shadow_fac;
249                         }
250                 }
251                 else {
252                         /* indirectly visible lighting after BSDF bounce */
253                         float3 sum = bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission + bsdf_eval->subsurface;
254                         L->indirect += throughput*sum*shadow;
255                 }
256         }
257         else
258                 L->emission += throughput*bsdf_eval->diffuse*shadow;
259 #else
260         *L += throughput*(*bsdf_eval)*shadow;
261 #endif
262 }
263
264 ccl_device_inline void path_radiance_accum_background(PathRadiance *L, float3 throughput, float3 value, int bounce)
265 {
266 #ifdef __PASSES__
267         if(L->use_light_pass) {
268                 if(bounce == 0)
269                         L->background += throughput*value;
270                 else if(bounce == 1)
271                         L->direct_emission += throughput*value;
272                 else
273                         L->indirect += throughput*value;
274         }
275         else
276                 L->emission += throughput*value;
277 #else
278         *L += throughput*value;
279 #endif
280 }
281
282 ccl_device_inline void path_radiance_sum_indirect(PathRadiance *L)
283 {
284 #ifdef __PASSES__
285         /* this division is a bit ugly, but means we only have to keep track of
286          * only a single throughput further along the path, here we recover just
287          * the indirect path that is not influenced by any particular BSDF type */
288         if(L->use_light_pass) {
289                 L->direct_emission = safe_divide_color(L->direct_emission, L->direct_throughput);
290                 L->direct_diffuse += L->path_diffuse*L->direct_emission;
291                 L->direct_glossy += L->path_glossy*L->direct_emission;
292                 L->direct_transmission += L->path_transmission*L->direct_emission;
293                 L->direct_subsurface += L->path_subsurface*L->direct_emission;
294
295                 L->indirect = safe_divide_color(L->indirect, L->direct_throughput);
296                 L->indirect_diffuse += L->path_diffuse*L->indirect;
297                 L->indirect_glossy += L->path_glossy*L->indirect;
298                 L->indirect_transmission += L->path_transmission*L->indirect;
299                 L->indirect_subsurface += L->path_subsurface*L->indirect;
300         }
301 #endif
302 }
303
304 ccl_device_inline void path_radiance_reset_indirect(PathRadiance *L)
305 {
306 #ifdef __PASSES__
307         if(L->use_light_pass) {
308                 L->path_diffuse = make_float3(0.0f, 0.0f, 0.0f);
309                 L->path_glossy = make_float3(0.0f, 0.0f, 0.0f);
310                 L->path_transmission = make_float3(0.0f, 0.0f, 0.0f);
311                 L->path_subsurface = make_float3(0.0f, 0.0f, 0.0f);
312
313                 L->direct_emission = make_float3(0.0f, 0.0f, 0.0f);
314                 L->indirect = make_float3(0.0f, 0.0f, 0.0f);
315         }
316 #endif
317 }
318
319 ccl_device_inline float3 path_radiance_clamp_and_sum(KernelGlobals *kg, PathRadiance *L)
320 {
321 #ifdef __PASSES__
322         if(L->use_light_pass) {
323                 path_radiance_sum_indirect(L);
324
325                 float3 L_direct = L->direct_diffuse + L->direct_glossy + L->direct_transmission + L->direct_subsurface + L->emission;
326                 float3 L_indirect = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission + L->indirect_subsurface;
327                 
328                 if(!kernel_data.background.transparent)
329                         L_direct += L->background;
330
331 #ifdef __CLAMP_SAMPLE__ 
332                 float clamp_direct = kernel_data.integrator.sample_clamp_direct;
333                 float clamp_indirect = kernel_data.integrator.sample_clamp_indirect;
334
335                 if(clamp_direct != FLT_MAX || clamp_indirect != FLT_MAX) {
336                         float scale;
337
338                         /* Direct */
339                         float sum_direct = fabsf(L_direct.x) + fabsf(L_direct.y) + fabsf(L_direct.z);
340                         if(sum_direct > clamp_direct) {
341                                 scale = clamp_direct/sum_direct;
342                                 L_direct *= scale;
343
344                                 L->direct_diffuse *= scale;
345                                 L->direct_glossy *= scale;
346                                 L->direct_transmission *= scale;
347                                 L->direct_subsurface *= scale;
348                                 L->emission *= scale;
349                                 L->background *= scale;
350                         }
351
352                         /* Indirect */
353                         float sum_indirect = fabsf(L_indirect.x) + fabsf(L_indirect.y) + fabsf(L_indirect.z);
354                         if(sum_indirect > clamp_indirect) {
355                                 scale = clamp_indirect/sum_indirect;
356                                 L_indirect *= scale;
357
358                                 L->indirect_diffuse *= scale;
359                                 L->indirect_glossy *= scale;
360                                 L->indirect_transmission *= scale;
361                                 L->indirect_subsurface *= scale;
362                         }
363                 }
364 #endif
365                 /* Combine */
366                 float3 L_sum = L_direct + L_indirect;
367
368                 return L_sum;
369         }
370         else
371                 return L->emission;
372 #else
373         return *L;
374 #endif
375 }
376
377 ccl_device_inline void path_radiance_reject(PathRadiance *L, float3 *L_sum)
378 {
379         float sum = fabsf((*L_sum).x) + fabsf((*L_sum).y) + fabsf((*L_sum).z);
380
381         if(!isfinite(sum)) {
382                 /* invalid value, reject */
383                 *L_sum = make_float3(0.0f, 0.0f, 0.0f);
384
385 #ifdef __PASSES__
386                 if(L->use_light_pass) {
387                         L->direct_diffuse = make_float3(0.0f, 0.0f, 0.0f);
388                         L->direct_glossy = make_float3(0.0f, 0.0f, 0.0f);
389                         L->direct_transmission = make_float3(0.0f, 0.0f, 0.0f);
390                         L->direct_subsurface = make_float3(0.0f, 0.0f, 0.0f);
391
392                         L->indirect_diffuse = make_float3(0.0f, 0.0f, 0.0f);
393                         L->indirect_glossy = make_float3(0.0f, 0.0f, 0.0f);
394                         L->indirect_transmission = make_float3(0.0f, 0.0f, 0.0f);
395                         L->indirect_subsurface = make_float3(0.0f, 0.0f, 0.0f);
396
397                         L->emission = make_float3(0.0f, 0.0f, 0.0f);
398                 }
399 #endif
400         }
401 }
402
403 CCL_NAMESPACE_END
404