Blender  V2.93
kernel_path_volume.h
Go to the documentation of this file.
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 
18 
19 #ifdef __VOLUME_SCATTER__
20 
21 ccl_device_inline void kernel_path_volume_connect_light(KernelGlobals *kg,
22  ShaderData *sd,
23  ShaderData *emission_sd,
24  float3 throughput,
26  PathRadiance *L)
27 {
28 # ifdef __EMISSION__
29  /* sample illumination from lights to find path contribution */
30  Ray light_ray 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 
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 
65 ccl_device_noinline_cpu bool kernel_path_volume_bounce(KernelGlobals *kg,
66  ShaderData *sd,
67  ccl_addr_space float3 *throughput,
69  PathRadianceState *L_state,
70  ccl_addr_space Ray *ray)
71 {
72  /* sample phase function */
73  float phase_pdf;
75  float3 phase_omega_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 */
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. */
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__))
131 ccl_device void kernel_branched_path_volume_connect_light(KernelGlobals *kg,
132  ShaderData *sd,
133  ShaderData *emission_sd,
134  float3 throughput,
136  PathRadiance *L,
137  bool sample_all_lights,
138  Ray *ray,
139  const VolumeSegment *segment)
140 {
141 # ifdef __EMISSION__
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) {
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;
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 
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 */
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 
unsigned int uint
Definition: BLI_sys_types.h:83
#define UNLIKELY(x)
const char * label
Light lamp
ccl_device_inline bool bsdf_eval_is_zero(BsdfEval *eval)
ccl_device_inline void path_radiance_accum_light(KernelGlobals *kg, PathRadiance *L, ccl_addr_space PathState *state, float3 throughput, BsdfEval *bsdf_eval, float3 shadow, float shadow_fac, bool is_lamp)
ccl_device_inline void path_radiance_bsdf_bounce(KernelGlobals *kg, PathRadianceState *L_state, ccl_addr_space float3 *throughput, BsdfEval *bsdf_eval, float bsdf_pdf, int bounce, int bsdf_label)
#define kernel_data
#define ccl_addr_space
#define ccl_optional_struct_init
#define ccl_device
#define ccl_device_noinline_cpu
#define ccl_device_inline
#define CCL_NAMESPACE_END
#define fminf(x, y)
ccl_device_noinline_cpu bool direct_emission(KernelGlobals *kg, ShaderData *sd, ShaderData *emission_sd, LightSample *ls, ccl_addr_space PathState *state, Ray *ray, BsdfEval *eval, bool *is_lamp, float rand_terminate)
ccl_device_inline uint cmj_hash(uint i, uint p)
ccl_device_noinline bool light_sample(KernelGlobals *kg, int lamp, float randu, float randv, float time, float3 P, int bounce, LightSample *ls)
Definition: kernel_light.h:663
ccl_device_inline int light_select_num_samples(KernelGlobals *kg, int index)
Definition: kernel_light.h:700
ccl_device_inline bool light_select_reached_max_bounces(KernelGlobals *kg, int index, int bounce)
Definition: kernel_light.h:658
ccl_device_inline void path_state_next(KernelGlobals *kg, ccl_addr_space PathState *state, int label)
ccl_device_inline float path_state_continuation_probability(KernelGlobals *kg, ccl_addr_space PathState *state, const float3 throughput)
ccl_device_inline void path_state_rng_2D(KernelGlobals *kg, const ccl_addr_space PathState *state, int dimension, float *fx, float *fy)
ccl_device_inline float path_branched_rng_1D(KernelGlobals *kg, uint rng_hash, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension)
ccl_device_inline float path_state_rng_1D(KernelGlobals *kg, const ccl_addr_space PathState *state, int dimension)
ccl_device_inline void path_branched_rng_2D(KernelGlobals *kg, uint rng_hash, const ccl_addr_space PathState *state, int branch, int num_branches, int dimension, float *fx, float *fy)
ccl_device_inline float path_branched_rng_light_termination(KernelGlobals *kg, uint rng_hash, const ccl_addr_space PathState *state, int branch, int num_branches)
ccl_device_inline float path_state_rng_light_termination(KernelGlobals *kg, const ccl_addr_space PathState *state)
ccl_device_inline bool shadow_blocked(KernelGlobals *kg, ShaderData *sd, ShaderData *shadow_sd, ccl_addr_space PathState *state, Ray *ray, float3 *shadow)
@ PRNG_BOUNCE_NUM
Definition: kernel_types.h:248
@ PRNG_BSDF_U
Definition: kernel_types.h:240
@ PRNG_LIGHT_U
Definition: kernel_types.h:242
@ PRNG_SCATTER_DISTANCE
Definition: kernel_types.h:247
@ PRNG_TERMINATE
Definition: kernel_types.h:245
@ PRNG_PHASE_CHANNEL
Definition: kernel_types.h:246
ShaderData
VolumeIntegrateResult
Definition: kernel_volume.h:27
@ VOLUME_PATH_SCATTERED
Definition: kernel_volume.h:28
static ulong state[N]
#define L
Segment< FEdge *, Vec3r > segment
float3 P
Definition: kernel_types.h:647