Cycles:
[blender-staging.git] / intern / cycles / kernel / kernel_path.h
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 "kernel_differential.h"
20 #include "kernel_montecarlo.h"
21 #include "kernel_triangle.h"
22 #include "kernel_object.h"
23 #ifdef __QBVH__
24 #include "kernel_qbvh.h"
25 #else
26 #include "kernel_bvh.h"
27 #endif
28 #include "kernel_camera.h"
29 #include "kernel_shader.h"
30 #include "kernel_light.h"
31 #include "kernel_emission.h"
32 #include "kernel_random.h"
33
34 CCL_NAMESPACE_BEGIN
35
36 #ifdef __MODIFY_TP__
37 __device float3 path_terminate_modified_throughput(KernelGlobals *kg, __global float3 *buffer, int x, int y, int pass)
38 {
39         /* modify throughput to influence path termination probability, to avoid
40            darker regions receiving fewer samples than lighter regions. also RGB
41            are weighted differently. proper validation still remains to be done. */
42         const float3 weights = make_float3(1.0f, 1.33f, 0.66f);
43         const float3 one = make_float3(1.0f, 1.0f, 1.0f);
44         const int minpass = 5;
45         const float minL = 0.1f;
46
47         if(pass >= minpass) {
48                 float3 L = buffer[x + y*kernel_data.cam.width];
49                 float3 Lmin = make_float3(minL, minL, minL);
50                 float correct = (float)(pass+1)/(float)pass;
51
52                 L = film_map(L*correct, pass);
53
54                 return weights/clamp(L, Lmin, one);
55         }
56
57         return weights;
58 }
59 #endif
60
61 __device float path_terminate_probability(KernelGlobals *kg, int bounce, const float3 throughput)
62 {
63         if(bounce >= kernel_data.integrator.maxbounce)
64                 return 0.0f;
65         else if(bounce <= kernel_data.integrator.minbounce)
66                 return 1.0f;
67
68         return average(throughput);
69 }
70
71 __device int path_flag_from_label(int path_flag, int label)
72 {
73         /* reflect/transmit */
74         if(label & LABEL_REFLECT) {
75                 path_flag |= PATH_RAY_REFLECT;
76                 path_flag &= ~PATH_RAY_TRANSMIT;
77         }
78         else {
79                 kernel_assert(label & LABEL_TRANSMIT);
80
81                 path_flag |= PATH_RAY_TRANSMIT;
82                 path_flag &= ~PATH_RAY_REFLECT;
83         }
84
85         /* diffuse/glossy/singular */
86         if(label & LABEL_DIFFUSE) {
87                 path_flag |= PATH_RAY_DIFFUSE;
88                 path_flag &= ~(PATH_RAY_GLOSSY|PATH_RAY_SINGULAR);
89         }
90         else if(label & LABEL_GLOSSY) {
91                 path_flag |= PATH_RAY_GLOSSY;
92                 path_flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_SINGULAR);
93         }
94         else {
95                 kernel_assert(label & (LABEL_SINGULAR|LABEL_STRAIGHT));
96
97                 path_flag |= PATH_RAY_SINGULAR;
98                 path_flag &= ~(PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY);
99         }
100         
101         /* ray through transparent is still camera ray */
102         if(!(label & LABEL_STRAIGHT))
103                 path_flag &= ~PATH_RAY_CAMERA;
104         
105         return path_flag;
106 }
107
108 __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int pass, Ray ray, float3 throughput)
109 {
110         /* initialize */
111         float3 L = make_float3(0.0f, 0.0f, 0.0f);
112         float Ltransparent = 0.0f;
113
114 #ifdef __EMISSION__
115         float ray_pdf = 0.0f;
116 #endif
117         int path_flag = PATH_RAY_CAMERA|PATH_RAY_SINGULAR;
118         int rng_offset = PRNG_BASE_NUM;
119
120         /* path iteration */
121         for(int bounce = 0; ; bounce++, rng_offset += PRNG_BOUNCE_NUM) {
122                 /* intersect scene */
123                 Intersection isect;
124
125                 if(!scene_intersect(kg, &ray, false, &isect)) {
126                         /* eval background shader if nothing hit */
127                         if(kernel_data.background.transparent && (path_flag & PATH_RAY_CAMERA)) {
128                                 Ltransparent += average(throughput);
129                         }
130                         else {
131 #ifdef __BACKGROUND__
132                                 ShaderData sd;
133                                 shader_setup_from_background(kg, &sd, &ray);
134                                 L += throughput*shader_eval_background(kg, &sd, path_flag);
135                                 shader_release(kg, &sd);
136 #else
137                                 L += make_float3(0.8f, 0.8f, 0.8f);
138 #endif
139                         }
140
141                         break;
142                 }
143
144                 /* setup shading */
145                 ShaderData sd;
146                 shader_setup_from_ray(kg, &sd, &isect, &ray);
147                 float rbsdf = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF);
148                 shader_eval_surface(kg, &sd, rbsdf, path_flag);
149
150 #ifdef __HOLDOUT__
151                 if((sd.flag & SD_HOLDOUT) && (path_flag & PATH_RAY_CAMERA)) {
152                         float3 holdout_weight = shader_holdout_eval(kg, &sd);
153
154                         if(kernel_data.background.transparent) {
155                                 Ltransparent += average(holdout_weight*throughput);
156                         }
157                         else {
158                                 ShaderData sd;
159                                 shader_setup_from_background(kg, &sd, &ray);
160                                 L += holdout_weight*throughput*shader_eval_background(kg, &sd, path_flag);
161                                 shader_release(kg, &sd);
162                         }
163                 }
164 #endif
165
166 #ifdef __EMISSION__
167                 /* emission */
168                 if(kernel_data.integrator.use_emission) {
169                         if(sd.flag & SD_EMISSION)
170                                 L += throughput*indirect_emission(kg, &sd, isect.t, path_flag, ray_pdf);
171
172                         /* sample illumination from lights to find path contribution */
173                         if((sd.flag & SD_BSDF_HAS_EVAL) &&
174                                 bounce != kernel_data.integrator.maxbounce) {
175                                 float light_t = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT);
176                                 float light_o = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_F);
177                                 float light_u = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_U);
178                                 float light_v = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_V);
179
180                                 Ray light_ray;
181                                 float3 light_L;
182
183                                 if(direct_emission(kg, &sd, light_t, light_o, light_u, light_v, &light_ray, &light_L)) {
184                                         /* trace shadow ray */
185                                         if(!scene_intersect(kg, &light_ray, true, &isect))
186                                                 L += throughput*light_L;
187                                 }
188                         }
189                 }
190 #endif
191
192                 /* no BSDF? we can stop here */
193                 if(!(sd.flag & SD_BSDF)) {
194                         path_flag &= ~PATH_RAY_CAMERA;
195                         break;
196                 }
197
198                 /* sample BSDF */
199                 float bsdf_pdf;
200                 float3 bsdf_eval;
201                 float3 bsdf_omega_in;
202                 differential3 bsdf_domega_in;
203                 float bsdf_u = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF_U);
204                 float bsdf_v = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF_V);
205                 int label;
206
207                 label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval,
208                         &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
209
210                 shader_release(kg, &sd);
211
212                 if(bsdf_pdf == 0.0f || is_zero(bsdf_eval)) {
213                         path_flag &= ~PATH_RAY_CAMERA;
214                         break;
215                 }
216
217                 /* modify throughput */
218                 throughput *= bsdf_eval/bsdf_pdf;
219
220                 /* set labels */
221 #ifdef __EMISSION__
222                 ray_pdf = bsdf_pdf;
223 #endif
224
225                 path_flag = path_flag_from_label(path_flag, label);
226
227                 /* path termination */
228                 float probability = path_terminate_probability(kg, bounce, throughput);
229                 float terminate = path_rng(kg, rng, pass, rng_offset + PRNG_TERMINATE);
230
231                 if(terminate >= probability) {
232                         path_flag &= ~PATH_RAY_CAMERA;
233                         break;
234                 }
235
236                 throughput /= probability;
237
238                 /* setup ray */
239                 ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
240                 ray.D = bsdf_omega_in;
241                 ray.t = FLT_MAX;
242 #ifdef __RAY_DIFFERENTIALS__
243                 ray.dP = sd.dP;
244                 ray.dD = bsdf_domega_in;
245 #endif
246         }
247
248         return make_float4(L.x, L.y, L.z, 1.0f - Ltransparent);
249 }
250
251 __device void kernel_path_trace(KernelGlobals *kg, __global float4 *buffer, __global uint *rng_state, int pass, int x, int y)
252 {
253         /* initialize random numbers */
254         RNG rng;
255
256         float filter_u;
257         float filter_v;
258
259         path_rng_init(kg, rng_state, pass, &rng, x, y, &filter_u, &filter_v);
260
261         /* sample camera ray */
262         Ray ray;
263
264         float lens_u = path_rng(kg, &rng, pass, PRNG_LENS_U);
265         float lens_v = path_rng(kg, &rng, pass, PRNG_LENS_V);
266
267         camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, &ray);
268
269         /* integrate */
270 #ifdef __MODIFY_TP__
271         float3 throughput = path_terminate_modified_throughput(kg, buffer, x, y, pass);
272         float4 L = kernel_path_integrate(kg, &rng, pass, ray, throughput)/throughput;
273 #else
274         float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
275         float4 L = kernel_path_integrate(kg, &rng, pass, ray, throughput);
276 #endif
277
278         /* accumulate result in output buffer */
279         int index = x + y*kernel_data.cam.width;
280
281         if(pass == 0)
282                 buffer[index] = L;
283         else
284                 buffer[index] += L;
285
286         path_rng_end(kg, rng_state, rng, x, y);
287 }
288
289 CCL_NAMESPACE_END
290