2 * Copyright 2011-2015 Blender Foundation
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "kernel_split_common.h"
19 /* Note on kernel_lamp_emission
20 * This is the 3rd kernel in the ray-tracing logic. This is the second of the
21 * path-iteration kernels. This kernel takes care of the indirect lamp emission logic.
22 * This kernel operates on QUEUE_ACTIVE_AND_REGENERATED_RAYS. It processes rays of state RAY_ACTIVE
23 * and RAY_HIT_BACKGROUND.
24 * We will empty QUEUE_ACTIVE_AND_REGENERATED_RAYS queue in this kernel.
25 * The input/output of the kernel is as follows,
26 * Throughput_coop ------------------------------------|--- kernel_lamp_emission --|--- PathRadiance_coop
27 * Ray_coop -------------------------------------------| |--- Queue_data(QUEUE_ACTIVE_AND_REGENERATED_RAYS)
28 * PathState_coop -------------------------------------| |--- Queue_index(QUEUE_ACTIVE_AND_REGENERATED_RAYS)
29 * kg (globals) ---------------------------------------| |
30 * Intersection_coop ----------------------------------| |
31 * ray_state ------------------------------------------| |
32 * Queue_data (QUEUE_ACTIVE_AND_REGENERATED_RAYS) -----| |
33 * Queue_index (QUEUE_ACTIVE_AND_REGENERATED_RAYS) ----| |
34 * queuesize ------------------------------------------| |
35 * use_queues_flag ------------------------------------| |
36 * sw -------------------------------------------------| |
37 * sh -------------------------------------------------| |
38 * parallel_samples -----------------------------------| |
40 ccl_device void kernel_lamp_emission(
42 ccl_global float3 *throughput_coop, /* Required for lamp emission */
43 PathRadiance *PathRadiance_coop, /* Required for lamp emission */
44 ccl_global Ray *Ray_coop, /* Required for lamp emission */
45 ccl_global PathState *PathState_coop, /* Required for lamp emission */
46 Intersection *Intersection_coop, /* Required for lamp emission */
47 ccl_global char *ray_state, /* Denotes the state of each ray */
49 ccl_global char *use_queues_flag, /* Used to decide if this kernel should use
50 * queues to fetch ray index
52 int parallel_samples, /* Number of samples to be processed in parallel */
55 if(IS_STATE(ray_state, ray_index, RAY_ACTIVE) ||
56 IS_STATE(ray_state, ray_index, RAY_HIT_BACKGROUND))
58 PathRadiance *L = &PathRadiance_coop[ray_index];
59 ccl_global PathState *state = &PathState_coop[ray_index];
61 float3 throughput = throughput_coop[ray_index];
62 Ray ray = Ray_coop[ray_index];
65 if(kernel_data.integrator.use_lamp_mis && !(state->flag & PATH_RAY_CAMERA)) {
66 /* ray starting from previous non-transparent bounce */
69 light_ray.P = ray.P - state->ray_t*ray.D;
70 state->ray_t += Intersection_coop[ray_index].t;
72 light_ray.t = state->ray_t;
73 light_ray.time = ray.time;
74 light_ray.dD = ray.dD;
75 light_ray.dP = ray.dP;
76 /* intersect with lamp */
79 if(indirect_lamp_emission(kg, state, &light_ray, &emission)) {
80 path_radiance_accum_emission(L, throughput, emission, state->bounce);
83 #endif /* __LAMP_MIS__ */
85 /* __VOLUME__ feature is disabled */
88 /* volume attenuation, emission, scatter */
89 if(state->volume_stack[0].shader != SHADER_NONE) {
91 volume_ray.t = (hit)? isect.t: FLT_MAX;
93 bool heterogeneous = volume_stack_is_heterogeneous(kg, state->volume_stack);
95 #ifdef __VOLUME_DECOUPLED__
96 int sampling_method = volume_stack_sampling_method(kg, state->volume_stack);
97 bool decoupled = kernel_volume_use_decoupled(kg, heterogeneous, true, sampling_method);
100 /* cache steps along volume for repeated sampling */
101 VolumeSegment volume_segment;
102 ShaderData volume_sd;
104 shader_setup_from_volume(kg, &volume_sd, &volume_ray);
105 kernel_volume_decoupled_record(kg, state,
106 &volume_ray, &volume_sd, &volume_segment, heterogeneous);
108 volume_segment.sampling_method = sampling_method;
111 if(volume_segment.closure_flag & SD_EMISSION)
112 path_radiance_accum_emission(&L, throughput, volume_segment.accum_emission, state->bounce);
115 VolumeIntegrateResult result = VOLUME_PATH_ATTENUATED;
117 if(volume_segment.closure_flag & SD_SCATTER) {
120 /* direct light sampling */
121 kernel_branched_path_volume_connect_light(kg, rng, &volume_sd,
122 throughput, state, &L, 1.0f, all, &volume_ray, &volume_segment);
124 /* indirect sample. if we use distance sampling and take just
125 * one sample for direct and indirect light, we could share
126 * this computation, but makes code a bit complex */
127 float rphase = path_state_rng_1D_for_decision(kg, rng, state, PRNG_PHASE);
128 float rscatter = path_state_rng_1D_for_decision(kg, rng, state, PRNG_SCATTER_DISTANCE);
130 result = kernel_volume_decoupled_scatter(kg,
131 state, &volume_ray, &volume_sd, &throughput,
132 rphase, rscatter, &volume_segment, NULL, true);
135 if(result != VOLUME_PATH_SCATTERED)
136 throughput *= volume_segment.accum_transmittance;
138 /* free cached steps */
139 kernel_volume_decoupled_free(kg, &volume_segment);
141 if(result == VOLUME_PATH_SCATTERED) {
142 if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, state, &L, &ray))
149 #endif /* __VOLUME_DECOUPLED__ */
151 /* integrate along volume segment with distance sampling */
152 ShaderData volume_sd;
153 VolumeIntegrateResult result = kernel_volume_integrate(
154 kg, state, &volume_sd, &volume_ray, &L, &throughput, rng, heterogeneous);
156 #ifdef __VOLUME_SCATTER__
157 if(result == VOLUME_PATH_SCATTERED) {
158 /* direct lighting */
159 kernel_path_volume_connect_light(kg, rng, &volume_sd, throughput, state, &L);
161 /* indirect light bounce */
162 if(kernel_path_volume_bounce(kg, rng, &volume_sd, &throughput, state, &L, &ray))
167 #endif /* __VOLUME_SCATTER__ */
170 #endif /* __VOLUME__ */