Blender  V3.3
intersect_volume_stack.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 
6 #include "kernel/bvh/bvh.h"
7 #include "kernel/geom/geom.h"
10 
12 
15  const float3 from_P,
16  const float3 to_P)
17 {
19 
20  ShaderDataTinyStorage stack_sd_storage;
21  ccl_private ShaderData *stack_sd = AS_SHADER_DATA(&stack_sd_storage);
22 
23  kernel_assert(kernel_data.integrator.use_volumes);
24 
25  Ray volume_ray ccl_optional_struct_init;
26  volume_ray.P = from_P;
27  volume_ray.D = normalize_len(to_P - from_P, &volume_ray.tmax);
28  volume_ray.tmin = 0.0f;
29  volume_ray.self.object = INTEGRATOR_STATE(state, isect, object);
30  volume_ray.self.prim = INTEGRATOR_STATE(state, isect, prim);
31  volume_ray.self.light_object = OBJECT_NONE;
32  volume_ray.self.light_prim = PRIM_NONE;
33  /* Store to avoid global fetches on every intersection step. */
34  const uint volume_stack_size = kernel_data.volume_stack_size;
35 
36  const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
38 
39 #ifdef __VOLUME_RECORD_ALL__
40  Intersection hits[2 * MAX_VOLUME_STACK_SIZE + 1];
41  uint num_hits = scene_intersect_volume(kg, &volume_ray, hits, 2 * volume_stack_size, visibility);
42  if (num_hits > 0) {
43  Intersection *isect = hits;
44 
45  qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
46 
47  for (uint hit = 0; hit < num_hits; ++hit, ++isect) {
48  /* Ignore self, SSS itself already enters and exits the object. */
49  if (isect->object == volume_ray.self.object) {
50  continue;
51  }
52  shader_setup_from_ray(kg, stack_sd, &volume_ray, isect);
53  volume_stack_enter_exit(kg, state, stack_sd);
54  }
55  }
56 #else
57  Intersection isect;
58  int step = 0;
59  while (step < 2 * volume_stack_size &&
60  scene_intersect_volume(kg, &volume_ray, &isect, visibility)) {
61  /* Ignore self, SSS itself already enters and exits the object. */
62  if (isect.object != volume_ray.self.object) {
63  shader_setup_from_ray(kg, stack_sd, &volume_ray, &isect);
64  volume_stack_enter_exit(kg, state, stack_sd);
65  }
66  /* Move ray forward. */
67  volume_ray.tmin = intersection_t_offset(isect.t);
68  volume_ray.self.object = isect.object;
69  volume_ray.self.prim = isect.prim;
70  ++step;
71  }
72 #endif
73 }
74 
76 {
78 
79  ShaderDataTinyStorage stack_sd_storage;
80  ccl_private ShaderData *stack_sd = AS_SHADER_DATA(&stack_sd_storage);
81 
82  Ray volume_ray ccl_optional_struct_init;
83  integrator_state_read_ray(kg, state, &volume_ray);
84 
85  /* Trace ray in random direction. Any direction works, Z up is a guess to get the
86  * fewest hits. */
87  volume_ray.D = make_float3(0.0f, 0.0f, 1.0f);
88  volume_ray.tmin = 0.0f;
89  volume_ray.tmax = FLT_MAX;
90  volume_ray.self.object = OBJECT_NONE;
91  volume_ray.self.prim = PRIM_NONE;
92  volume_ray.self.light_object = OBJECT_NONE;
93  volume_ray.self.light_prim = PRIM_NONE;
94 
95  int stack_index = 0, enclosed_index = 0;
96 
97  const uint32_t path_flag = INTEGRATOR_STATE(state, path, flag);
98  const uint32_t visibility = SHADOW_CATCHER_PATH_VISIBILITY(path_flag, PATH_RAY_CAMERA);
99 
100  /* Initialize volume stack with background volume For shadow catcher the
101  * background volume is always assumed to be CG. */
102  if (kernel_data.background.volume_shader != SHADER_NONE) {
103  if (!(path_flag & PATH_RAY_SHADOW_CATCHER_PASS)) {
104  INTEGRATOR_STATE_ARRAY_WRITE(state, volume_stack, stack_index, object) = OBJECT_NONE;
106  state, volume_stack, stack_index, shader) = kernel_data.background.volume_shader;
107  stack_index++;
108  }
109  }
110 
111  /* Store to avoid global fetches on every intersection step. */
112  const uint volume_stack_size = kernel_data.volume_stack_size;
113 
114 #ifdef __VOLUME_RECORD_ALL__
115  Intersection hits[2 * MAX_VOLUME_STACK_SIZE + 1];
116  uint num_hits = scene_intersect_volume(kg, &volume_ray, hits, 2 * volume_stack_size, visibility);
117  if (num_hits > 0) {
118  int enclosed_volumes[MAX_VOLUME_STACK_SIZE];
119  Intersection *isect = hits;
120 
121  qsort(hits, num_hits, sizeof(Intersection), intersections_compare);
122 
123  for (uint hit = 0; hit < num_hits; ++hit, ++isect) {
124  shader_setup_from_ray(kg, stack_sd, &volume_ray, isect);
125  if (stack_sd->flag & SD_BACKFACING) {
126  bool need_add = true;
127  for (int i = 0; i < enclosed_index && need_add; ++i) {
128  /* If ray exited the volume and never entered to that volume
129  * it means that camera is inside such a volume.
130  */
131  if (enclosed_volumes[i] == stack_sd->object) {
132  need_add = false;
133  }
134  }
135  for (int i = 0; i < stack_index && need_add; ++i) {
136  /* Don't add intersections twice. */
138  if (entry.object == stack_sd->object) {
139  need_add = false;
140  break;
141  }
142  }
143  if (need_add && stack_index < volume_stack_size - 1) {
144  const VolumeStack new_entry = {stack_sd->object, stack_sd->shader};
145  integrator_state_write_volume_stack(state, stack_index, new_entry);
146  ++stack_index;
147  }
148  }
149  else {
150  /* If ray from camera enters the volume, this volume shouldn't
151  * be added to the stack on exit.
152  */
153  enclosed_volumes[enclosed_index++] = stack_sd->object;
154  }
155  }
156  }
157 #else
158  /* CUDA does not support definition of a variable size arrays, so use the maximum possible. */
159  int enclosed_volumes[MAX_VOLUME_STACK_SIZE];
160  int step = 0;
161 
162  while (stack_index < volume_stack_size - 1 && enclosed_index < MAX_VOLUME_STACK_SIZE - 1 &&
163  step < 2 * volume_stack_size) {
164  Intersection isect;
165  if (!scene_intersect_volume(kg, &volume_ray, &isect, visibility)) {
166  break;
167  }
168 
169  shader_setup_from_ray(kg, stack_sd, &volume_ray, &isect);
170  if (stack_sd->flag & SD_BACKFACING) {
171  /* If ray exited the volume and never entered to that volume
172  * it means that camera is inside such a volume.
173  */
174  bool need_add = true;
175  for (int i = 0; i < enclosed_index && need_add; ++i) {
176  /* If ray exited the volume and never entered to that volume
177  * it means that camera is inside such a volume.
178  */
179  if (enclosed_volumes[i] == stack_sd->object) {
180  need_add = false;
181  }
182  }
183  for (int i = 0; i < stack_index && need_add; ++i) {
184  /* Don't add intersections twice. */
186  if (entry.object == stack_sd->object) {
187  need_add = false;
188  break;
189  }
190  }
191  if (need_add) {
192  const VolumeStack new_entry = {stack_sd->object, stack_sd->shader};
193  integrator_state_write_volume_stack(state, stack_index, new_entry);
194  ++stack_index;
195  }
196  }
197  else {
198  /* If ray from camera enters the volume, this volume shouldn't
199  * be added to the stack on exit.
200  */
201  enclosed_volumes[enclosed_index++] = stack_sd->object;
202  }
203 
204  /* Move ray forward. */
205  volume_ray.tmin = intersection_t_offset(isect.t);
206  volume_ray.self.object = isect.object;
207  volume_ray.self.prim = isect.prim;
208  ++step;
209  }
210 #endif
211 
212  /* Write terminator. */
213  const VolumeStack new_entry = {OBJECT_NONE, SHADER_NONE};
214  integrator_state_write_volume_stack(state, stack_index, new_entry);
215 }
216 
218 {
220 
222  /* Volume stack re-init for shadow catcher, continue with shading of hit. */
223  integrator_intersect_next_kernel_after_shadow_catcher_volume<
225  }
226  else {
227  /* Volume stack init for camera rays, continue with intersection of camera ray. */
229  state,
232  }
233 }
234 
unsigned int uint
Definition: BLI_sys_types.h:67
#define kernel_assert(cond)
Definition: cpu/compat.h:34
#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_NAMESPACE_END
Definition: cuda/compat.h:9
ccl_device_forceinline float intersection_t_offset(const float t)
ccl_device int intersections_compare(const void *a, const void *b)
#define kernel_data
const KernelGlobalsCPU *ccl_restrict KernelGlobals
ccl_device void integrator_intersect_volume_stack(KernelGlobals kg, IntegratorState state)
CCL_NAMESPACE_BEGIN ccl_device void integrator_volume_stack_update_for_subsurface(KernelGlobals kg, IntegratorState state, const float3 from_P, const float3 to_P)
ccl_device void integrator_volume_stack_init(KernelGlobals kg, IntegratorState state)
const int state
#define MAX_VOLUME_STACK_SIZE
Definition: kernel/types.h:692
@ SD_BACKFACING
Definition: kernel/types.h:738
#define AS_SHADER_DATA(shader_data_tiny_storage)
Definition: kernel/types.h:943
#define SHADER_NONE
Definition: kernel/types.h:39
#define PRIM_NONE
Definition: kernel/types.h:41
@ PATH_RAY_SHADOW_CATCHER_PASS
Definition: kernel/types.h:285
@ PATH_RAY_ALL_VISIBILITY
Definition: kernel/types.h:217
@ PATH_RAY_CAMERA
Definition: kernel/types.h:194
#define OBJECT_NONE
Definition: kernel/types.h:40
ShaderDataTinyStorage
Definition: kernel/types.h:933
ShaderData
Definition: kernel/types.h:925
#define SHADOW_CATCHER_PATH_VISIBILITY(path_flag, visibility)
Definition: kernel/types.h:306
@ DEVICE_KERNEL_INTEGRATOR_INTERSECT_VOLUME_STACK
@ DEVICE_KERNEL_INTEGRATOR_INTERSECT_CLOSEST
#define PROFILING_INIT(kg, event)
ccl_device_inline float2 normalize_len(const float2 &a, float *t)
#define make_float3(x, y, z)
Definition: metal/compat.h:204
CCL_NAMESPACE_BEGIN ccl_device_inline void shader_setup_from_ray(KernelGlobals kg, ccl_private ShaderData *ccl_restrict sd, ccl_private const Ray *ccl_restrict ray, ccl_private const Intersection *ccl_restrict isect)
Definition: shader_data.h:28
#define INTEGRATOR_STATE_ARRAY_WRITE(state, nested_struct, array_index, member)
Definition: state.h:159
IntegratorStateCPU *ccl_restrict IntegratorState
Definition: state.h:147
#define INTEGRATOR_STATE(state, nested_struct, member)
Definition: state.h:154
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 VolumeStack integrator_state_read_volume_stack(ConstIntegratorState state, int i)
Definition: state_util.h:90
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 void integrator_state_write_volume_stack(IntegratorState state, int i, VolumeStack entry)
Definition: state_util.h:98
unsigned int uint32_t
Definition: stdint.h:80
@ PROFILING_INTERSECT_VOLUME_STACK
ccl_device void volume_stack_enter_exit(KernelGlobals kg, ccl_private const ShaderData *sd, StackReadOp stack_read, StackWriteOp stack_write)
Definition: volume_stack.h:22