Blender  V3.3
intersect_shadow.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 
8 /* Visibility for the shadow ray. */
11 {
12  uint visibility = PATH_RAY_SHADOW;
13 
14 #ifdef __SHADOW_CATCHER__
15  const uint32_t path_flag = INTEGRATOR_STATE(state, shadow_path, flag);
16  visibility = SHADOW_CATCHER_PATH_VISIBILITY(path_flag, visibility);
17 #endif
18 
19  return visibility;
20 }
21 
24  ccl_private const Ray *ray,
25  const uint visibility)
26 {
27  /* Mask which will pick only opaque visibility bits from the `visibility`.
28  * Calculate the mask at compile time: the visibility will either be a high bits for the shadow
29  * catcher objects, or lower bits for the regular objects (there is no need to check the path
30  * state here again). */
31  constexpr const uint opaque_mask = SHADOW_CATCHER_VISIBILITY_SHIFT(PATH_RAY_SHADOW_OPAQUE) |
33 
34  Intersection isect;
35  const bool opaque_hit = scene_intersect(kg, ray, visibility & opaque_mask, &isect);
36 
37  if (!opaque_hit) {
38  INTEGRATOR_STATE_WRITE(state, shadow_path, num_hits) = 0;
39  }
40 
41  return opaque_hit;
42 }
43 
46 {
47  const int transparent_max_bounce = kernel_data.integrator.transparent_max_bounce;
48  const int transparent_bounce = INTEGRATOR_STATE(state, shadow_path, transparent_bounce);
49 
50  return max(transparent_max_bounce - transparent_bounce - 1, 0);
51 }
52 
53 #ifdef __TRANSPARENT_SHADOWS__
54 # ifndef __KERNEL_GPU__
55 ccl_device int shadow_intersections_compare(const void *a, const void *b)
56 {
57  const Intersection *isect_a = (const Intersection *)a;
58  const Intersection *isect_b = (const Intersection *)b;
59 
60  if (isect_a->t < isect_b->t)
61  return -1;
62  else if (isect_a->t > isect_b->t)
63  return 1;
64  else
65  return 0;
66 }
67 # endif
68 
69 ccl_device_inline void sort_shadow_intersections(IntegratorShadowState state, uint num_hits)
70 {
71  kernel_assert(num_hits > 0);
72 
73 # ifdef __KERNEL_GPU__
74  /* Use bubble sort which has more friendly memory pattern on GPU. */
75  bool swapped;
76  do {
77  swapped = false;
78  for (int j = 0; j < num_hits - 1; ++j) {
79  if (INTEGRATOR_STATE_ARRAY(state, shadow_isect, j, t) >
80  INTEGRATOR_STATE_ARRAY(state, shadow_isect, j + 1, t)) {
84  integrator_state_read_shadow_isect(state, &tmp_j_1, j + 1);
87  swapped = true;
88  }
89  }
90  --num_hits;
91  } while (swapped);
92 # else
93  Intersection *isect_array = (Intersection *)state->shadow_isect;
94  qsort(isect_array, num_hits, sizeof(Intersection), shadow_intersections_compare);
95 # endif
96 }
97 
98 ccl_device bool integrate_intersect_shadow_transparent(KernelGlobals kg,
100  ccl_private const Ray *ray,
101  const uint visibility)
102 {
103  /* Limit the number hits to the max transparent bounces allowed and the size that we
104  * have available in the integrator state. */
105  const uint max_hits = integrate_shadow_max_transparent_hits(kg, state);
106  uint num_hits = 0;
107  float throughput = 1.0f;
108  bool opaque_hit = scene_intersect_shadow_all(
109  kg, state, ray, visibility, max_hits, &num_hits, &throughput);
110 
111  /* Computed throughput from baked shadow transparency, where we can bypass recording
112  * intersections and shader evaluation. */
113  if (throughput != 1.0f) {
114  INTEGRATOR_STATE_WRITE(state, shadow_path, throughput) *= throughput;
115  }
116 
117  /* If number of hits exceed the transparent bounces limit, make opaque. */
118  if (num_hits > max_hits) {
119  opaque_hit = true;
120  }
121 
122  if (!opaque_hit) {
123  const uint num_recorded_hits = min(num_hits, min(max_hits, INTEGRATOR_SHADOW_ISECT_SIZE));
124 
125  if (num_recorded_hits > 0) {
126  sort_shadow_intersections(state, num_recorded_hits);
127  }
128 
129  INTEGRATOR_STATE_WRITE(state, shadow_path, num_hits) = num_hits;
130  }
131  else {
132  INTEGRATOR_STATE_WRITE(state, shadow_path, num_hits) = 0;
133  }
134 
135  return opaque_hit;
136 }
137 #endif
138 
140 {
142 
143  /* Read ray from integrator state into local memory. */
146  ray.self.object = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, object);
147  ray.self.prim = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 0, prim);
148  ray.self.light_object = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 1, object);
149  ray.self.light_prim = INTEGRATOR_STATE_ARRAY(state, shadow_isect, 1, prim);
150  /* Compute visibility. */
151  const uint visibility = integrate_intersect_shadow_visibility(kg, state);
152 
153 #ifdef __TRANSPARENT_SHADOWS__
154  /* TODO: compile different kernels depending on this? Especially for OptiX
155  * conditional trace calls are bad. */
156  const bool opaque_hit = (kernel_data.integrator.transparent_shadows) ?
157  integrate_intersect_shadow_transparent(kg, state, &ray, visibility) :
158  integrate_intersect_shadow_opaque(kg, state, &ray, visibility);
159 #else
160  const bool opaque_hit = integrate_intersect_shadow_opaque(kg, state, &ray, visibility);
161 #endif
162 
163  if (opaque_hit) {
164  /* Hit an opaque surface, shadow path ends here. */
166  return;
167  }
168  else {
169  /* Hit nothing or transparent surfaces, continue to shadow kernel
170  * for shading and render buffer output.
171  *
172  * TODO: could also write to render buffer directly if no transparent shadows?
173  * Could save a kernel execution for the common case. */
175  state,
178  return;
179  }
180 }
181 
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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#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_device_inline
Definition: cuda/compat.h:34
#define CCL_NAMESPACE_END
Definition: cuda/compat.h:9
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
ccl_device_forceinline int integrate_shadow_max_transparent_hits(KernelGlobals kg, ConstIntegratorShadowState state)
ccl_device void integrator_intersect_shadow(KernelGlobals kg, IntegratorShadowState state)
CCL_NAMESPACE_BEGIN ccl_device_forceinline uint integrate_intersect_shadow_visibility(KernelGlobals kg, ConstIntegratorShadowState state)
ccl_device bool integrate_intersect_shadow_opaque(KernelGlobals kg, IntegratorShadowState state, ccl_private const Ray *ray, const uint visibility)
ccl_device_intersect bool scene_intersect(KernelGlobals kg, ccl_private const Ray *ray, const uint visibility, ccl_private Intersection *isect)
const int state
#define SHADOW_CATCHER_VISIBILITY_SHIFT(visibility)
Definition: kernel/types.h:304
@ PATH_RAY_SHADOW
Definition: kernel/types.h:206
@ PATH_RAY_SHADOW_OPAQUE
Definition: kernel/types.h:204
#define INTEGRATOR_SHADOW_ISECT_SIZE
Definition: kernel/types.h:53
#define SHADOW_CATCHER_PATH_VISIBILITY(path_flag, visibility)
Definition: kernel/types.h:306
@ DEVICE_KERNEL_INTEGRATOR_SHADE_SHADOW
@ DEVICE_KERNEL_INTEGRATOR_INTERSECT_SHADOW
#define PROFILING_INIT(kg, event)
static unsigned a[3]
Definition: RandGen.cpp:78
static const pxr::TfToken b("b", pxr::TfToken::Immortal)
#define min(a, b)
Definition: sort.c:35
const IntegratorShadowStateCPU *ccl_restrict ConstIntegratorShadowState
Definition: state.h:150
#define INTEGRATOR_STATE_WRITE(state, nested_struct, member)
Definition: state.h:155
#define INTEGRATOR_STATE(state, nested_struct, member)
Definition: state.h:154
IntegratorShadowStateCPU *ccl_restrict IntegratorShadowState
Definition: state.h:149
#define INTEGRATOR_STATE_ARRAY(state, nested_struct, array_index, member)
Definition: state.h:157
ccl_device_forceinline void integrator_shadow_path_terminate(KernelGlobals kg, IntegratorShadowState state, const DeviceKernel current_kernel)
Definition: state_flow.h:196
ccl_device_forceinline void integrator_shadow_path_next(KernelGlobals kg, IntegratorShadowState state, const DeviceKernel current_kernel, const DeviceKernel next_kernel)
Definition: state_flow.h:187
ccl_device_forceinline void integrator_state_write_shadow_isect(IntegratorShadowState state, ccl_private const Intersection *ccl_restrict isect, const int index)
Definition: state_util.h:116
ccl_device_forceinline void integrator_state_read_shadow_ray(KernelGlobals kg, ConstIntegratorShadowState state, ccl_private Ray *ccl_restrict ray)
Definition: state_util.h:53
ccl_device_forceinline void integrator_state_read_shadow_isect(ConstIntegratorShadowState state, ccl_private Intersection *ccl_restrict isect, const int index)
Definition: state_util.h:129
unsigned int uint32_t
Definition: stdint.h:80
float max
@ PROFILING_INTERSECT_SHADOW