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 #if defined(__BRANCHED_PATH__) || defined(__SUBSURFACE__) || defined(__SHADOW_TRICKS__) || \
20     defined(__BAKING__)
21 /* branched path tracing: connect path directly to position on one or more lights and add it to L
22  */
kernel_branched_path_surface_connect_light(KernelGlobals * kg,ShaderData * sd,ShaderData * emission_sd,ccl_addr_space PathState * state,float3 throughput,float num_samples_adjust,PathRadiance * L,int sample_all_lights)23 ccl_device_noinline_cpu void kernel_branched_path_surface_connect_light(
24     KernelGlobals *kg,
25     ShaderData *sd,
26     ShaderData *emission_sd,
27     ccl_addr_space PathState *state,
28     float3 throughput,
29     float num_samples_adjust,
30     PathRadiance *L,
31     int sample_all_lights)
32 {
33 #  ifdef __EMISSION__
34   /* sample illumination from lights to find path contribution */
35   BsdfEval L_light ccl_optional_struct_init;
36 
37   int num_lights = 0;
38   if (kernel_data.integrator.use_direct_light) {
39     if (sample_all_lights) {
40       num_lights = kernel_data.integrator.num_all_lights;
41       if (kernel_data.integrator.pdf_triangles != 0.0f) {
42         num_lights += 1;
43       }
44     }
45     else {
46       num_lights = 1;
47     }
48   }
49 
50   for (int i = 0; i < num_lights; i++) {
51     /* sample one light at random */
52     int num_samples = 1;
53     int num_all_lights = 1;
54     uint lamp_rng_hash = state->rng_hash;
55     bool double_pdf = false;
56     bool is_mesh_light = false;
57     bool is_lamp = false;
58 
59     if (sample_all_lights) {
60       /* lamp sampling */
61       is_lamp = i < kernel_data.integrator.num_all_lights;
62       if (is_lamp) {
63         if (UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce))) {
64           continue;
65         }
66         num_samples = ceil_to_int(num_samples_adjust * light_select_num_samples(kg, i));
67         num_all_lights = kernel_data.integrator.num_all_lights;
68         lamp_rng_hash = cmj_hash(state->rng_hash, i);
69         double_pdf = kernel_data.integrator.pdf_triangles != 0.0f;
70       }
71       /* mesh light sampling */
72       else {
73         num_samples = ceil_to_int(num_samples_adjust * kernel_data.integrator.mesh_light_samples);
74         double_pdf = kernel_data.integrator.num_all_lights != 0;
75         is_mesh_light = true;
76       }
77     }
78 
79     float num_samples_inv = num_samples_adjust / (num_samples * num_all_lights);
80 
81     for (int j = 0; j < num_samples; j++) {
82       Ray light_ray ccl_optional_struct_init;
83       light_ray.t = 0.0f; /* reset ray */
84 #    ifdef __OBJECT_MOTION__
85       light_ray.time = sd->time;
86 #    endif
87       bool has_emission = false;
88 
89       if (kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL)) {
90         float light_u, light_v;
91         path_branched_rng_2D(
92             kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
93         float terminate = path_branched_rng_light_termination(
94             kg, lamp_rng_hash, state, j, num_samples);
95 
96         /* only sample triangle lights */
97         if (is_mesh_light && double_pdf) {
98           light_u = 0.5f * light_u;
99         }
100 
101         LightSample ls ccl_optional_struct_init;
102         const int lamp = is_lamp ? i : -1;
103         if (light_sample(kg, lamp, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
104           /* The sampling probability returned by lamp_light_sample assumes that all lights were
105            * sampled. However, this code only samples lamps, so if the scene also had mesh lights,
106            * the real probability is twice as high. */
107           if (double_pdf) {
108             ls.pdf *= 2.0f;
109           }
110 
111           has_emission = direct_emission(
112               kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate);
113         }
114       }
115 
116       /* trace shadow ray */
117       float3 shadow;
118 
119       const bool blocked = shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow);
120 
121       if (has_emission) {
122         if (!blocked) {
123           /* accumulate */
124           path_radiance_accum_light(kg,
125                                     L,
126                                     state,
127                                     throughput * num_samples_inv,
128                                     &L_light,
129                                     shadow,
130                                     num_samples_inv,
131                                     is_lamp);
132         }
133         else {
134           path_radiance_accum_total_light(L, state, throughput * num_samples_inv, &L_light);
135         }
136       }
137     }
138   }
139 #  endif
140 }
141 
142 /* branched path tracing: bounce off or through surface to with new direction stored in ray */
kernel_branched_path_surface_bounce(KernelGlobals * kg,ShaderData * sd,const ShaderClosure * sc,int sample,int num_samples,ccl_addr_space float3 * throughput,ccl_addr_space PathState * state,PathRadianceState * L_state,ccl_addr_space Ray * ray,float sum_sample_weight)143 ccl_device bool kernel_branched_path_surface_bounce(KernelGlobals *kg,
144                                                     ShaderData *sd,
145                                                     const ShaderClosure *sc,
146                                                     int sample,
147                                                     int num_samples,
148                                                     ccl_addr_space float3 *throughput,
149                                                     ccl_addr_space PathState *state,
150                                                     PathRadianceState *L_state,
151                                                     ccl_addr_space Ray *ray,
152                                                     float sum_sample_weight)
153 {
154   /* sample BSDF */
155   float bsdf_pdf;
156   BsdfEval bsdf_eval ccl_optional_struct_init;
157   float3 bsdf_omega_in ccl_optional_struct_init;
158   differential3 bsdf_domega_in ccl_optional_struct_init;
159   float bsdf_u, bsdf_v;
160   path_branched_rng_2D(
161       kg, state->rng_hash, state, sample, num_samples, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
162   int label;
163 
164   label = shader_bsdf_sample_closure(
165       kg, sd, sc, bsdf_u, bsdf_v, &bsdf_eval, &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
166 
167   if (bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
168     return false;
169 
170   /* modify throughput */
171   path_radiance_bsdf_bounce(kg, L_state, throughput, &bsdf_eval, bsdf_pdf, state->bounce, label);
172 
173 #  ifdef __DENOISING_FEATURES__
174   state->denoising_feature_weight *= sc->sample_weight / (sum_sample_weight * num_samples);
175 #  endif
176 
177   /* modify path state */
178   path_state_next(kg, state, label);
179 
180   /* setup ray */
181   ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT) ? -sd->Ng : sd->Ng);
182   ray->D = normalize(bsdf_omega_in);
183   ray->t = FLT_MAX;
184 #  ifdef __RAY_DIFFERENTIALS__
185   ray->dP = sd->dP;
186   ray->dD = bsdf_domega_in;
187 #  endif
188 #  ifdef __OBJECT_MOTION__
189   ray->time = sd->time;
190 #  endif
191 
192 #  ifdef __VOLUME__
193   /* enter/exit volume */
194   if (label & LABEL_TRANSMIT)
195     kernel_volume_stack_enter_exit(kg, sd, state->volume_stack);
196 #  endif
197 
198   /* branch RNG state */
199   path_state_branch(state, sample, num_samples);
200 
201   /* set MIS state */
202   state->min_ray_pdf = fminf(bsdf_pdf, FLT_MAX);
203   state->ray_pdf = bsdf_pdf;
204 #  ifdef __LAMP_MIS__
205   state->ray_t = 0.0f;
206 #  endif
207 
208   return true;
209 }
210 
211 #endif
212 
213 /* path tracing: connect path directly to position on a light and add it to L */
kernel_path_surface_connect_light(KernelGlobals * kg,ShaderData * sd,ShaderData * emission_sd,float3 throughput,ccl_addr_space PathState * state,PathRadiance * L)214 ccl_device_inline void kernel_path_surface_connect_light(KernelGlobals *kg,
215                                                          ShaderData *sd,
216                                                          ShaderData *emission_sd,
217                                                          float3 throughput,
218                                                          ccl_addr_space PathState *state,
219                                                          PathRadiance *L)
220 {
221   PROFILING_INIT(kg, PROFILING_CONNECT_LIGHT);
222 
223 #ifdef __EMISSION__
224 #  ifdef __SHADOW_TRICKS__
225   int all = (state->flag & PATH_RAY_SHADOW_CATCHER);
226   kernel_branched_path_surface_connect_light(kg, sd, emission_sd, state, throughput, 1.0f, L, all);
227 #  else
228   /* sample illumination from lights to find path contribution */
229   Ray light_ray ccl_optional_struct_init;
230   BsdfEval L_light ccl_optional_struct_init;
231   bool is_lamp = false;
232   bool has_emission = false;
233 
234   light_ray.t = 0.0f;
235 #    ifdef __OBJECT_MOTION__
236   light_ray.time = sd->time;
237 #    endif
238 
239   if (kernel_data.integrator.use_direct_light && (sd->flag & SD_BSDF_HAS_EVAL)) {
240     float light_u, light_v;
241     path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
242 
243     LightSample ls ccl_optional_struct_init;
244     if (light_sample(kg, -1, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
245       float terminate = path_state_rng_light_termination(kg, state);
246       has_emission = direct_emission(
247           kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate);
248     }
249   }
250 
251   /* trace shadow ray */
252   float3 shadow;
253 
254   const bool blocked = shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow);
255 
256   if (has_emission) {
257     if (!blocked) {
258       /* accumulate */
259       path_radiance_accum_light(kg, L, state, throughput, &L_light, shadow, 1.0f, is_lamp);
260     }
261     else {
262       path_radiance_accum_total_light(L, state, throughput, &L_light);
263     }
264   }
265 #  endif
266 #endif
267 }
268 
269 /* path tracing: bounce off or through surface to with new direction stored in ray */
kernel_path_surface_bounce(KernelGlobals * kg,ShaderData * sd,ccl_addr_space float3 * throughput,ccl_addr_space PathState * state,PathRadianceState * L_state,ccl_addr_space Ray * ray)270 ccl_device bool kernel_path_surface_bounce(KernelGlobals *kg,
271                                            ShaderData *sd,
272                                            ccl_addr_space float3 *throughput,
273                                            ccl_addr_space PathState *state,
274                                            PathRadianceState *L_state,
275                                            ccl_addr_space Ray *ray)
276 {
277   PROFILING_INIT(kg, PROFILING_SURFACE_BOUNCE);
278 
279   /* no BSDF? we can stop here */
280   if (sd->flag & SD_BSDF) {
281     /* sample BSDF */
282     float bsdf_pdf;
283     BsdfEval bsdf_eval ccl_optional_struct_init;
284     float3 bsdf_omega_in ccl_optional_struct_init;
285     differential3 bsdf_domega_in ccl_optional_struct_init;
286     float bsdf_u, bsdf_v;
287     path_state_rng_2D(kg, state, PRNG_BSDF_U, &bsdf_u, &bsdf_v);
288     int label;
289 
290     label = shader_bsdf_sample(
291         kg, sd, bsdf_u, bsdf_v, &bsdf_eval, &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf);
292 
293     if (bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval))
294       return false;
295 
296     /* modify throughput */
297     path_radiance_bsdf_bounce(kg, L_state, throughput, &bsdf_eval, bsdf_pdf, state->bounce, label);
298 
299     /* set labels */
300     if (!(label & LABEL_TRANSPARENT)) {
301       state->ray_pdf = bsdf_pdf;
302 #ifdef __LAMP_MIS__
303       state->ray_t = 0.0f;
304 #endif
305       state->min_ray_pdf = fminf(bsdf_pdf, state->min_ray_pdf);
306     }
307 
308     /* update path state */
309     path_state_next(kg, state, label);
310 
311     /* setup ray */
312     ray->P = ray_offset(sd->P, (label & LABEL_TRANSMIT) ? -sd->Ng : sd->Ng);
313     ray->D = normalize(bsdf_omega_in);
314 
315     if (state->bounce == 0)
316       ray->t -= sd->ray_length; /* clipping works through transparent */
317     else
318       ray->t = FLT_MAX;
319 
320 #ifdef __RAY_DIFFERENTIALS__
321     ray->dP = sd->dP;
322     ray->dD = bsdf_domega_in;
323 #endif
324 
325 #ifdef __VOLUME__
326     /* enter/exit volume */
327     if (label & LABEL_TRANSMIT)
328       kernel_volume_stack_enter_exit(kg, sd, state->volume_stack);
329 #endif
330     return true;
331   }
332 #ifdef __VOLUME__
333   else if (sd->flag & SD_HAS_ONLY_VOLUME) {
334     if (!path_state_volume_next(kg, state)) {
335       return false;
336     }
337 
338     if (state->bounce == 0)
339       ray->t -= sd->ray_length; /* clipping works through transparent */
340     else
341       ray->t = FLT_MAX;
342 
343     /* setup ray position, direction stays unchanged */
344     ray->P = ray_offset(sd->P, -sd->Ng);
345 #  ifdef __RAY_DIFFERENTIALS__
346     ray->dP = sd->dP;
347 #  endif
348 
349     /* enter/exit volume */
350     kernel_volume_stack_enter_exit(kg, sd, state->volume_stack);
351     return true;
352   }
353 #endif
354   else {
355     /* no bsdf or volume? */
356     return false;
357   }
358 }
359 
360 CCL_NAMESPACE_END
361