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 #ifdef __VOLUME_SCATTER__
20
kernel_path_volume_connect_light(KernelGlobals * kg,ShaderData * sd,ShaderData * emission_sd,float3 throughput,ccl_addr_space PathState * state,PathRadiance * L)21 ccl_device_inline void kernel_path_volume_connect_light(KernelGlobals *kg,
22 ShaderData *sd,
23 ShaderData *emission_sd,
24 float3 throughput,
25 ccl_addr_space PathState *state,
26 PathRadiance *L)
27 {
28 # ifdef __EMISSION__
29 /* sample illumination from lights to find path contribution */
30 Ray light_ray ccl_optional_struct_init;
31 BsdfEval L_light ccl_optional_struct_init;
32 bool is_lamp = false;
33 bool has_emission = false;
34
35 light_ray.t = 0.0f;
36 # ifdef __OBJECT_MOTION__
37 /* connect to light from given point where shader has been evaluated */
38 light_ray.time = sd->time;
39 # endif
40
41 if (kernel_data.integrator.use_direct_light) {
42 float light_u, light_v;
43 path_state_rng_2D(kg, state, PRNG_LIGHT_U, &light_u, &light_v);
44
45 LightSample ls ccl_optional_struct_init;
46 if (light_sample(kg, -1, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
47 float terminate = path_state_rng_light_termination(kg, state);
48 has_emission = direct_emission(
49 kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate);
50 }
51 }
52
53 /* trace shadow ray */
54 float3 shadow;
55
56 const bool blocked = shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow);
57
58 if (has_emission && !blocked) {
59 /* accumulate */
60 path_radiance_accum_light(kg, L, state, throughput, &L_light, shadow, 1.0f, is_lamp);
61 }
62 # endif /* __EMISSION__ */
63 }
64
kernel_path_volume_bounce(KernelGlobals * kg,ShaderData * sd,ccl_addr_space float3 * throughput,ccl_addr_space PathState * state,PathRadianceState * L_state,ccl_addr_space Ray * ray)65 ccl_device_noinline_cpu bool kernel_path_volume_bounce(KernelGlobals *kg,
66 ShaderData *sd,
67 ccl_addr_space float3 *throughput,
68 ccl_addr_space PathState *state,
69 PathRadianceState *L_state,
70 ccl_addr_space Ray *ray)
71 {
72 /* sample phase function */
73 float phase_pdf;
74 BsdfEval phase_eval ccl_optional_struct_init;
75 float3 phase_omega_in ccl_optional_struct_init;
76 differential3 phase_domega_in ccl_optional_struct_init;
77 float phase_u, phase_v;
78 path_state_rng_2D(kg, state, PRNG_BSDF_U, &phase_u, &phase_v);
79 int label;
80
81 label = shader_volume_phase_sample(
82 kg, sd, phase_u, phase_v, &phase_eval, &phase_omega_in, &phase_domega_in, &phase_pdf);
83
84 if (phase_pdf == 0.0f || bsdf_eval_is_zero(&phase_eval))
85 return false;
86
87 /* modify throughput */
88 path_radiance_bsdf_bounce(kg, L_state, throughput, &phase_eval, phase_pdf, state->bounce, label);
89
90 /* set labels */
91 state->ray_pdf = phase_pdf;
92 # ifdef __LAMP_MIS__
93 state->ray_t = 0.0f;
94 # endif
95 state->min_ray_pdf = fminf(phase_pdf, state->min_ray_pdf);
96
97 /* update path state */
98 path_state_next(kg, state, label);
99
100 /* Russian roulette termination of volume ray scattering. */
101 float probability = path_state_continuation_probability(kg, state, *throughput);
102
103 if (probability == 0.0f) {
104 return false;
105 }
106 else if (probability != 1.0f) {
107 /* Use dimension from the previous bounce, has not been used yet. */
108 float terminate = path_state_rng_1D(kg, state, PRNG_TERMINATE - PRNG_BOUNCE_NUM);
109
110 if (terminate >= probability) {
111 return false;
112 }
113
114 *throughput /= probability;
115 }
116
117 /* setup ray */
118 ray->P = sd->P;
119 ray->D = phase_omega_in;
120 ray->t = FLT_MAX;
121
122 # ifdef __RAY_DIFFERENTIALS__
123 ray->dP = sd->dP;
124 ray->dD = phase_domega_in;
125 # endif
126
127 return true;
128 }
129
130 # if !defined(__SPLIT_KERNEL__) && (defined(__BRANCHED_PATH__) || defined(__VOLUME_DECOUPLED__))
kernel_branched_path_volume_connect_light(KernelGlobals * kg,ShaderData * sd,ShaderData * emission_sd,float3 throughput,ccl_addr_space PathState * state,PathRadiance * L,bool sample_all_lights,Ray * ray,const VolumeSegment * segment)131 ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg,
132 ShaderData *sd,
133 ShaderData *emission_sd,
134 float3 throughput,
135 ccl_addr_space PathState *state,
136 PathRadiance *L,
137 bool sample_all_lights,
138 Ray *ray,
139 const VolumeSegment *segment)
140 {
141 # ifdef __EMISSION__
142 BsdfEval L_light ccl_optional_struct_init;
143
144 int num_lights = 1;
145 if (sample_all_lights) {
146 num_lights = kernel_data.integrator.num_all_lights;
147 if (kernel_data.integrator.pdf_triangles != 0.0f) {
148 num_lights += 1;
149 }
150 }
151
152 for (int i = 0; i < num_lights; ++i) {
153 /* sample one light at random */
154 int num_samples = 1;
155 int num_all_lights = 1;
156 uint lamp_rng_hash = state->rng_hash;
157 bool double_pdf = false;
158 bool is_mesh_light = false;
159 bool is_lamp = false;
160
161 if (sample_all_lights) {
162 /* lamp sampling */
163 is_lamp = i < kernel_data.integrator.num_all_lights;
164 if (is_lamp) {
165 if (UNLIKELY(light_select_reached_max_bounces(kg, i, state->bounce))) {
166 continue;
167 }
168 num_samples = light_select_num_samples(kg, i);
169 num_all_lights = kernel_data.integrator.num_all_lights;
170 lamp_rng_hash = cmj_hash(state->rng_hash, i);
171 double_pdf = kernel_data.integrator.pdf_triangles != 0.0f;
172 }
173 /* mesh light sampling */
174 else {
175 num_samples = kernel_data.integrator.mesh_light_samples;
176 double_pdf = kernel_data.integrator.num_all_lights != 0;
177 is_mesh_light = true;
178 }
179 }
180
181 float num_samples_inv = 1.0f / (num_samples * num_all_lights);
182
183 for (int j = 0; j < num_samples; j++) {
184 Ray light_ray ccl_optional_struct_init;
185 light_ray.t = 0.0f; /* reset ray */
186 # ifdef __OBJECT_MOTION__
187 light_ray.time = sd->time;
188 # endif
189 bool has_emission = false;
190
191 float3 tp = throughput;
192
193 if (kernel_data.integrator.use_direct_light) {
194 /* sample random position on random light/triangle */
195 float light_u, light_v;
196 path_branched_rng_2D(
197 kg, lamp_rng_hash, state, j, num_samples, PRNG_LIGHT_U, &light_u, &light_v);
198
199 /* only sample triangle lights */
200 if (is_mesh_light && double_pdf) {
201 light_u = 0.5f * light_u;
202 }
203
204 LightSample ls ccl_optional_struct_init;
205 const int lamp = is_lamp ? i : -1;
206 light_sample(kg, lamp, light_u, light_v, sd->time, ray->P, state->bounce, &ls);
207
208 /* sample position on volume segment */
209 float rphase = path_branched_rng_1D(
210 kg, state->rng_hash, state, j, num_samples, PRNG_PHASE_CHANNEL);
211 float rscatter = path_branched_rng_1D(
212 kg, state->rng_hash, state, j, num_samples, PRNG_SCATTER_DISTANCE);
213
214 VolumeIntegrateResult result = kernel_volume_decoupled_scatter(kg,
215 state,
216 ray,
217 sd,
218 &tp,
219 rphase,
220 rscatter,
221 segment,
222 (ls.t != FLT_MAX) ? &ls.P :
223 NULL,
224 false);
225
226 if (result == VOLUME_PATH_SCATTERED) {
227 /* todo: split up light_sample so we don't have to call it again with new position */
228 if (light_sample(kg, lamp, light_u, light_v, sd->time, sd->P, state->bounce, &ls)) {
229 if (double_pdf) {
230 ls.pdf *= 2.0f;
231 }
232
233 /* sample random light */
234 float terminate = path_branched_rng_light_termination(
235 kg, state->rng_hash, state, j, num_samples);
236 has_emission = direct_emission(
237 kg, sd, emission_sd, &ls, state, &light_ray, &L_light, &is_lamp, terminate);
238 }
239 }
240 }
241
242 /* trace shadow ray */
243 float3 shadow;
244
245 const bool blocked = shadow_blocked(kg, sd, emission_sd, state, &light_ray, &shadow);
246
247 if (has_emission && !blocked) {
248 /* accumulate */
249 path_radiance_accum_light(
250 kg, L, state, tp * num_samples_inv, &L_light, shadow, num_samples_inv, is_lamp);
251 }
252 }
253 }
254 # endif /* __EMISSION__ */
255 }
256 # endif /* __SPLIT_KERNEL__ */
257
258 #endif /* __VOLUME_SCATTER__ */
259
260 CCL_NAMESPACE_END
261