Blender  V3.3
intersect_closest.h
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright 2011-2022 Blender Foundation */
3 
4 #pragma once
5 
7 
10 
11 #include "kernel/light/light.h"
12 
14 
15 #include "kernel/geom/geom.h"
16 
17 #include "kernel/bvh/bvh.h"
18 
20 
23  const int shader_flags)
24 {
25 
26  /* Optional AO bounce termination.
27  * We continue evaluating emissive/transparent surfaces and volumes, similar
28  * to direct lighting. Only if we know there are none can we terminate the
29  * path immediately. */
30  if (path_state_ao_bounce(kg, state)) {
31  if (shader_flags & (SD_HAS_TRANSPARENT_SHADOW | SD_HAS_EMISSION)) {
33  }
36  }
37  else {
38  return true;
39  }
40  }
41 
42  /* Load random number state. */
43  RNGState rng_state;
44  path_state_rng_load(state, &rng_state);
45 
46  /* We perform path termination in this kernel to avoid launching shade_surface
47  * and evaluating the shader when not needed. Only for emission and transparent
48  * surfaces in front of emission do we need to evaluate the shader, since we
49  * perform MIS as part of indirect rays. */
50  const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
51  const float probability = path_state_continuation_probability(kg, state, path_flag);
52  INTEGRATOR_STATE_WRITE(state, path, continuation_probability) = probability;
53 
54  if (probability != 1.0f) {
55  const float terminate = path_state_rng_1D(kg, &rng_state, PRNG_TERMINATE);
56 
57  if (probability == 0.0f || terminate >= probability) {
58  if (shader_flags & SD_HAS_EMISSION) {
59  /* Mark path to be terminated right after shader evaluation on the surface. */
61  }
63  /* TODO: only do this for emissive volumes. */
65  }
66  else {
67  return true;
68  }
69  }
70  }
71 
72  return false;
73 }
74 
75 #ifdef __SHADOW_CATCHER__
76 /* Split path if a shadow catcher was hit. */
77 ccl_device_forceinline void integrator_split_shadow_catcher(
78  KernelGlobals kg,
82 {
83  /* Test if we hit a shadow catcher object, and potentially split the path to continue tracing two
84  * paths from here. */
85  const int object_flags = intersection_get_object_flags(kg, isect);
86  if (!kernel_shadow_catcher_is_path_split_bounce(kg, state, object_flags)) {
87  return;
88  }
89 
90  kernel_write_shadow_catcher_bounce_data(kg, state, render_buffer);
91 
92  /* Mark state as having done a shadow catcher split so that it stops contributing to
93  * the shadow catcher matte pass, but keeps contributing to the combined pass. */
95 
96  /* Copy current state to new state. */
98 
99  /* Initialize new state.
100  *
101  * Note that the splitting leaves kernel and sorting counters as-is, so use INIT semantic for
102  * the matte path. */
103 
104  /* Mark current state so that it will only track contribution of shadow catcher objects ignoring
105  * non-catcher objects. */
107 
108  if (kernel_data.film.pass_background != PASS_UNUSED && !kernel_data.background.transparent) {
109  /* If using background pass, schedule background shading kernel so that we have a background
110  * to alpha-over on. The background kernel will then continue the path afterwards. */
113  return;
114  }
115 
117  /* Volume stack is not empty. Re-init the volume stack to exclude any non-shadow catcher
118  * objects from it, and then continue shading volume and shadow catcher surface after. */
120  return;
121  }
122 
123  /* Continue with shading shadow catcher surface. */
124  const int shader = intersection_get_shader(kg, isect);
125  const int flags = kernel_data_fetch(shaders, shader).flags;
126  const bool use_caustics = kernel_data.integrator.use_caustics &&
127  (object_flags & SD_OBJECT_CAUSTICS);
128  const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE);
129 
130  if (use_caustics) {
132  }
133  else if (use_raytrace_kernel) {
136  }
137  else {
139  }
140 }
141 
142 /* Schedule next kernel to be executed after updating volume stack for shadow catcher. */
143 template<DeviceKernel current_kernel>
144 ccl_device_forceinline void integrator_intersect_next_kernel_after_shadow_catcher_volume(
146 {
147  /* Continue with shading shadow catcher surface. Same as integrator_split_shadow_catcher, but
148  * using NEXT instead of INIT. */
150  integrator_state_read_isect(kg, state, &isect);
151 
152  const int shader = intersection_get_shader(kg, &isect);
153  const int flags = kernel_data_fetch(shaders, shader).flags;
154  const int object_flags = intersection_get_object_flags(kg, &isect);
155  const bool use_caustics = kernel_data.integrator.use_caustics &&
156  (object_flags & SD_OBJECT_CAUSTICS);
157  const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE);
158 
159  if (use_caustics) {
161  kg, state, current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE, shader);
162  }
163  else if (use_raytrace_kernel) {
165  kg, state, current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader);
166  }
167  else {
169  kg, state, current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE, shader);
170  }
171 }
172 
173 /* Schedule next kernel to be executed after executing background shader for shadow catcher. */
174 template<DeviceKernel current_kernel>
175 ccl_device_forceinline void integrator_intersect_next_kernel_after_shadow_catcher_background(
177 {
178  /* Same logic as integrator_split_shadow_catcher, but using NEXT instead of INIT. */
180  /* Volume stack is not empty. Re-init the volume stack to exclude any non-shadow catcher
181  * objects from it, and then continue shading volume and shadow catcher surface after. */
184  return;
185  }
186 
187  /* Continue with shading shadow catcher surface. */
188  integrator_intersect_next_kernel_after_shadow_catcher_volume<current_kernel>(kg, state);
189 }
190 #endif
191 
192 /* Schedule next kernel to be executed after intersect closest.
193  *
194  * Note that current_kernel is a template value since making this a variable
195  * leads to poor performance with CUDA atomics. */
196 template<DeviceKernel current_kernel>
198  KernelGlobals kg,
202  const bool hit)
203 {
204  /* Continue with volume kernel if we are inside a volume, regardless if we hit anything. */
205 #ifdef __VOLUME__
207  const bool hit_surface = hit && !(isect->type & PRIMITIVE_LAMP);
208  const int shader = (hit_surface) ? intersection_get_shader(kg, isect) : SHADER_NONE;
209  const int flags = (hit_surface) ? kernel_data_fetch(shaders, shader).flags : 0;
210 
211  if (!integrator_intersect_terminate(kg, state, flags)) {
213  }
214  else {
215  integrator_path_terminate(kg, state, current_kernel);
216  }
217  return;
218  }
219 #endif
220 
221  if (hit) {
222  /* Hit a surface, continue with light or surface kernel. */
223  if (isect->type & PRIMITIVE_LAMP) {
225  }
226  else {
227  /* Hit a surface, continue with surface kernel unless terminated. */
228  const int shader = intersection_get_shader(kg, isect);
229  const int flags = kernel_data_fetch(shaders, shader).flags;
230 
231  if (!integrator_intersect_terminate(kg, state, flags)) {
232  const int object_flags = intersection_get_object_flags(kg, isect);
233  const bool use_caustics = kernel_data.integrator.use_caustics &&
234  (object_flags & SD_OBJECT_CAUSTICS);
235  const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE);
236  if (use_caustics) {
238  kg, state, current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE, shader);
239  }
240  else if (use_raytrace_kernel) {
242  kg, state, current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader);
243  }
244  else {
246  kg, state, current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE, shader);
247  }
248 
249 #ifdef __SHADOW_CATCHER__
250  /* Handle shadow catcher. */
251  integrator_split_shadow_catcher(kg, state, isect, render_buffer);
252 #endif
253  }
254  else {
255  integrator_path_terminate(kg, state, current_kernel);
256  }
257  }
258  }
259  else {
260  /* Nothing hit, continue with background kernel. */
262  }
263 }
264 
265 /* Schedule next kernel to be executed after shade volume.
266  *
267  * The logic here matches integrator_intersect_next_kernel, except that
268  * volume shading and termination testing have already been done. */
269 template<DeviceKernel current_kernel>
271  KernelGlobals kg,
275 {
276  if (isect->prim != PRIM_NONE) {
277  /* Hit a surface, continue with light or surface kernel. */
278  if (isect->type & PRIMITIVE_LAMP) {
280  return;
281  }
282  else {
283  /* Hit a surface, continue with surface kernel unless terminated. */
284  const int shader = intersection_get_shader(kg, isect);
285  const int flags = kernel_data_fetch(shaders, shader).flags;
286  const int object_flags = intersection_get_object_flags(kg, isect);
287  const bool use_caustics = kernel_data.integrator.use_caustics &&
288  (object_flags & SD_OBJECT_CAUSTICS);
289  const bool use_raytrace_kernel = (flags & SD_HAS_RAYTRACE);
290 
291  if (use_caustics) {
293  kg, state, current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE, shader);
294  }
295  else if (use_raytrace_kernel) {
297  kg, state, current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE, shader);
298  }
299  else {
301  kg, state, current_kernel, DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE, shader);
302  }
303 
304 #ifdef __SHADOW_CATCHER__
305  /* Handle shadow catcher. */
306  integrator_split_shadow_catcher(kg, state, isect, render_buffer);
307 #endif
308  return;
309  }
310  }
311  else {
312  /* Nothing hit, continue with background kernel. */
314  return;
315  }
316 }
317 
321 {
323 
324  /* Read ray from integrator state into local memory. */
326  integrator_state_read_ray(kg, state, &ray);
327  kernel_assert(ray.tmax != 0.0f);
328 
329  const uint visibility = path_state_ray_visibility(state);
330  const int last_isect_prim = INTEGRATOR_STATE(state, isect, prim);
331  const int last_isect_object = INTEGRATOR_STATE(state, isect, object);
332 
333  /* Trick to use short AO rays to approximate indirect light at the end of the path. */
334  if (path_state_ao_bounce(kg, state)) {
335  ray.tmax = kernel_data.integrator.ao_bounces_distance;
336 
337  if (last_isect_object != OBJECT_NONE) {
338  const float object_ao_distance = kernel_data_fetch(objects, last_isect_object).ao_distance;
339  if (object_ao_distance != 0.0f) {
340  ray.tmax = object_ao_distance;
341  }
342  }
343  }
344 
345  /* Scene Intersection. */
347  isect.object = OBJECT_NONE;
348  isect.prim = PRIM_NONE;
349  ray.self.object = last_isect_object;
350  ray.self.prim = last_isect_prim;
351  ray.self.light_object = OBJECT_NONE;
352  ray.self.light_prim = PRIM_NONE;
353  bool hit = scene_intersect(kg, &ray, visibility, &isect);
354 
355  /* TODO: remove this and do it in the various intersection functions instead. */
356  if (!hit) {
357  isect.prim = PRIM_NONE;
358  }
359 
360  /* Setup mnee flag to signal last intersection with a caster */
361  const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
362 
363 #ifdef __MNEE__
364  /* Path culling logic for MNEE (removes fireflies at the cost of bias) */
365  if (kernel_data.integrator.use_caustics) {
366  /* The following firefly removal mechanism works by culling light connections when
367  * a ray comes from a caustic caster directly after bouncing off a different caustic
368  * receiver */
369  bool from_caustic_caster = false;
370  bool from_caustic_receiver = false;
371  if (!(path_flag & PATH_RAY_CAMERA) && last_isect_object != OBJECT_NONE) {
372  const int object_flags = kernel_data_fetch(object_flag, last_isect_object);
373  from_caustic_receiver = (object_flags & SD_OBJECT_CAUSTICS_RECEIVER);
374  from_caustic_caster = (object_flags & SD_OBJECT_CAUSTICS_CASTER);
375  }
376 
377  bool has_receiver_ancestor = INTEGRATOR_STATE(state, path, mnee) & PATH_MNEE_RECEIVER_ANCESTOR;
379  if (from_caustic_caster && has_receiver_ancestor)
381  if (from_caustic_receiver)
383  }
384 #endif /* __MNEE__ */
385 
386  /* Light intersection for MIS. */
387  if (kernel_data.integrator.use_lamp_mis) {
388  /* NOTE: if we make lights visible to camera rays, we'll need to initialize
389  * these in the path_state_init. */
390  const int last_type = INTEGRATOR_STATE(state, isect, type);
391  hit = lights_intersect(
392  kg, state, &ray, &isect, last_isect_prim, last_isect_object, last_type, path_flag) ||
393  hit;
394  }
395 
396  /* Write intersection result into global integrator state memory. */
397  integrator_state_write_isect(kg, state, &isect);
398 
399  /* Setup up next kernel to be executed. */
400  integrator_intersect_next_kernel<DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST>(
401  kg, state, &isect, render_buffer, hit);
402 }
403 
unsigned int uint
Definition: BLI_sys_types.h:67
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#define ccl_restrict
Definition: cuda/compat.h:50
#define ccl_device_forceinline
Definition: cuda/compat.h:35
#define ccl_optional_struct_init
Definition: cuda/compat.h:53
#define ccl_device
Definition: cuda/compat.h:32
#define ccl_private
Definition: cuda/compat.h:48
#define ccl_global
Definition: cuda/compat.h:43
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
ccl_device_forceinline int intersection_get_object_flags(KernelGlobals kg, ccl_private const Intersection *ccl_restrict isect)
ccl_device_forceinline int intersection_get_shader(KernelGlobals kg, ccl_private const Intersection *ccl_restrict isect)
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
#define kernel_data_fetch(name, index)
CCL_NAMESPACE_BEGIN ccl_device_forceinline bool integrator_intersect_terminate(KernelGlobals kg, IntegratorState state, const int shader_flags)
ccl_device_forceinline void integrator_intersect_next_kernel_after_volume(KernelGlobals kg, IntegratorState state, ccl_private const Intersection *ccl_restrict isect, ccl_global float *ccl_restrict render_buffer)
ccl_device_forceinline void integrator_intersect_next_kernel(KernelGlobals kg, IntegratorState state, ccl_private const Intersection *ccl_restrict isect, ccl_global float *ccl_restrict render_buffer, const bool hit)
ccl_device void integrator_intersect_closest(KernelGlobals kg, IntegratorState state, ccl_global float *ccl_restrict render_buffer)
ccl_device_intersect bool scene_intersect(KernelGlobals kg, ccl_private const Ray *ray, const uint visibility, ccl_private Intersection *isect)
ccl_gpu_kernel_postfix ccl_global KernelWorkTile const int ccl_global float * render_buffer
const int state
ccl_device bool lights_intersect(KernelGlobals kg, IntegratorState state, ccl_private const Ray *ccl_restrict ray, ccl_private Intersection *ccl_restrict isect, const int last_prim, const int last_object, const int last_type, const uint32_t path_flag)
@ PATH_MNEE_RECEIVER_ANCESTOR
Definition: kernel/types.h:294
@ PATH_MNEE_CULL_LIGHT_CONNECTION
Definition: kernel/types.h:295
@ SD_HAS_TRANSPARENT_SHADOW
Definition: kernel/types.h:766
@ SD_HAS_EMISSION
Definition: kernel/types.h:790
@ SD_HAS_RAYTRACE
Definition: kernel/types.h:792
#define PASS_UNUSED
Definition: kernel/types.h:44
@ PRIMITIVE_LAMP
Definition: kernel/types.h:556
#define SHADER_NONE
Definition: kernel/types.h:39
@ PRNG_TERMINATE
Definition: kernel/types.h:169
#define PRIM_NONE
Definition: kernel/types.h:41
@ PATH_RAY_SHADOW_CATCHER_HIT
Definition: kernel/types.h:278
@ PATH_RAY_TERMINATE_AFTER_TRANSPARENT
Definition: kernel/types.h:245
@ PATH_RAY_TERMINATE_AFTER_VOLUME
Definition: kernel/types.h:248
@ PATH_RAY_SHADOW_CATCHER_PASS
Definition: kernel/types.h:285
@ PATH_RAY_TERMINATE_IN_NEXT_VOLUME
Definition: kernel/types.h:239
@ PATH_RAY_SHADOW_CATCHER_BACKGROUND
Definition: kernel/types.h:288
@ PATH_RAY_CAMERA
Definition: kernel/types.h:194
@ PATH_RAY_TERMINATE_ON_NEXT_SURFACE
Definition: kernel/types.h:238
#define OBJECT_NONE
Definition: kernel/types.h:40
@ SD_OBJECT_CAUSTICS
Definition: kernel/types.h:829
@ SD_OBJECT_CAUSTICS_RECEIVER
Definition: kernel/types.h:824
@ SD_OBJECT_CAUSTICS_CASTER
Definition: kernel/types.h:822
@ DEVICE_KERNEL_INTEGRATOR_SHADE_LIGHT
@ DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE
@ DEVICE_KERNEL_INTEGRATOR_INTERSECT_VOLUME_STACK
@ DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_RAYTRACE
@ DEVICE_KERNEL_INTEGRATOR_SHADE_SURFACE_MNEE
@ DEVICE_KERNEL_INTEGRATOR_SHADE_VOLUME
@ DEVICE_KERNEL_INTEGRATOR_SHADE_BACKGROUND
#define PROFILING_INIT(kg, event)
ccl_device_inline float path_state_continuation_probability(KernelGlobals kg, ConstIntegratorState state, const uint32_t path_flag)
Definition: path_state.h:231
ccl_device_inline bool path_state_ao_bounce(KernelGlobals kg, ConstIntegratorState state)
Definition: path_state.h:255
ccl_device_inline float path_state_rng_1D(KernelGlobals kg, ccl_private const RNGState *rng_state, int dimension)
Definition: path_state.h:299
ccl_device_inline void path_state_rng_load(ConstIntegratorState state, ccl_private RNGState *rng_state)
Definition: path_state.h:283
ccl_device_inline uint path_state_ray_visibility(ConstIntegratorState state)
Definition: path_state.h:210
CCL_NAMESPACE_BEGIN ccl_device_inline bool kernel_shadow_catcher_is_path_split_bounce(KernelGlobals kg, IntegratorState state, const int object_flag)
IntegratorStateCPU *ccl_restrict IntegratorState
Definition: state.h:147
#define INTEGRATOR_STATE_WRITE(state, nested_struct, member)
Definition: state.h:155
#define INTEGRATOR_STATE(state, nested_struct, member)
Definition: state.h:154
ccl_device_forceinline void integrator_path_next_sorted(KernelGlobals kg, IntegratorState state, const DeviceKernel current_kernel, const DeviceKernel next_kernel, const uint32_t key)
Definition: state_flow.h:168
ccl_device_forceinline void integrator_path_terminate(KernelGlobals kg, IntegratorState state, const DeviceKernel current_kernel)
Definition: state_flow.h:160
ccl_device_forceinline void integrator_path_next(KernelGlobals kg, IntegratorState state, const DeviceKernel current_kernel, const DeviceKernel next_kernel)
Definition: state_flow.h:151
ccl_device_forceinline void integrator_path_init_sorted(KernelGlobals kg, IntegratorState state, const DeviceKernel next_kernel, const uint32_t key)
Definition: state_flow.h:142
ccl_device_forceinline void integrator_path_init(KernelGlobals kg, IntegratorState state, const DeviceKernel next_kernel)
Definition: state_flow.h:135
ccl_device_forceinline void integrator_state_write_isect(KernelGlobals kg, IntegratorState state, ccl_private const Intersection *ccl_restrict isect)
Definition: state_util.h:68
ccl_device_forceinline void integrator_state_read_ray(KernelGlobals kg, ConstIntegratorState state, ccl_private Ray *ccl_restrict ray)
Definition: state_util.h:27
ccl_device_forceinline bool integrator_state_volume_stack_is_empty(KernelGlobals kg, ConstIntegratorState state)
Definition: state_util.h:106
ccl_device_inline IntegratorState integrator_state_shadow_catcher_split(KernelGlobals kg, IntegratorState state)
Definition: state_util.h:320
ccl_device_forceinline void integrator_state_read_isect(KernelGlobals kg, ConstIntegratorState state, ccl_private Intersection *ccl_restrict isect)
Definition: state_util.h:79
unsigned int uint32_t
Definition: stdint.h:80
@ PROFILING_INTERSECT_CLOSEST