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