47aeea4f5c59484d3e12b6eddb35cb980111c900
[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 float3 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
113 #ifdef __EMISSION__
114         float ray_pdf = 0.0f;
115 #endif
116         int path_flag = PATH_RAY_CAMERA|PATH_RAY_SINGULAR;
117         int rng_offset = PRNG_BASE_NUM;
118
119         /* path iteration */
120         for(int bounce = 0; ; bounce++, rng_offset += PRNG_BOUNCE_NUM) {
121                 /* intersect scene */
122                 Intersection isect;
123
124                 if(!scene_intersect(kg, &ray, false, &isect)) {
125                         /* eval background shader if nothing hit */
126 #ifdef __BACKGROUND__
127                         ShaderData sd;
128                         shader_setup_from_background(kg, &sd, &ray);
129                         L += throughput*shader_eval_background(kg, &sd, path_flag);
130                         shader_release(kg, &sd);
131 #else
132                         L += make_float3(0.8f, 0.8f, 0.8f);
133 #endif
134                         break;
135                 }
136
137                 /* setup shading */
138                 ShaderData sd;
139                 shader_setup_from_ray(kg, &sd, &isect, &ray);
140                 float rbsdf = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF);
141                 shader_eval_surface(kg, &sd, rbsdf, path_flag);
142
143 #ifdef __EMISSION__
144                 /* emission */
145                 if(kernel_data.integrator.use_emission) {
146                         if(sd.flag & SD_EMISSION)
147                                 L += throughput*indirect_emission(kg, &sd, isect.t, path_flag, ray_pdf);
148
149                         /* sample illumination from lights to find path contribution */
150                         if((sd.flag & SD_BSDF_HAS_EVAL) &&
151                                 bounce != kernel_data.integrator.maxbounce) {
152                                 float light_t = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT);
153                                 float light_o = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_F);
154                                 float light_u = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_U);
155                                 float light_v = path_rng(kg, rng, pass, rng_offset + PRNG_LIGHT_V);
156
157                                 Ray light_ray;
158                                 float3 light_L;
159
160                                 if(direct_emission(kg, &sd, light_t, light_o, light_u, light_v, &light_ray, &light_L)) {
161                                         /* trace shadow ray */
162                                         if(!scene_intersect(kg, &light_ray, true, &isect))
163                                                 L += throughput*light_L;
164                                 }
165                         }
166                 }
167 #endif
168
169                 /* sample BSDF */
170                 float bsdf_pdf;
171                 float3 bsdf_eval;
172                 float3 bsdf_omega_in;
173                 differential3 bsdf_domega_in;
174                 float bsdf_u = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF_U);
175                 float bsdf_v = path_rng(kg, rng, pass, rng_offset + PRNG_BSDF_V);
176                 int label;
177
178                 label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval,
179                         &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
180
181                 shader_release(kg, &sd);
182
183                 if(bsdf_pdf == 0.0f || is_zero(bsdf_eval))
184                         break;
185
186                 /* modify throughput */
187                 throughput *= bsdf_eval/bsdf_pdf;
188
189                 /* set labels */
190 #ifdef __EMISSION__
191                 ray_pdf = bsdf_pdf;
192 #endif
193
194                 path_flag = path_flag_from_label(path_flag, label);
195
196                 /* path termination */
197                 float probability = path_terminate_probability(kg, bounce, throughput);
198                 float terminate = path_rng(kg, rng, pass, rng_offset + PRNG_TERMINATE);
199
200                 if(terminate >= probability)
201                         break;
202
203                 throughput /= probability;
204
205                 /* setup ray */
206                 ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng);
207                 ray.D = bsdf_omega_in;
208                 ray.t = FLT_MAX;
209 #ifdef __RAY_DIFFERENTIALS__
210                 ray.dP = sd.dP;
211                 ray.dD = bsdf_domega_in;
212 #endif
213         }
214
215         return L;
216 }
217
218 __device void kernel_path_trace(KernelGlobals *kg, __global float4 *buffer, __global uint *rng_state, int pass, int x, int y)
219 {
220         /* initialize random numbers */
221         RNG rng;
222
223         float filter_u;
224         float filter_v;
225
226         path_rng_init(kg, rng_state, pass, &rng, x, y, &filter_u, &filter_v);
227
228         /* sample camera ray */
229         Ray ray;
230
231         float lens_u = path_rng(kg, &rng, pass, PRNG_LENS_U);
232         float lens_v = path_rng(kg, &rng, pass, PRNG_LENS_V);
233
234         camera_sample(kg, x, y, filter_u, filter_v, lens_u, lens_v, &ray);
235
236         /* integrate */
237 #ifdef __MODIFY_TP__
238         float3 throughput = path_terminate_modified_throughput(kg, buffer, x, y, pass);
239         float3 L = kernel_path_integrate(kg, &rng, pass, ray, throughput)/throughput;
240 #else
241         float3 throughput = make_float3(1.0f, 1.0f, 1.0f);
242         float3 L = kernel_path_integrate(kg, &rng, pass, ray, throughput);
243 #endif
244
245         /* accumulate result in output buffer */
246         int index = x + y*kernel_data.cam.width;
247
248         float4 result;
249         result.x = L.x;
250         result.y = L.y;
251         result.z = L.z;
252         result.w = 1.0f;
253
254         if(pass == 0)
255                 buffer[index] = result;
256         else
257                 buffer[index] += result;
258
259         path_rng_end(kg, rng_state, rng, x, y);
260 }
261
262 CCL_NAMESPACE_END
263